Move asyncpackage from apps/openmw/mwlua to components/lua

This commit is contained in:
Petr Mikheev 2023-02-12 22:21:35 +01:00
parent 9673f5b932
commit 71ba7b88e2
12 changed files with 136 additions and 124 deletions

View file

@ -0,0 +1,71 @@
#include "asyncpackage.hpp"
namespace sol
{
template <>
struct is_automagical<LuaUtil::AsyncPackageId> : std::false_type
{
};
template <>
struct is_automagical<LuaUtil::Callback> : std::false_type
{
};
}
namespace LuaUtil
{
struct TimerCallback
{
AsyncPackageId mAsyncId;
std::string mName;
};
sol::function getAsyncPackageInitializer(
lua_State* L, std::function<double()> simulationTimeFn, std::function<double()> gameTimeFn)
{
sol::state_view lua(L);
using TimerType = ScriptsContainer::TimerType;
sol::usertype<AsyncPackageId> api = lua.new_usertype<AsyncPackageId>("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<Callback> callbackType = lua.new_usertype<Callback>("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);
}
}

View file

@ -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<double()> simulationTimeFn, std::function<double()> 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 <typename... Args>
sol::object call(Args&&... args) const
{
sol::optional<ScriptId> scriptId = mHiddenData[ScriptsContainer::sScriptIdKey];
if (scriptId.has_value())
return LuaUtil::call(scriptId.value(), mFunc, std::forward<Args>(args)...);
else
Log(Debug::Debug) << "Ignored callback to the removed script "
<< mHiddenData.get<std::string>(ScriptsContainer::sScriptDebugNameKey);
return sol::nil;
}
template <typename... Args>
void tryCall(Args&&... args) const
{
try
{
this->call(std::forward<Args>(args)...);
}
catch (std::exception& e)
{
Log(Debug::Error) << "Error in callback: " << e.what();
}
}
};
}
#endif // COMPONENTS_LUA_ASYNCPACKAGE_H

View file

@ -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 <typename... Args>
sol::object call(Args&&... args) const
{
sol::optional<ScriptId> scriptId = mHiddenData[ScriptsContainer::sScriptIdKey];
if (scriptId.has_value())
return LuaUtil::call(scriptId.value(), mFunc, std::forward<Args>(args)...);
else
Log(Debug::Debug) << "Ignored callback to the removed script "
<< mHiddenData.get<std::string>(ScriptsContainer::sScriptDebugNameKey);
return sol::nil;
}
template <typename... Args>
void tryCall(Args&&... args) const
{
try
{
this->call(std::forward<Args>(args)...);
}
catch (std::exception& e)
{
Log(Debug::Error) << "Error in callback: " << e.what();
}
}
};
}
#endif // COMPONENTS_LUA_SCRIPTSCONTAINER_H

View file

@ -4,7 +4,7 @@
#include <map>
#include <sol/sol.hpp>
#include "scriptscontainer.hpp"
#include "asyncpackage.hpp"
#include "serialization.hpp"
namespace LuaUtil