From 628017a8176fd43d7da327c9775a5cf0c5a66fb8 Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Sun, 12 Feb 2023 22:21:35 +0100 Subject: [PATCH] Move asyncpackage from apps/openmw/mwlua to components/lua (!2733 for 0.48) --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwlua/asyncbindings.cpp | 69 ------------------ apps/openmw/mwlua/luabindings.hpp | 9 --- apps/openmw/mwlua/luamanagerimp.cpp | 6 +- apps/openmw_test_suite/lua/test_async.cpp | 2 +- .../lua/test_scriptscontainer.cpp | 1 + components/CMakeLists.txt | 2 +- components/lua/asyncpackage.cpp | 71 +++++++++++++++++++ components/lua/asyncpackage.hpp | 53 ++++++++++++++ components/lua/scriptscontainer.hpp | 32 --------- components/lua/storage.hpp | 2 +- components/lua_ui/widget.hpp | 2 +- 12 files changed, 135 insertions(+), 116 deletions(-) delete mode 100644 apps/openmw/mwlua/asyncbindings.cpp create mode 100644 components/lua/asyncpackage.cpp create mode 100644 components/lua/asyncpackage.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 13fb717147..65fbea3fcf 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -60,7 +60,7 @@ add_openmw_dir (mwscript add_openmw_dir (mwlua luamanagerimp object worldview userdataserializer eventqueue - luabindings localscripts playerscripts objectbindings cellbindings asyncbindings + luabindings localscripts playerscripts objectbindings cellbindings camerabindings uibindings inputbindings nearbybindings postprocessingbindings stats debugbindings types/types types/door types/actor types/container types/weapon types/npc types/creature types/activator types/book types/lockpick types/probe types/apparatus types/potion types/ingredient types/misc types/repair ) diff --git a/apps/openmw/mwlua/asyncbindings.cpp b/apps/openmw/mwlua/asyncbindings.cpp deleted file mode 100644 index 968920ab7f..0000000000 --- a/apps/openmw/mwlua/asyncbindings.cpp +++ /dev/null @@ -1,69 +0,0 @@ -#include "luabindings.hpp" - -#include "luamanagerimp.hpp" - -namespace sol -{ - template <> - struct is_automagical : std::false_type {}; - - template <> - struct is_automagical : std::false_type {}; -} - -namespace MWLua -{ - - struct TimerCallback - { - AsyncPackageId mAsyncId; - std::string mName; - }; - - sol::function getAsyncPackageInitializer(const Context& context) - { - using TimerType = LuaUtil::ScriptsContainer::TimerType; - sol::usertype api = context.mLua->sol().new_usertype("AsyncPackage"); - api["registerTimerCallback"] - = [](const AsyncPackageId& asyncId, std::string_view name, sol::main_protected_function callback) { - asyncId.mContainer->registerTimerCallback(asyncId.mScriptId, name, std::move(callback)); - return TimerCallback{ asyncId, std::string(name) }; - }; - api["newSimulationTimer"] = [world = context.mWorldView](const AsyncPackageId&, double delay, - const TimerCallback& callback, sol::main_object callbackArg) { - callback.mAsyncId.mContainer->setupSerializableTimer(TimerType::SIMULATION_TIME, - world->getSimulationTime() + delay, callback.mAsyncId.mScriptId, callback.mName, - std::move(callbackArg)); - }; - api["newGameTimer"] = [world = context.mWorldView](const AsyncPackageId&, double delay, - const TimerCallback& callback, sol::main_object callbackArg) { - callback.mAsyncId.mContainer->setupSerializableTimer(TimerType::GAME_TIME, world->getGameTime() + delay, - callback.mAsyncId.mScriptId, callback.mName, std::move(callbackArg)); - }; - api["newUnsavableSimulationTimer"] = [world = context.mWorldView](const AsyncPackageId& asyncId, double delay, - sol::main_protected_function callback) { - asyncId.mContainer->setupUnsavableTimer( - TimerType::SIMULATION_TIME, world->getSimulationTime() + delay, asyncId.mScriptId, std::move(callback)); - }; - api["newUnsavableGameTimer"] = [world = context.mWorldView](const AsyncPackageId& asyncId, double delay, - sol::main_protected_function callback) { - asyncId.mContainer->setupUnsavableTimer( - TimerType::GAME_TIME, world->getGameTime() + delay, asyncId.mScriptId, std::move(callback)); - }; - api["callback"] = [](const AsyncPackageId& asyncId, sol::main_protected_function fn) -> LuaUtil::Callback { - return LuaUtil::Callback{ std::move(fn), asyncId.mHiddenData }; - }; - - sol::usertype callbackType = context.mLua->sol().new_usertype("Callback"); - callbackType[sol::meta_function::call] = - [](const LuaUtil::Callback& callback, sol::variadic_args va) { return callback.call(sol::as_args(va)); }; - - auto initializer = [](sol::table hiddenData) - { - LuaUtil::ScriptsContainer::ScriptId id = hiddenData[LuaUtil::ScriptsContainer::sScriptIdKey]; - return AsyncPackageId{id.mContainer, id.mIndex, hiddenData}; - }; - return sol::make_object(context.mLua->sol(), initializer); - } - -} diff --git a/apps/openmw/mwlua/luabindings.hpp b/apps/openmw/mwlua/luabindings.hpp index 5760a383ec..8c0a7b94c4 100644 --- a/apps/openmw/mwlua/luabindings.hpp +++ b/apps/openmw/mwlua/luabindings.hpp @@ -38,15 +38,6 @@ namespace MWLua void initCellBindingsForLocalScripts(const Context&); void initCellBindingsForGlobalScripts(const Context&); - // Implemented in asyncbindings.cpp - struct AsyncPackageId - { - LuaUtil::ScriptsContainer* mContainer; - int mScriptId; - sol::table mHiddenData; - }; - sol::function getAsyncPackageInitializer(const Context&); - // Implemented in camerabindings.cpp sol::table initCameraPackage(const Context&); diff --git a/apps/openmw/mwlua/luamanagerimp.cpp b/apps/openmw/mwlua/luamanagerimp.cpp index d98bb557b4..458fc73ce1 100644 --- a/apps/openmw/mwlua/luamanagerimp.cpp +++ b/apps/openmw/mwlua/luamanagerimp.cpp @@ -12,6 +12,7 @@ #include +#include #include #include @@ -86,7 +87,10 @@ namespace MWLua LocalScripts::initializeSelfPackage(localContext); LuaUtil::LuaStorage::initLuaBindings(mLua.sol()); - mLua.addCommonPackage("openmw.async", getAsyncPackageInitializer(context)); + mLua.addCommonPackage("openmw.async", + LuaUtil::getAsyncPackageInitializer( + mLua.sol(), [this] { return mWorldView.getSimulationTime(); }, + [this] { return mWorldView.getGameTime(); })); mLua.addCommonPackage("openmw.util", LuaUtil::initUtilPackage(mLua.sol())); mLua.addCommonPackage("openmw.core", initCorePackage(context)); mLua.addCommonPackage("openmw.types", initTypesPackage(context)); diff --git a/apps/openmw_test_suite/lua/test_async.cpp b/apps/openmw_test_suite/lua/test_async.cpp index c1e1fd6c86..56f7a09be1 100644 --- a/apps/openmw_test_suite/lua/test_async.cpp +++ b/apps/openmw_test_suite/lua/test_async.cpp @@ -1,8 +1,8 @@ #include "gmock/gmock.h" #include +#include #include -#include #include "../testing_util.hpp" diff --git a/apps/openmw_test_suite/lua/test_scriptscontainer.cpp b/apps/openmw_test_suite/lua/test_scriptscontainer.cpp index 84b632913c..ef3ddc692b 100644 --- a/apps/openmw_test_suite/lua/test_scriptscontainer.cpp +++ b/apps/openmw_test_suite/lua/test_scriptscontainer.cpp @@ -3,6 +3,7 @@ #include +#include #include #include diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index a48a6a8036..0b0a39ef92 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -34,7 +34,7 @@ endif (GIT_CHECKOUT) # source files add_component_dir (lua - luastate scriptscontainer utilpackage serialization configuration l10n storage + luastate scriptscontainer asyncpackage utilpackage serialization configuration l10n storage ) add_component_dir (l10n diff --git a/components/lua/asyncpackage.cpp b/components/lua/asyncpackage.cpp new file mode 100644 index 0000000000..59f23fbd99 --- /dev/null +++ b/components/lua/asyncpackage.cpp @@ -0,0 +1,71 @@ +#include "asyncpackage.hpp" + +namespace sol +{ + template <> + struct is_automagical : std::false_type + { + }; + + template <> + struct is_automagical : std::false_type + { + }; +} + +namespace LuaUtil +{ + + struct TimerCallback + { + AsyncPackageId mAsyncId; + std::string mName; + }; + + sol::function getAsyncPackageInitializer( + lua_State* L, std::function simulationTimeFn, std::function gameTimeFn) + { + sol::state_view lua(L); + using TimerType = ScriptsContainer::TimerType; + sol::usertype api = lua.new_usertype("AsyncPackage"); + api["registerTimerCallback"] + = [](const AsyncPackageId& asyncId, std::string_view name, sol::main_protected_function callback) { + asyncId.mContainer->registerTimerCallback(asyncId.mScriptId, name, std::move(callback)); + return TimerCallback{ asyncId, std::string(name) }; + }; + api["newSimulationTimer"] = [simulationTimeFn](const AsyncPackageId&, double delay, + const TimerCallback& callback, sol::main_object callbackArg) { + callback.mAsyncId.mContainer->setupSerializableTimer(TimerType::SIMULATION_TIME, simulationTimeFn() + delay, + callback.mAsyncId.mScriptId, callback.mName, std::move(callbackArg)); + }; + api["newGameTimer"] = [gameTimeFn](const AsyncPackageId&, double delay, const TimerCallback& callback, + sol::main_object callbackArg) { + callback.mAsyncId.mContainer->setupSerializableTimer(TimerType::GAME_TIME, gameTimeFn() + delay, + callback.mAsyncId.mScriptId, callback.mName, std::move(callbackArg)); + }; + api["newUnsavableSimulationTimer"] + = [simulationTimeFn](const AsyncPackageId& asyncId, double delay, sol::main_protected_function callback) { + asyncId.mContainer->setupUnsavableTimer( + TimerType::SIMULATION_TIME, simulationTimeFn() + delay, asyncId.mScriptId, std::move(callback)); + }; + api["newUnsavableGameTimer"] + = [gameTimeFn](const AsyncPackageId& asyncId, double delay, sol::main_protected_function callback) { + asyncId.mContainer->setupUnsavableTimer( + TimerType::GAME_TIME, gameTimeFn() + delay, asyncId.mScriptId, std::move(callback)); + }; + api["callback"] = [](const AsyncPackageId& asyncId, sol::main_protected_function fn) -> Callback { + return Callback{ std::move(fn), asyncId.mHiddenData }; + }; + + sol::usertype callbackType = lua.new_usertype("Callback"); + callbackType[sol::meta_function::call] + = [](const Callback& callback, sol::variadic_args va) { return callback.call(sol::as_args(va)); }; + + auto initializer = [](sol::table hiddenData) { + ScriptsContainer::ScriptId id = hiddenData[ScriptsContainer::sScriptIdKey]; + return AsyncPackageId{ id.mContainer, id.mIndex, hiddenData }; + }; + return sol::make_object(lua, initializer); + } + +} diff --git a/components/lua/asyncpackage.hpp b/components/lua/asyncpackage.hpp new file mode 100644 index 0000000000..6123375b25 --- /dev/null +++ b/components/lua/asyncpackage.hpp @@ -0,0 +1,53 @@ +#ifndef COMPONENTS_LUA_ASYNCPACKAGE_H +#define COMPONENTS_LUA_ASYNCPACKAGE_H + +#include "scriptscontainer.hpp" + +namespace LuaUtil +{ + struct AsyncPackageId + { + ScriptsContainer* mContainer; + int mScriptId; + sol::table mHiddenData; + }; + sol::function getAsyncPackageInitializer( + lua_State* L, std::function simulationTimeFn, std::function gameTimeFn); + + // Wrapper for a Lua function. + // Holds information about the script the function belongs to. + // Needed to prevent callback calls if the script was removed. + struct Callback + { + sol::main_protected_function mFunc; + sol::table mHiddenData; // same object as Script::mHiddenData in ScriptsContainer + + bool isValid() const { return mHiddenData[ScriptsContainer::sScriptIdKey] != sol::nil; } + + template + sol::object call(Args&&... args) const + { + if (isValid()) + return LuaUtil::call(mFunc, std::forward(args)...); + else + Log(Debug::Debug) << "Ignored callback to the removed script " + << mHiddenData.get(ScriptsContainer::sScriptDebugNameKey); + return sol::nil; + } + + template + void tryCall(Args&&... args) const + { + try + { + this->call(std::forward(args)...); + } + catch (std::exception& e) + { + Log(Debug::Error) << "Error in callback: " << e.what(); + } + } + }; +} + +#endif // COMPONENTS_LUA_ASYNCPACKAGE_H diff --git a/components/lua/scriptscontainer.hpp b/components/lua/scriptscontainer.hpp index 201218a6e2..c20b369176 100644 --- a/components/lua/scriptscontainer.hpp +++ b/components/lua/scriptscontainer.hpp @@ -246,38 +246,6 @@ namespace LuaUtil int64_t mTemporaryCallbackCounter = 0; }; - // Wrapper for a Lua function. - // Holds information about the script the function belongs to. - // Needed to prevent callback calls if the script was removed. - struct Callback - { - sol::main_protected_function mFunc; - sol::table mHiddenData; // same object as Script::mHiddenData in ScriptsContainer - - bool isValid() const { return mHiddenData[ScriptsContainer::sScriptIdKey] != sol::nil; } - - template - sol::object call(Args&&... args) const - { - if (isValid()) - return LuaUtil::call(mFunc, std::forward(args)...); - else - Log(Debug::Debug) << "Ignored callback to the removed script " - << mHiddenData.get(ScriptsContainer::sScriptDebugNameKey); - return sol::nil; - } - - template - void tryCall(Args&&... args) const - { - try { this->call(std::forward(args)...); } - catch (std::exception& e) - { - Log(Debug::Error) << "Error in callback: " << e.what(); - } - } - }; - } #endif // COMPONENTS_LUA_SCRIPTSCONTAINER_H diff --git a/components/lua/storage.hpp b/components/lua/storage.hpp index b2fbde4abe..e1a257298c 100644 --- a/components/lua/storage.hpp +++ b/components/lua/storage.hpp @@ -6,7 +6,7 @@ #include -#include "scriptscontainer.hpp" +#include "asyncpackage.hpp" #include "serialization.hpp" namespace LuaUtil diff --git a/components/lua_ui/widget.hpp b/components/lua_ui/widget.hpp index 3285f629ac..5bba387070 100644 --- a/components/lua_ui/widget.hpp +++ b/components/lua_ui/widget.hpp @@ -7,7 +7,7 @@ #include #include -#include +#include #include "properties.hpp"