diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 11e5700c49..ff2ecfe5c9 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 types/armor types/light types/static types/clothing worker diff --git a/apps/openmw/mwlua/asyncbindings.cpp b/apps/openmw/mwlua/asyncbindings.cpp deleted file mode 100644 index e850ef41e4..0000000000 --- a/apps/openmw/mwlua/asyncbindings.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include "luabindings.hpp" - -#include "worldview.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::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 67455db29c..d4706c3e1e 100644 --- a/apps/openmw/mwlua/luabindings.hpp +++ b/apps/openmw/mwlua/luabindings.hpp @@ -34,15 +34,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 4863f7a7f6..9bbd63ac25 100644 --- a/apps/openmw/mwlua/luamanagerimp.cpp +++ b/apps/openmw/mwlua/luamanagerimp.cpp @@ -16,6 +16,7 @@ #include +#include #include #include @@ -95,7 +96,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 6a167ef33d..aa4059b632 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 ae615fd4e5..e69f1bae9e 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 0af1e61a23..b9704787d1 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..bc11cee908 --- /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) { + 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..cbf9ad9ac6 --- /dev/null +++ b/components/lua/asyncpackage.hpp @@ -0,0 +1,54 @@ +#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 + { + sol::optional scriptId = mHiddenData[ScriptsContainer::sScriptIdKey]; + if (scriptId.has_value()) + return LuaUtil::call(scriptId.value(), 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 1592b3ae23..631b1e58a8 100644 --- a/components/lua/scriptscontainer.hpp +++ b/components/lua/scriptscontainer.hpp @@ -269,43 +269,6 @@ namespace LuaUtil static int64_t sInstanceCount; // debug information, shown in Lua profiler }; - - // 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 - { - sol::optional scriptId = mHiddenData[ScriptsContainer::sScriptIdKey]; - if (scriptId.has_value()) - return LuaUtil::call(scriptId.value(), 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 e99fc525ff..7f3c10dd0d 100644 --- a/components/lua/storage.hpp +++ b/components/lua/storage.hpp @@ -4,7 +4,7 @@ #include #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 ffa4bc5af8..b1c67ae3fa 100644 --- a/components/lua_ui/widget.hpp +++ b/components/lua_ui/widget.hpp @@ -7,7 +7,7 @@ #include #include -#include +#include #include "properties.hpp"