#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 static bool isLuaCallback(const sol::object&); static Callback fromLua(const sol::table&); static sol::table makeMetatable(lua_State* L); static sol::table make(const AsyncPackageId& asyncId, sol::main_protected_function fn, sol::table metatable); 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