Merge branch 'drop_on_exit' into 'master'

Add a storage mode to drop section on game exit

See merge request OpenMW/openmw!3905
This commit is contained in:
psi29a 2024-02-28 20:36:40 +00:00
commit 03d5872a55
6 changed files with 84 additions and 26 deletions

View file

@ -17,6 +17,15 @@ namespace LuaUtil
{
LuaStorage::Value LuaStorage::Section::sEmpty;
void LuaStorage::registerLifeTime(LuaUtil::LuaState& luaState, sol::table& res)
{
res["LIFE_TIME"] = LuaUtil::makeStrictReadOnly(luaState.tableFromPairs<std::string_view, Section::LifeTime>({
{ "Persistent", Section::LifeTime::Persistent },
{ "GameSession", Section::LifeTime::GameSession },
{ "Temporary", Section::LifeTime::Temporary },
}));
}
sol::object LuaStorage::Value::getCopy(lua_State* L) const
{
return deserialize(L, mSerializedValue);
@ -142,7 +151,12 @@ namespace LuaUtil
sview["removeOnExit"] = [](const SectionView& section) {
if (section.mReadOnly)
throw std::runtime_error("Access to storage is read only");
section.mSection->mPermanent = false;
section.mSection->mLifeTime = Section::Temporary;
};
sview["setLifeTime"] = [](const SectionView& section, Section::LifeTime lifeTime) {
if (section.mReadOnly)
throw std::runtime_error("Access to storage is read only");
section.mSection->mLifeTime = lifeTime;
};
sview["set"] = [](const SectionView& section, std::string_view key, const sol::object& value) {
if (section.mReadOnly)
@ -151,26 +165,33 @@ namespace LuaUtil
};
}
sol::table LuaStorage::initGlobalPackage(lua_State* lua, LuaStorage* globalStorage)
sol::table LuaStorage::initGlobalPackage(LuaUtil::LuaState& luaState, LuaStorage* globalStorage)
{
sol::table res(lua, sol::create);
sol::table res(luaState.sol(), sol::create);
registerLifeTime(luaState, res);
res["globalSection"]
= [globalStorage](std::string_view section) { return globalStorage->getMutableSection(section); };
res["allGlobalSections"] = [globalStorage]() { return globalStorage->getAllSections(); };
return LuaUtil::makeReadOnly(res);
}
sol::table LuaStorage::initLocalPackage(lua_State* lua, LuaStorage* globalStorage)
sol::table LuaStorage::initLocalPackage(LuaUtil::LuaState& luaState, LuaStorage* globalStorage)
{
sol::table res(lua, sol::create);
sol::table res(luaState.sol(), sol::create);
registerLifeTime(luaState, res);
res["globalSection"]
= [globalStorage](std::string_view section) { return globalStorage->getReadOnlySection(section); };
return LuaUtil::makeReadOnly(res);
}
sol::table LuaStorage::initPlayerPackage(lua_State* lua, LuaStorage* globalStorage, LuaStorage* playerStorage)
sol::table LuaStorage::initPlayerPackage(
LuaUtil::LuaState& luaState, LuaStorage* globalStorage, LuaStorage* playerStorage)
{
sol::table res(lua, sol::create);
sol::table res(luaState.sol(), sol::create);
registerLifeTime(luaState, res);
res["globalSection"]
= [globalStorage](std::string_view section) { return globalStorage->getReadOnlySection(section); };
res["playerSection"]
@ -179,9 +200,12 @@ namespace LuaUtil
return LuaUtil::makeReadOnly(res);
}
sol::table LuaStorage::initMenuPackage(lua_State* lua, LuaStorage* globalStorage, LuaStorage* playerStorage)
sol::table LuaStorage::initMenuPackage(
LuaUtil::LuaState& luaState, LuaStorage* globalStorage, LuaStorage* playerStorage)
{
sol::table res(lua, sol::create);
sol::table res(luaState.sol(), sol::create);
registerLifeTime(luaState, res);
res["playerSection"] = [playerStorage](std::string_view section) {
return playerStorage->getMutableSection(section, /*forMenuScripts=*/true);
};
@ -199,7 +223,7 @@ namespace LuaUtil
it->second->mCallbacks.clear();
// Note that we don't clear menu callbacks for permanent sections
// because starting/loading a game doesn't reset menu scripts.
if (!it->second->mPermanent)
if (it->second->mLifeTime == Section::Temporary)
{
it->second->mMenuScriptsCallbacks.clear();
it->second->mValues.clear();
@ -238,7 +262,7 @@ namespace LuaUtil
sol::table data(mLua, sol::create);
for (const auto& [sectionName, section] : mData)
{
if (section->mPermanent && !section->mValues.empty())
if (section->mLifeTime == Section::Persistent && !section->mValues.empty())
data[sectionName] = section->asTable();
}
std::string serializedData = serialize(data);

View file

@ -14,11 +14,13 @@ namespace LuaUtil
class LuaStorage
{
public:
static void initLuaBindings(lua_State*);
static sol::table initGlobalPackage(lua_State* lua, LuaStorage* globalStorage);
static sol::table initLocalPackage(lua_State* lua, LuaStorage* globalStorage);
static sol::table initPlayerPackage(lua_State* lua, LuaStorage* globalStorage, LuaStorage* playerStorage);
static sol::table initMenuPackage(lua_State* lua, LuaStorage* globalStorage, LuaStorage* playerStorage);
static void initLuaBindings(lua_State* L);
static sol::table initGlobalPackage(LuaUtil::LuaState& luaState, LuaStorage* globalStorage);
static sol::table initLocalPackage(LuaUtil::LuaState& luaState, LuaStorage* globalStorage);
static sol::table initPlayerPackage(
LuaUtil::LuaState& luaState, LuaStorage* globalStorage, LuaStorage* playerStorage);
static sol::table initMenuPackage(
LuaUtil::LuaState& luaState, LuaStorage* globalStorage, LuaStorage* playerStorage);
explicit LuaStorage(lua_State* lua)
: mLua(lua)
@ -78,6 +80,13 @@ namespace LuaUtil
struct Section
{
enum LifeTime
{
Persistent,
GameSession,
Temporary
};
explicit Section(LuaStorage* storage, std::string name)
: mStorage(storage)
, mSectionName(std::move(name))
@ -96,7 +105,7 @@ namespace LuaUtil
std::vector<Callback> mCallbacks;
std::vector<Callback> mMenuScriptsCallbacks; // menu callbacks are in a separate vector because we don't
// remove them in clear()
bool mPermanent = true;
LifeTime mLifeTime = Persistent;
static Value sEmpty;
void checkIfActive() const { mStorage->checkIfActive(); }
@ -120,6 +129,7 @@ namespace LuaUtil
if (!mActive)
throw std::logic_error("Trying to access inactive storage");
}
static void registerLifeTime(LuaUtil::LuaState& luaState, sol::table& res);
};
}