diff --git a/include/TLuaEngine.h b/include/TLuaEngine.h index 69526dd..3701f56 100644 --- a/include/TLuaEngine.h +++ b/include/TLuaEngine.h @@ -8,10 +8,10 @@ #include #include #include +#include #include #include #include -#include #define SOL_ALL_SAFETIES_ON 1 #include @@ -25,7 +25,7 @@ struct TLuaResult { std::atomic_bool Ready; std::atomic_bool Error; std::string ErrorMessage; - sol::protected_function_result Result; + sol::object Result { sol::nil }; TLuaStateId StateId; std::string Function; // TODO: Add condition_variable @@ -41,6 +41,9 @@ struct TLuaPluginConfig { class TLuaEngine : IThreaded { public: TLuaEngine(TServer& Server, TNetwork& Network); + ~TLuaEngine() noexcept { + beammp_debug("Lua Engine terminated"); + } void operator()() override; @@ -49,6 +52,7 @@ public: void EnsureStateExists(TLuaStateId StateId, const std::string& Name, bool DontCallOnInit = false); void RegisterEvent(const std::string& EventName, TLuaStateId StateId, const std::string& FunctionName); [[nodiscard]] std::vector> TriggerEvent(const std::string& EventName); + std::set GetEventHandlersForState(const std::string& EventName, TLuaStateId StateId); static constexpr const char* BeamMPFnNotFoundError = "BEAMMP_FN_NOT_FOUND"; @@ -61,12 +65,16 @@ private: public: StateThreadData(const std::string& Name, std::atomic_bool& Shutdown, TLuaStateId StateId, TLuaEngine& Engine); StateThreadData(const StateThreadData&) = delete; + ~StateThreadData() noexcept { beammp_debug("\"" + mStateId + "\" destroyed"); } [[nodiscard]] std::shared_ptr EnqueueScript(const std::shared_ptr& Script); [[nodiscard]] std::shared_ptr EnqueueFunctionCall(const std::string& FunctionName); void RegisterEvent(const std::string& EventName, const std::string& FunctionName); void operator()() override; - + private: + sol::table Lua_TriggerGlobalEvent(const std::string& EventName); + sol::table Lua_TriggerLocalEvent(const std::string& EventName); + std::string mName; std::atomic_bool& mShutdown; TLuaStateId mStateId; diff --git a/src/LuaAPI.cpp b/src/LuaAPI.cpp index 5519c2a..c13f01f 100644 --- a/src/LuaAPI.cpp +++ b/src/LuaAPI.cpp @@ -7,6 +7,8 @@ static std::string LuaToString(const sol::object& Value, size_t Indent = 1) { return Value.as(); case sol::type::number: return std::to_string(Value.as()); + case sol::type::nil: + return ""; case sol::type::boolean: return Value.as() ? "true" : "false"; case sol::type::table: { diff --git a/src/TConsole.cpp b/src/TConsole.cpp index 3702c35..423e132 100644 --- a/src/TConsole.cpp +++ b/src/TConsole.cpp @@ -62,13 +62,12 @@ TConsole::TConsole() { beammp_info("Lua not started yet, please try again in a second"); } else { auto Future = mLuaEngine->EnqueueScript(mStateId, std::make_shared(cmd)); - // wait for it to finish - /*while (!Future->Ready) { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } - if (Future->Error) { - beammp_error(Future->ErrorMessage); - }*/ + while (!Future->Ready) { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + if (Future->Error) { + beammp_lua_error(Future->ErrorMessage); + } } } }; diff --git a/src/TLuaEngine.cpp b/src/TLuaEngine.cpp index 0475ec1..d6752e4 100644 --- a/src/TLuaEngine.cpp +++ b/src/TLuaEngine.cpp @@ -148,6 +148,54 @@ std::vector> TLuaEngine::TriggerEvent(const std::str return Results; } +std::set TLuaEngine::GetEventHandlersForState(const std::string& EventName, TLuaStateId StateId) { + return mEvents[EventName][StateId]; +} + +sol::table TLuaEngine::StateThreadData::Lua_TriggerGlobalEvent(const std::string& EventName) { + auto Return = mEngine->TriggerEvent(EventName); + beammp_debug("Triggering event \"" + EventName + "\" in \"" + mStateId + "\""); + sol::state_view StateView(mState); + sol::table AsyncEventReturn = StateView.create_table(); + AsyncEventReturn["ReturnValueImpl"] = Return; + AsyncEventReturn.set_function("IsDone", + [&](const sol::table& Self) -> bool { + auto Vector = Self.get>>("ReturnValueImpl"); + for (const auto& Value : Vector) { + if (!Value->Ready) { + return false; + } + } + return true; + }); + AsyncEventReturn.set_function("GetResults", + [&](const sol::table& Self) -> sol::table { + sol::state_view StateView(mState); + sol::table Result = StateView.create_table(); + auto Vector = Self.get>>("ReturnValueImpl"); + for (const auto& Value : Vector) { + if (!Value->Ready) { + return sol::nil; + } + Result.add(Value->Result); + } + return Result; + }); + return AsyncEventReturn; +} + +sol::table TLuaEngine::StateThreadData::Lua_TriggerLocalEvent(const std::string& EventName) { + sol::state_view StateView(mState); + sol::table Result = StateView.create_table(); + for (const auto& Handler : mEngine->GetEventHandlersForState(EventName, mStateId)) { + auto Fn = StateView[Handler]; + if (Fn.valid() && Fn.get_type() == sol::type::function) { + Result.add(Fn()); + } + } + return Result; +} + TLuaEngine::StateThreadData::StateThreadData(const std::string& Name, std::atomic_bool& Shutdown, TLuaStateId StateId, TLuaEngine& Engine) : mName(Name) , mShutdown(Shutdown) @@ -167,31 +215,11 @@ TLuaEngine::StateThreadData::StateThreadData(const std::string& Name, std::atomi }); Table.set_function("TriggerGlobalEvent", [&](const std::string& EventName) -> sol::table { - auto Return = mEngine->TriggerEvent(EventName); - beammp_debug("Triggering event \"" + EventName + "\" in \"" + mStateId + "\""); - sol::state_view StateView(mState); - sol::table AsyncEventReturn = StateView.create_table(); - AsyncEventReturn["ReturnValueImpl"] = Return; - AsyncEventReturn.set_function("Wait", - [&](const sol::table& Self) -> sol::table { - sol::state_view StateView(mState); - sol::table Result = StateView.create_table(); - beammp_debug("beginning to loop"); - auto Vector = Self.get>>("ReturnValueImpl"); - for (const auto& Value : Vector) { - beammp_debug("waiting on a value"); - Value->WaitUntilReady(); - if (Value->Error) { - if (Value->ErrorMessage != BeamMPFnNotFoundError) { - beammp_lua_error("\"" + StateId + "\"" + Value->ErrorMessage); - } - } else { - Result.add(Value->Result); - } - } - return Result; - }); - return AsyncEventReturn; + return Lua_TriggerGlobalEvent(EventName); + }); + Table.set_function("TriggerLocalEvent", + [&](const std::string& EventName) -> sol::table { + return Lua_TriggerLocalEvent(EventName); }); Table.create_named("Settings", "Debug", 0, @@ -214,9 +242,10 @@ std::shared_ptr TLuaEngine::StateThreadData::EnqueueScript(const std std::shared_ptr TLuaEngine::StateThreadData::EnqueueFunctionCall(const std::string& FunctionName) { beammp_debug("calling \"" + FunctionName + "\" in \"" + mName + "\""); - std::unique_lock Lock(mStateFunctionQueueMutex); auto Result = std::make_shared(); Result->StateId = mStateId; + Result->Function = FunctionName; + std::unique_lock Lock(mStateFunctionQueueMutex); mStateFunctionQueue.push({ FunctionName, Result }); return Result; } @@ -277,6 +306,7 @@ void TLuaEngine::StateThreadData::operator()() { } } } + std::this_thread::sleep_for(std::chrono::milliseconds(10)); } }