mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-16 03:59:56 +00:00
Use the right deserializer for unloaded scripts
This commit is contained in:
parent
32a6ed6f49
commit
6572122acc
3 changed files with 100 additions and 8 deletions
|
@ -161,6 +161,29 @@ return {
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
)X");
|
||||||
|
|
||||||
|
constexpr VFS::Path::NormalizedView customDataPath("customdata.lua");
|
||||||
|
|
||||||
|
VFSTestFile customDataScript(R"X(
|
||||||
|
data = nil
|
||||||
|
return {
|
||||||
|
engineHandlers = {
|
||||||
|
onSave = function()
|
||||||
|
return data
|
||||||
|
end,
|
||||||
|
onLoad = function(state)
|
||||||
|
data = state
|
||||||
|
end,
|
||||||
|
onInit = function(state)
|
||||||
|
data = state
|
||||||
|
end
|
||||||
|
},
|
||||||
|
eventHandlers = {
|
||||||
|
WakeUp = function()
|
||||||
|
end
|
||||||
|
}
|
||||||
|
}
|
||||||
)X");
|
)X");
|
||||||
|
|
||||||
struct LuaScriptsContainerTest : Test
|
struct LuaScriptsContainerTest : Test
|
||||||
|
@ -178,6 +201,7 @@ return {
|
||||||
{ overrideInterfacePath, &overrideInterfaceScript },
|
{ overrideInterfacePath, &overrideInterfaceScript },
|
||||||
{ useInterfacePath, &useInterfaceScript },
|
{ useInterfacePath, &useInterfaceScript },
|
||||||
{ unloadPath, &unloadScript },
|
{ unloadPath, &unloadScript },
|
||||||
|
{ customDataPath, &customDataScript },
|
||||||
});
|
});
|
||||||
|
|
||||||
LuaUtil::ScriptsConfiguration mCfg;
|
LuaUtil::ScriptsConfiguration mCfg;
|
||||||
|
@ -199,6 +223,7 @@ CUSTOM, PLAYER: testInterface.lua
|
||||||
CUSTOM, PLAYER: overrideInterface.lua
|
CUSTOM, PLAYER: overrideInterface.lua
|
||||||
CUSTOM, PLAYER: useInterface.lua
|
CUSTOM, PLAYER: useInterface.lua
|
||||||
CUSTOM: unload.lua
|
CUSTOM: unload.lua
|
||||||
|
CUSTOM: customdata.lua
|
||||||
)X");
|
)X");
|
||||||
mCfg.init(std::move(cfg));
|
mCfg.init(std::move(cfg));
|
||||||
}
|
}
|
||||||
|
@ -570,4 +595,58 @@ CUSTOM: unload.lua
|
||||||
scripts1.load(data);
|
scripts1.load(data);
|
||||||
EXPECT_EQ(tracker.size(), 0);
|
EXPECT_EQ(tracker.size(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(LuaScriptsContainerTest, LoadOrderChange)
|
||||||
|
{
|
||||||
|
LuaUtil::ScriptTracker tracker;
|
||||||
|
LuaUtil::ScriptsContainer scripts1(&mLua, "Test", &tracker, false);
|
||||||
|
LuaUtil::BasicSerializer serializer1;
|
||||||
|
LuaUtil::BasicSerializer serializer2([](int contentFileIndex) -> int {
|
||||||
|
if (contentFileIndex == 12)
|
||||||
|
return 34;
|
||||||
|
else if (contentFileIndex == 37)
|
||||||
|
return 12;
|
||||||
|
return contentFileIndex;
|
||||||
|
});
|
||||||
|
scripts1.setSerializer(&serializer1);
|
||||||
|
scripts1.setSavedDataDeserializer(&serializer2);
|
||||||
|
|
||||||
|
mLua.protectedCall([&](LuaUtil::LuaView& lua) {
|
||||||
|
sol::object id1 = sol::make_object_userdata(lua.sol(), ESM::RefNum{ 42, 12 });
|
||||||
|
sol::object id2 = sol::make_object_userdata(lua.sol(), ESM::RefNum{ 13, 37 });
|
||||||
|
sol::table table = lua.newTable();
|
||||||
|
table[id1] = id2;
|
||||||
|
LuaUtil::BinaryData serialized = LuaUtil::serialize(table, &serializer1);
|
||||||
|
|
||||||
|
EXPECT_TRUE(scripts1.addCustomScript(*mCfg.findId(customDataPath), serialized));
|
||||||
|
EXPECT_EQ(tracker.size(), 1);
|
||||||
|
for (int i = 0; i < 600; ++i)
|
||||||
|
tracker.unloadInactiveScripts(lua);
|
||||||
|
EXPECT_EQ(tracker.size(), 0);
|
||||||
|
scripts1.receiveEvent("WakeUp", {});
|
||||||
|
EXPECT_EQ(tracker.size(), 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
ESM::LuaScripts data1;
|
||||||
|
ESM::LuaScripts data2;
|
||||||
|
scripts1.save(data1);
|
||||||
|
scripts1.load(data1);
|
||||||
|
scripts1.save(data2);
|
||||||
|
EXPECT_NE(data1.mScripts[0].mData, data2.mScripts[0].mData);
|
||||||
|
|
||||||
|
mLua.protectedCall([&](LuaUtil::LuaView& lua) {
|
||||||
|
sol::object deserialized = LuaUtil::deserialize(lua.sol(), data2.mScripts[0].mData, &serializer1);
|
||||||
|
EXPECT_TRUE(deserialized.is<sol::table>());
|
||||||
|
sol::table table = deserialized;
|
||||||
|
for (const auto& [key, value] : table)
|
||||||
|
{
|
||||||
|
EXPECT_TRUE(key.is<ESM::RefNum>());
|
||||||
|
EXPECT_TRUE(value.is<ESM::RefNum>());
|
||||||
|
EXPECT_EQ(key.as<ESM::RefNum>(), (ESM::RefNum{ 42, 34 }));
|
||||||
|
EXPECT_EQ(value.as<ESM::RefNum>(), (ESM::RefNum{ 13, 12 }));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
EXPECT_FALSE(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -569,7 +569,6 @@ namespace MWLua
|
||||||
scripts->addPackage(name, package);
|
scripts->addPackage(name, package);
|
||||||
}
|
}
|
||||||
scripts->setSerializer(mLocalSerializer.get());
|
scripts->setSerializer(mLocalSerializer.get());
|
||||||
scripts->setSavedDataDeserializer(mLocalLoader.get());
|
|
||||||
|
|
||||||
MWWorld::RefData& refData = ptr.getRefData();
|
MWWorld::RefData& refData = ptr.getRefData();
|
||||||
refData.setLuaScripts(std::move(scripts));
|
refData.setLuaScripts(std::move(scripts));
|
||||||
|
|
|
@ -485,19 +485,34 @@ namespace LuaUtil
|
||||||
if (scriptInfo.mSavedData == nullptr)
|
if (scriptInfo.mSavedData == nullptr)
|
||||||
continue;
|
continue;
|
||||||
ESM::LuaScript& script = container.mScripts.emplace_back(*scriptInfo.mSavedData);
|
ESM::LuaScript& script = container.mScripts.emplace_back(*scriptInfo.mSavedData);
|
||||||
for (ESM::LuaTimer& savedTimer : script.mTimers)
|
if (!script.mData.empty())
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
sol::object arg = deserialize(view.sol(), savedTimer.mCallbackArgument, mSavedDataDeserializer);
|
sol::object state = deserialize(view.sol(), script.mData, mSavedDataDeserializer);
|
||||||
|
script.mData = serialize(state, mSerializer);
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
printError(scriptId, "onLoad failed", e);
|
||||||
|
script.mData.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto it = script.mTimers.begin(); it != script.mTimers.end();)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
sol::object arg = deserialize(view.sol(), it->mCallbackArgument, mSavedDataDeserializer);
|
||||||
// It is important if the order of content files was changed. The deserialize-serialize
|
// It is important if the order of content files was changed. The deserialize-serialize
|
||||||
// procedure updates refnums, so timer.mSerializedArg may be not equal to
|
// procedure updates refnums, so timer.mSerializedArg may be not equal to
|
||||||
// savedTimer.mCallbackArgument.
|
// savedTimer.mCallbackArgument.
|
||||||
savedTimer.mCallbackArgument = serialize(arg, mSerializer);
|
it->mCallbackArgument = serialize(arg, mSerializer);
|
||||||
|
++it;
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
printError(scriptId, "can not load timer", e);
|
printError(scriptId, "can not load timer", e);
|
||||||
|
it = script.mTimers.erase(it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -547,8 +562,7 @@ namespace LuaUtil
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
sol::object state
|
sol::object state = deserialize(view.sol(), scriptInfo.mSavedData->mData, mSerializer);
|
||||||
= deserialize(view.sol(), scriptInfo.mSavedData->mData, mSavedDataDeserializer);
|
|
||||||
sol::object initializationData = deserialize(view.sol(), scriptInfo.mInitData, mSerializer);
|
sol::object initializationData = deserialize(view.sol(), scriptInfo.mInitData, mSerializer);
|
||||||
LuaUtil::call({ this, scriptId }, *onLoad, state, initializationData);
|
LuaUtil::call({ this, scriptId }, *onLoad, state, initializationData);
|
||||||
}
|
}
|
||||||
|
@ -567,8 +581,8 @@ namespace LuaUtil
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
timer.mArg = sol::main_object(
|
timer.mArg
|
||||||
deserialize(view.sol(), savedTimer.mCallbackArgument, mSavedDataDeserializer));
|
= sol::main_object(deserialize(view.sol(), savedTimer.mCallbackArgument, mSerializer));
|
||||||
// It is important if the order of content files was changed. The deserialize-serialize
|
// It is important if the order of content files was changed. The deserialize-serialize
|
||||||
// procedure updates refnums, so timer.mSerializedArg may be not equal to
|
// procedure updates refnums, so timer.mSerializedArg may be not equal to
|
||||||
// savedTimer.mCallbackArgument.
|
// savedTimer.mCallbackArgument.
|
||||||
|
|
Loading…
Reference in a new issue