Skip to content

Commit 6572122

Browse files
committed
Use the right deserializer for unloaded scripts
1 parent 32a6ed6 commit 6572122

File tree

3 files changed

+100
-8
lines changed

3 files changed

+100
-8
lines changed

apps/components_tests/lua/test_scriptscontainer.cpp

+79
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,29 @@ return {
161161
end
162162
}
163163
}
164+
)X");
165+
166+
constexpr VFS::Path::NormalizedView customDataPath("customdata.lua");
167+
168+
VFSTestFile customDataScript(R"X(
169+
data = nil
170+
return {
171+
engineHandlers = {
172+
onSave = function()
173+
return data
174+
end,
175+
onLoad = function(state)
176+
data = state
177+
end,
178+
onInit = function(state)
179+
data = state
180+
end
181+
},
182+
eventHandlers = {
183+
WakeUp = function()
184+
end
185+
}
186+
}
164187
)X");
165188

166189
struct LuaScriptsContainerTest : Test
@@ -178,6 +201,7 @@ return {
178201
{ overrideInterfacePath, &overrideInterfaceScript },
179202
{ useInterfacePath, &useInterfaceScript },
180203
{ unloadPath, &unloadScript },
204+
{ customDataPath, &customDataScript },
181205
});
182206

183207
LuaUtil::ScriptsConfiguration mCfg;
@@ -199,6 +223,7 @@ CUSTOM, PLAYER: testInterface.lua
199223
CUSTOM, PLAYER: overrideInterface.lua
200224
CUSTOM, PLAYER: useInterface.lua
201225
CUSTOM: unload.lua
226+
CUSTOM: customdata.lua
202227
)X");
203228
mCfg.init(std::move(cfg));
204229
}
@@ -570,4 +595,58 @@ CUSTOM: unload.lua
570595
scripts1.load(data);
571596
EXPECT_EQ(tracker.size(), 0);
572597
}
598+
599+
TEST_F(LuaScriptsContainerTest, LoadOrderChange)
600+
{
601+
LuaUtil::ScriptTracker tracker;
602+
LuaUtil::ScriptsContainer scripts1(&mLua, "Test", &tracker, false);
603+
LuaUtil::BasicSerializer serializer1;
604+
LuaUtil::BasicSerializer serializer2([](int contentFileIndex) -> int {
605+
if (contentFileIndex == 12)
606+
return 34;
607+
else if (contentFileIndex == 37)
608+
return 12;
609+
return contentFileIndex;
610+
});
611+
scripts1.setSerializer(&serializer1);
612+
scripts1.setSavedDataDeserializer(&serializer2);
613+
614+
mLua.protectedCall([&](LuaUtil::LuaView& lua) {
615+
sol::object id1 = sol::make_object_userdata(lua.sol(), ESM::RefNum{ 42, 12 });
616+
sol::object id2 = sol::make_object_userdata(lua.sol(), ESM::RefNum{ 13, 37 });
617+
sol::table table = lua.newTable();
618+
table[id1] = id2;
619+
LuaUtil::BinaryData serialized = LuaUtil::serialize(table, &serializer1);
620+
621+
EXPECT_TRUE(scripts1.addCustomScript(*mCfg.findId(customDataPath), serialized));
622+
EXPECT_EQ(tracker.size(), 1);
623+
for (int i = 0; i < 600; ++i)
624+
tracker.unloadInactiveScripts(lua);
625+
EXPECT_EQ(tracker.size(), 0);
626+
scripts1.receiveEvent("WakeUp", {});
627+
EXPECT_EQ(tracker.size(), 1);
628+
});
629+
630+
ESM::LuaScripts data1;
631+
ESM::LuaScripts data2;
632+
scripts1.save(data1);
633+
scripts1.load(data1);
634+
scripts1.save(data2);
635+
EXPECT_NE(data1.mScripts[0].mData, data2.mScripts[0].mData);
636+
637+
mLua.protectedCall([&](LuaUtil::LuaView& lua) {
638+
sol::object deserialized = LuaUtil::deserialize(lua.sol(), data2.mScripts[0].mData, &serializer1);
639+
EXPECT_TRUE(deserialized.is<sol::table>());
640+
sol::table table = deserialized;
641+
for (const auto& [key, value] : table)
642+
{
643+
EXPECT_TRUE(key.is<ESM::RefNum>());
644+
EXPECT_TRUE(value.is<ESM::RefNum>());
645+
EXPECT_EQ(key.as<ESM::RefNum>(), (ESM::RefNum{ 42, 34 }));
646+
EXPECT_EQ(value.as<ESM::RefNum>(), (ESM::RefNum{ 13, 12 }));
647+
return;
648+
}
649+
EXPECT_FALSE(true);
650+
});
651+
}
573652
}

apps/openmw/mwlua/luamanagerimp.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,6 @@ namespace MWLua
569569
scripts->addPackage(name, package);
570570
}
571571
scripts->setSerializer(mLocalSerializer.get());
572-
scripts->setSavedDataDeserializer(mLocalLoader.get());
573572

574573
MWWorld::RefData& refData = ptr.getRefData();
575574
refData.setLuaScripts(std::move(scripts));

components/lua/scriptscontainer.cpp

+21-7
Original file line numberDiff line numberDiff line change
@@ -485,19 +485,34 @@ namespace LuaUtil
485485
if (scriptInfo.mSavedData == nullptr)
486486
continue;
487487
ESM::LuaScript& script = container.mScripts.emplace_back(*scriptInfo.mSavedData);
488-
for (ESM::LuaTimer& savedTimer : script.mTimers)
488+
if (!script.mData.empty())
489489
{
490490
try
491491
{
492-
sol::object arg = deserialize(view.sol(), savedTimer.mCallbackArgument, mSavedDataDeserializer);
492+
sol::object state = deserialize(view.sol(), script.mData, mSavedDataDeserializer);
493+
script.mData = serialize(state, mSerializer);
494+
}
495+
catch (std::exception& e)
496+
{
497+
printError(scriptId, "onLoad failed", e);
498+
script.mData.clear();
499+
}
500+
}
501+
for (auto it = script.mTimers.begin(); it != script.mTimers.end();)
502+
{
503+
try
504+
{
505+
sol::object arg = deserialize(view.sol(), it->mCallbackArgument, mSavedDataDeserializer);
493506
// It is important if the order of content files was changed. The deserialize-serialize
494507
// procedure updates refnums, so timer.mSerializedArg may be not equal to
495508
// savedTimer.mCallbackArgument.
496-
savedTimer.mCallbackArgument = serialize(arg, mSerializer);
509+
it->mCallbackArgument = serialize(arg, mSerializer);
510+
++it;
497511
}
498512
catch (std::exception& e)
499513
{
500514
printError(scriptId, "can not load timer", e);
515+
it = script.mTimers.erase(it);
501516
}
502517
}
503518
}
@@ -547,8 +562,7 @@ namespace LuaUtil
547562
{
548563
try
549564
{
550-
sol::object state
551-
= deserialize(view.sol(), scriptInfo.mSavedData->mData, mSavedDataDeserializer);
565+
sol::object state = deserialize(view.sol(), scriptInfo.mSavedData->mData, mSerializer);
552566
sol::object initializationData = deserialize(view.sol(), scriptInfo.mInitData, mSerializer);
553567
LuaUtil::call({ this, scriptId }, *onLoad, state, initializationData);
554568
}
@@ -567,8 +581,8 @@ namespace LuaUtil
567581

568582
try
569583
{
570-
timer.mArg = sol::main_object(
571-
deserialize(view.sol(), savedTimer.mCallbackArgument, mSavedDataDeserializer));
584+
timer.mArg
585+
= sol::main_object(deserialize(view.sol(), savedTimer.mCallbackArgument, mSerializer));
572586
// It is important if the order of content files was changed. The deserialize-serialize
573587
// procedure updates refnums, so timer.mSerializedArg may be not equal to
574588
// savedTimer.mCallbackArgument.

0 commit comments

Comments
 (0)