From 68b8a148d7e97fb94407b211ff8514fccaaa36d7 Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Sat, 17 Jul 2021 20:12:41 +0200 Subject: [PATCH 1/3] Initialize Lua packages in LuaManager::init rather than in constructor. --- apps/openmw/mwlua/luamanagerimp.cpp | 10 +++++++--- apps/openmw/mwlua/luamanagerimp.hpp | 1 + 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwlua/luamanagerimp.cpp b/apps/openmw/mwlua/luamanagerimp.cpp index e01273bb84..b02dbbc296 100644 --- a/apps/openmw/mwlua/luamanagerimp.cpp +++ b/apps/openmw/mwlua/luamanagerimp.cpp @@ -31,7 +31,10 @@ namespace MWLua mLocalLoader = createUserdataSerializer(true, mWorldView.getObjectRegistry(), &mContentFileMapping); mGlobalScripts.setSerializer(mGlobalSerializer.get()); + } + void LuaManager::init() + { Context context; context.mIsGlobal = true; context.mLuaManager = this; @@ -60,14 +63,12 @@ namespace MWLua mCameraPackage = initCameraPackage(localContext); mUserInterfacePackage = initUserInterfacePackage(localContext); mNearbyPackage = initNearbyPackage(localContext); - } - void LuaManager::init() - { mKeyPressEvents.clear(); for (const std::string& path : mGlobalScriptList) if (mGlobalScripts.addNewScript(path)) Log(Debug::Info) << "Global script started: " << path; + mInitialized = true; } void LuaManager::update(bool paused, float dt) @@ -198,6 +199,8 @@ namespace MWLua void LuaManager::setupPlayer(const MWWorld::Ptr& ptr) { + if (!mInitialized) + return; if (!mPlayer.isEmpty()) throw std::logic_error("Player is initialized twice"); mWorldView.objectAddedToScene(ptr); @@ -279,6 +282,7 @@ namespace MWLua LocalScripts* LuaManager::createLocalScripts(const MWWorld::Ptr& ptr) { + assert(mInitialized); std::shared_ptr scripts; // When loading a game, it can be called before LuaManager::setPlayer, // so we can't just check ptr == mPlayer here. diff --git a/apps/openmw/mwlua/luamanagerimp.hpp b/apps/openmw/mwlua/luamanagerimp.hpp index df87457b23..a212f213c0 100644 --- a/apps/openmw/mwlua/luamanagerimp.hpp +++ b/apps/openmw/mwlua/luamanagerimp.hpp @@ -70,6 +70,7 @@ namespace MWLua private: LocalScripts* createLocalScripts(const MWWorld::Ptr& ptr); + bool mInitialized = false; LuaUtil::LuaState mLua; sol::table mNearbyPackage; sol::table mUserInterfacePackage; From 3e4c0b775dbeea3b610f9e90d341911f34fd57dc Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Tue, 1 Jun 2021 23:18:42 +0200 Subject: [PATCH 2/3] Add Lua package 'openmw.settings' --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwlua/luabindings.cpp | 2 +- apps/openmw/mwlua/luabindings.hpp | 5 ++ apps/openmw/mwlua/luamanagerimp.cpp | 7 ++ apps/openmw/mwlua/luamanagerimp.hpp | 2 + apps/openmw/mwlua/settingsbindings.cpp | 72 +++++++++++++++++++ docs/source/reference/lua-scripting/api.rst | 4 ++ .../lua-scripting/openmw_settings.rst | 5 ++ .../reference/lua-scripting/overview.rst | 3 + files/lua_api/openmw/settings.lua | 14 ++++ 10 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 apps/openmw/mwlua/settingsbindings.cpp create mode 100644 docs/source/reference/lua-scripting/openmw_settings.rst create mode 100644 files/lua_api/openmw/settings.lua diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 3c29baf3aa..6d58e880ed 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -57,7 +57,7 @@ add_openmw_dir (mwscript add_openmw_dir (mwlua luamanagerimp actions object worldview userdataserializer eventqueue query - luabindings localscripts objectbindings cellbindings asyncbindings camerabindings uibindings + luabindings localscripts objectbindings cellbindings asyncbindings camerabindings uibindings settingsbindings ) add_openmw_dir (mwsound diff --git a/apps/openmw/mwlua/luabindings.cpp b/apps/openmw/mwlua/luabindings.cpp index ebb24401fc..ca800f2dd4 100644 --- a/apps/openmw/mwlua/luabindings.cpp +++ b/apps/openmw/mwlua/luabindings.cpp @@ -31,7 +31,7 @@ namespace MWLua { auto* lua = context.mLua; sol::table api(lua->sol(), sol::create); - api["API_VERSION"] = 0; + api["API_VERSION"] = 1; api["sendGlobalEvent"] = [context](std::string eventName, const sol::object& eventData) { context.mGlobalEventQueue->push_back({std::move(eventName), LuaUtil::serialize(eventData, context.mSerializer)}); diff --git a/apps/openmw/mwlua/luabindings.hpp b/apps/openmw/mwlua/luabindings.hpp index 8be96763a5..568eb4e1ef 100644 --- a/apps/openmw/mwlua/luabindings.hpp +++ b/apps/openmw/mwlua/luabindings.hpp @@ -59,6 +59,11 @@ namespace MWLua // Implemented in uibindings.cpp sol::table initUserInterfacePackage(const Context&); + // Implemented in settingsbindings.cpp + sol::table initGlobalSettingsPackage(const Context&); + sol::table initLocalSettingsPackage(const Context&); + sol::table initPlayerSettingsPackage(const Context&); + // openmw.self package is implemented in localscripts.cpp } diff --git a/apps/openmw/mwlua/luamanagerimp.cpp b/apps/openmw/mwlua/luamanagerimp.cpp index b02dbbc296..bbfe0b8c3a 100644 --- a/apps/openmw/mwlua/luamanagerimp.cpp +++ b/apps/openmw/mwlua/luamanagerimp.cpp @@ -60,9 +60,12 @@ namespace MWLua mLua.addCommonPackage("openmw.core", initCorePackage(context)); mLua.addCommonPackage("openmw.query", initQueryPackage(context)); mGlobalScripts.addPackage("openmw.world", initWorldPackage(context)); + mGlobalScripts.addPackage("openmw.settings", initGlobalSettingsPackage(context)); mCameraPackage = initCameraPackage(localContext); mUserInterfacePackage = initUserInterfacePackage(localContext); mNearbyPackage = initNearbyPackage(localContext); + mLocalSettingsPackage = initLocalSettingsPackage(localContext); + mPlayerSettingsPackage = initPlayerSettingsPackage(localContext); mKeyPressEvents.clear(); for (const std::string& path : mGlobalScriptList) @@ -291,9 +294,13 @@ namespace MWLua scripts = std::make_shared(&mLua, LObject(getId(ptr), mWorldView.getObjectRegistry())); scripts->addPackage("openmw.ui", mUserInterfacePackage); scripts->addPackage("openmw.camera", mCameraPackage); + scripts->addPackage("openmw.settings", mPlayerSettingsPackage); } else + { scripts = std::make_shared(&mLua, LObject(getId(ptr), mWorldView.getObjectRegistry())); + scripts->addPackage("openmw.settings", mLocalSettingsPackage); + } scripts->addPackage("openmw.nearby", mNearbyPackage); scripts->setSerializer(mLocalSerializer.get()); diff --git a/apps/openmw/mwlua/luamanagerimp.hpp b/apps/openmw/mwlua/luamanagerimp.hpp index a212f213c0..48cdeba026 100644 --- a/apps/openmw/mwlua/luamanagerimp.hpp +++ b/apps/openmw/mwlua/luamanagerimp.hpp @@ -75,6 +75,8 @@ namespace MWLua sol::table mNearbyPackage; sol::table mUserInterfacePackage; sol::table mCameraPackage; + sol::table mLocalSettingsPackage; + sol::table mPlayerSettingsPackage; std::vector mGlobalScriptList; GlobalScripts mGlobalScripts{&mLua}; diff --git a/apps/openmw/mwlua/settingsbindings.cpp b/apps/openmw/mwlua/settingsbindings.cpp new file mode 100644 index 0000000000..0e267182ac --- /dev/null +++ b/apps/openmw/mwlua/settingsbindings.cpp @@ -0,0 +1,72 @@ +#include "luabindings.hpp" + +#include + +#include "../mwworld/esmstore.hpp" +#include "../mwworld/store.hpp" + +namespace MWLua +{ + + static sol::table initSettingsPackage(const Context& context, bool /*global*/, bool player) + { + LuaUtil::LuaState* lua = context.mLua; + sol::table config(lua->sol(), sol::create); + + // Access to settings.cfg. Temporary, will be removed at some point. + auto checkRead = [player](std::string_view category) + { + if ((category == "Camera" || category == "GUI" || category == "Hud" || + category == "Windows" || category == "Input") && !player) + throw std::runtime_error("This setting is only available in player scripts"); + }; + config["_getBoolFromSettingsCfg"] = [=](const std::string& category, const std::string& setting) + { + checkRead(category); + return Settings::Manager::getBool(setting, category); + }; + config["_getIntFromSettingsCfg"] = [=](const std::string& category, const std::string& setting) + { + checkRead(category); + return Settings::Manager::getInt(setting, category); + }; + config["_getFloatFromSettingsCfg"] = [=](const std::string& category, const std::string& setting) + { + checkRead(category); + return Settings::Manager::getFloat(setting, category); + }; + config["_getStringFromSettingsCfg"] = [=](const std::string& category, const std::string& setting) + { + checkRead(category); + return Settings::Manager::getString(setting, category); + }; + config["_getVector2FromSettingsCfg"] = [=](const std::string& category, const std::string& setting) + { + checkRead(category); + return Settings::Manager::getVector2(setting, category); + }; + config["_getVector3FromSettingsCfg"] = [=](const std::string& category, const std::string& setting) + { + checkRead(category); + return Settings::Manager::getVector3(setting, category); + }; + + const MWWorld::Store* gmst = &MWBase::Environment::get().getWorld()->getStore().get(); + config["getGMST"] = [lua, gmst](const std::string setting) -> sol::object + { + const ESM::Variant& value = gmst->find(setting)->mValue; + if (value.getType() == ESM::VT_String) + return sol::make_object(lua->sol(), value.getString()); + else if (value.getType() == ESM::VT_Int) + return sol::make_object(lua->sol(), value.getInteger()); + else + return sol::make_object(lua->sol(), value.getFloat()); + }; + return lua->makeReadOnly(config); + } + + sol::table initGlobalSettingsPackage(const Context& context) { return initSettingsPackage(context, true, false); } + sol::table initLocalSettingsPackage(const Context& context) { return initSettingsPackage(context, false, false); } + sol::table initPlayerSettingsPackage(const Context& context) { return initSettingsPackage(context, false, true); } + +} diff --git a/docs/source/reference/lua-scripting/api.rst b/docs/source/reference/lua-scripting/api.rst index 3a18f2445a..356fc16cbb 100644 --- a/docs/source/reference/lua-scripting/api.rst +++ b/docs/source/reference/lua-scripting/api.rst @@ -7,6 +7,7 @@ Lua API reference engine_handlers openmw_util + openmw_settings openmw_core openmw_async openmw_query @@ -37,6 +38,9 @@ Player scripts are local scripts that are attached to a player. |:ref:`openmw.util ` | everywhere | | Defines utility functions and classes like 3D vectors, | | | | | that don't depend on the game world. | +---------------------------------------------------------+--------------------+---------------------------------------------------------------+ +|:ref:`openmw.settings ` | everywhere | | Access to GMST records in content files (implemented) and | +| | | | to mod settings (not implemented). | ++---------------------------------------------------------+--------------------+---------------------------------------------------------------+ |:ref:`openmw.core ` | everywhere | | Functions that are common for both global and local scripts | +---------------------------------------------------------+--------------------+---------------------------------------------------------------+ |:ref:`openmw.async ` | everywhere | | Timers (implemented) and coroutine utils (not implemented) | diff --git a/docs/source/reference/lua-scripting/openmw_settings.rst b/docs/source/reference/lua-scripting/openmw_settings.rst new file mode 100644 index 0000000000..f3d26882bb --- /dev/null +++ b/docs/source/reference/lua-scripting/openmw_settings.rst @@ -0,0 +1,5 @@ +Package openmw.settings +======================= + +.. raw:: html + :file: generated_html/openmw_settings.html diff --git a/docs/source/reference/lua-scripting/overview.rst b/docs/source/reference/lua-scripting/overview.rst index d3ce319d01..c193886340 100644 --- a/docs/source/reference/lua-scripting/overview.rst +++ b/docs/source/reference/lua-scripting/overview.rst @@ -299,6 +299,9 @@ Player scripts are local scripts that are attached to a player. |:ref:`openmw.util ` | everywhere | | Defines utility functions and classes like 3D vectors, | | | | | that don't depend on the game world. | +---------------------------------------------------------+--------------------+---------------------------------------------------------------+ +|:ref:`openmw.settings ` | everywhere | | Access to GMST records in content files (implemented) and | +| | | | to mod settings (not implemented). | ++---------------------------------------------------------+--------------------+---------------------------------------------------------------+ |:ref:`openmw.core ` | everywhere | | Functions that are common for both global and local scripts | +---------------------------------------------------------+--------------------+---------------------------------------------------------------+ |:ref:`openmw.async ` | everywhere | | Timers (implemented) and coroutine utils (not implemented) | diff --git a/files/lua_api/openmw/settings.lua b/files/lua_api/openmw/settings.lua new file mode 100644 index 0000000000..6c35caa8af --- /dev/null +++ b/files/lua_api/openmw/settings.lua @@ -0,0 +1,14 @@ +------------------------------------------------------------------------------- +-- `openmw.settings` provides read-only access to GMST records in content files. +-- @module settings +-- @usage +-- local settings = require('openmw.settings') + +------------------------------------------------------------------------------- +-- Get a GMST setting from content files. +-- @function [parent=#settings] getGMST +-- @param #string setting + + +return nil + From 2938aaf05c43f2f996c7142d7dd4c7270dfef41e Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Sun, 25 Jul 2021 15:36:25 +0200 Subject: [PATCH 3/3] Rename `API_VERSION` -> `API_REVISION` in Lua API. --- apps/openmw/mwlua/luabindings.cpp | 2 +- files/lua_api/openmw/core.lua | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwlua/luabindings.cpp b/apps/openmw/mwlua/luabindings.cpp index ca800f2dd4..48174f55ee 100644 --- a/apps/openmw/mwlua/luabindings.cpp +++ b/apps/openmw/mwlua/luabindings.cpp @@ -31,7 +31,7 @@ namespace MWLua { auto* lua = context.mLua; sol::table api(lua->sol(), sol::create); - api["API_VERSION"] = 1; + api["API_REVISION"] = 1; api["sendGlobalEvent"] = [context](std::string eventName, const sol::object& eventData) { context.mGlobalEventQueue->push_back({std::move(eventName), LuaUtil::serialize(eventData, context.mSerializer)}); diff --git a/files/lua_api/openmw/core.lua b/files/lua_api/openmw/core.lua index 6b38fc20e1..040e6968dd 100644 --- a/files/lua_api/openmw/core.lua +++ b/files/lua_api/openmw/core.lua @@ -7,8 +7,8 @@ ------------------------------------------------------------------------------- --- The version of OpenMW Lua API. It is an integer that is incremented every time the API is changed. --- @field [parent=#core] #number API_VERSION +-- The revision of OpenMW Lua API. It is an integer that is incremented every time the API is changed. +-- @field [parent=#core] #number API_REVISION ------------------------------------------------------------------------------- -- Send an event to global scripts.