Lua scripts configuration in omwaddon

This commit is contained in:
Petr Mikheev 2022-05-20 21:47:13 +02:00
parent 58fd560ce9
commit a70d5831c5
26 changed files with 700 additions and 236 deletions

View file

@ -3,6 +3,8 @@
#include "components/esm3/esmreader.hpp"
#include "components/esm3/esmwriter.hpp"
#include <components/lua/serialization.hpp>
// List of all records, that are related to Lua.
//
// Records:
@ -10,13 +12,15 @@
// LUAM - MWLua::LuaManager (in saves)
//
// Subrecords:
// LUAF - LuaScriptCfg::mFlags
// LUAF - LuaScriptCfg::mFlags and ESM::RecNameInts list
// LUAW - Start of MWLua::WorldView data
// LUAE - Start of MWLua::LocalEvent or MWLua::GlobalEvent (eventName)
// LUAS - VFS path to a Lua script
// LUAD - Serialized Lua variable
// LUAT - MWLua::ScriptsContainer::Timer
// LUAC - Name of a timer callback (string)
// LUAR - Attach script to a specific record (LuaScriptCfg::PerRecordCfg)
// LUAI - Attach script to a specific instance (LuaScriptCfg::PerRefCfg)
void ESM::saveLuaBinaryData(ESMWriter& esm, const std::string& data)
{
@ -39,25 +43,120 @@ std::string ESM::loadLuaBinaryData(ESMReader& esm)
return data;
}
static bool readBool(ESM::ESMReader& esm)
{
char c;
esm.getT<char>(c);
return c != 0;
}
void ESM::LuaScriptsCfg::load(ESMReader& esm)
{
while (esm.isNextSub("LUAS"))
{
std::string name = esm.getHString();
uint64_t flags;
esm.getHNT(flags, "LUAF");
std::string data = loadLuaBinaryData(esm);
mScripts.push_back({std::move(name), std::move(data), flags});
mScripts.emplace_back();
ESM::LuaScriptCfg& script = mScripts.back();
script.mScriptPath = esm.getHString();
esm.getSubNameIs("LUAF");
esm.getSubHeader();
if (esm.getSubSize() < 4 || (esm.getSubSize() % 4 != 0))
esm.fail("Incorrect LUAF size");
esm.getT(script.mFlags);
script.mTypes.resize((esm.getSubSize() - 4) / 4);
for (uint32_t& type : script.mTypes)
esm.getT(type);
script.mInitializationData = loadLuaBinaryData(esm);
while (esm.isNextSub("LUAR"))
{
esm.getSubHeader();
script.mRecords.emplace_back();
ESM::LuaScriptCfg::PerRecordCfg& recordCfg = script.mRecords.back();
recordCfg.mRecordId.resize(esm.getSubSize() - 1);
recordCfg.mAttach = readBool(esm);
esm.getExact(recordCfg.mRecordId.data(), static_cast<int>(recordCfg.mRecordId.size()));
recordCfg.mInitializationData = loadLuaBinaryData(esm);
}
while (esm.isNextSub("LUAI"))
{
esm.getSubHeader();
script.mRefs.emplace_back();
ESM::LuaScriptCfg::PerRefCfg& refCfg = script.mRefs.back();
refCfg.mAttach = readBool(esm);
esm.getT<uint32_t>(refCfg.mRefnumIndex);
esm.getT<int32_t>(refCfg.mRefnumContentFile);
refCfg.mInitializationData = loadLuaBinaryData(esm);
}
}
}
void ESM::LuaScriptsCfg::adjustRefNums(const ESMReader& esm)
{
auto adjustRefNumFn = [&esm](int contentFile) -> int
{
if (contentFile == 0)
return esm.getIndex();
else if (contentFile > 0 && contentFile <= static_cast<int>(esm.getParentFileIndices().size()))
return esm.getParentFileIndices()[contentFile - 1];
else
throw std::runtime_error("Incorrect contentFile index");
};
lua_State* L = lua_open();
LuaUtil::BasicSerializer serializer(adjustRefNumFn);
auto adjustLuaData = [&](std::string& data)
{
if (data.empty())
return;
sol::object luaData = LuaUtil::deserialize(L, data, &serializer);
data = LuaUtil::serialize(luaData, &serializer);
};
for (LuaScriptCfg& script : mScripts)
{
adjustLuaData(script.mInitializationData);
for (LuaScriptCfg::PerRecordCfg& recordCfg : script.mRecords)
adjustLuaData(recordCfg.mInitializationData);
for (LuaScriptCfg::PerRefCfg& refCfg : script.mRefs)
{
adjustLuaData(refCfg.mInitializationData);
refCfg.mRefnumContentFile = adjustRefNumFn(refCfg.mRefnumContentFile);
}
}
lua_close(L);
}
void ESM::LuaScriptsCfg::save(ESMWriter& esm) const
{
for (const LuaScriptCfg& script : mScripts)
{
esm.writeHNString("LUAS", script.mScriptPath);
esm.writeHNT("LUAF", script.mFlags);
esm.startSubRecord("LUAF");
esm.writeT<uint32_t>(script.mFlags);
for (uint32_t type : script.mTypes)
esm.writeT<uint32_t>(type);
esm.endRecord("LUAF");
saveLuaBinaryData(esm, script.mInitializationData);
for (const LuaScriptCfg::PerRecordCfg& recordCfg : script.mRecords)
{
esm.startSubRecord("LUAR");
esm.writeT<char>(recordCfg.mAttach ? 1 : 0);
esm.write(recordCfg.mRecordId.data(), recordCfg.mRecordId.size());
esm.endRecord("LUAR");
saveLuaBinaryData(esm, recordCfg.mInitializationData);
}
for (const LuaScriptCfg::PerRefCfg& refCfg : script.mRefs)
{
esm.startSubRecord("LUAI");
esm.writeT<char>(refCfg.mAttach ? 1 : 0);
esm.writeT<uint32_t>(refCfg.mRefnumIndex);
esm.writeT<int32_t>(refCfg.mRefnumContentFile);
esm.endRecord("LUAI");
saveLuaBinaryData(esm, refCfg.mInitializationData);
}
}
}