Lua: working events, global and local

This commit is contained in:
Lion Kortlepel
2021-09-16 18:14:11 +02:00
parent e602decb96
commit 1c80a4deb7
4 changed files with 75 additions and 36 deletions
+11 -3
View File
@@ -8,10 +8,10 @@
#include <memory> #include <memory>
#include <mutex> #include <mutex>
#include <queue> #include <queue>
#include <set>
#include <toml11/toml.hpp> #include <toml11/toml.hpp>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include <set>
#define SOL_ALL_SAFETIES_ON 1 #define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp> #include <sol/sol.hpp>
@@ -25,7 +25,7 @@ struct TLuaResult {
std::atomic_bool Ready; std::atomic_bool Ready;
std::atomic_bool Error; std::atomic_bool Error;
std::string ErrorMessage; std::string ErrorMessage;
sol::protected_function_result Result; sol::object Result { sol::nil };
TLuaStateId StateId; TLuaStateId StateId;
std::string Function; std::string Function;
// TODO: Add condition_variable // TODO: Add condition_variable
@@ -41,6 +41,9 @@ struct TLuaPluginConfig {
class TLuaEngine : IThreaded { class TLuaEngine : IThreaded {
public: public:
TLuaEngine(TServer& Server, TNetwork& Network); TLuaEngine(TServer& Server, TNetwork& Network);
~TLuaEngine() noexcept {
beammp_debug("Lua Engine terminated");
}
void operator()() override; void operator()() override;
@@ -49,6 +52,7 @@ public:
void EnsureStateExists(TLuaStateId StateId, const std::string& Name, bool DontCallOnInit = false); void EnsureStateExists(TLuaStateId StateId, const std::string& Name, bool DontCallOnInit = false);
void RegisterEvent(const std::string& EventName, TLuaStateId StateId, const std::string& FunctionName); void RegisterEvent(const std::string& EventName, TLuaStateId StateId, const std::string& FunctionName);
[[nodiscard]] std::vector<std::shared_ptr<TLuaResult>> TriggerEvent(const std::string& EventName); [[nodiscard]] std::vector<std::shared_ptr<TLuaResult>> TriggerEvent(const std::string& EventName);
std::set<std::string> GetEventHandlersForState(const std::string& EventName, TLuaStateId StateId);
static constexpr const char* BeamMPFnNotFoundError = "BEAMMP_FN_NOT_FOUND"; static constexpr const char* BeamMPFnNotFoundError = "BEAMMP_FN_NOT_FOUND";
@@ -61,12 +65,16 @@ private:
public: public:
StateThreadData(const std::string& Name, std::atomic_bool& Shutdown, TLuaStateId StateId, TLuaEngine& Engine); StateThreadData(const std::string& Name, std::atomic_bool& Shutdown, TLuaStateId StateId, TLuaEngine& Engine);
StateThreadData(const StateThreadData&) = delete; StateThreadData(const StateThreadData&) = delete;
~StateThreadData() noexcept { beammp_debug("\"" + mStateId + "\" destroyed"); }
[[nodiscard]] std::shared_ptr<TLuaResult> EnqueueScript(const std::shared_ptr<std::string>& Script); [[nodiscard]] std::shared_ptr<TLuaResult> EnqueueScript(const std::shared_ptr<std::string>& Script);
[[nodiscard]] std::shared_ptr<TLuaResult> EnqueueFunctionCall(const std::string& FunctionName); [[nodiscard]] std::shared_ptr<TLuaResult> EnqueueFunctionCall(const std::string& FunctionName);
void RegisterEvent(const std::string& EventName, const std::string& FunctionName); void RegisterEvent(const std::string& EventName, const std::string& FunctionName);
void operator()() override; void operator()() override;
private: private:
sol::table Lua_TriggerGlobalEvent(const std::string& EventName);
sol::table Lua_TriggerLocalEvent(const std::string& EventName);
std::string mName; std::string mName;
std::atomic_bool& mShutdown; std::atomic_bool& mShutdown;
TLuaStateId mStateId; TLuaStateId mStateId;
+2
View File
@@ -7,6 +7,8 @@ static std::string LuaToString(const sol::object& Value, size_t Indent = 1) {
return Value.as<std::string>(); return Value.as<std::string>();
case sol::type::number: case sol::type::number:
return std::to_string(Value.as<float>()); return std::to_string(Value.as<float>());
case sol::type::nil:
return "<nil>";
case sol::type::boolean: case sol::type::boolean:
return Value.as<bool>() ? "true" : "false"; return Value.as<bool>() ? "true" : "false";
case sol::type::table: { case sol::type::table: {
+6 -7
View File
@@ -62,13 +62,12 @@ TConsole::TConsole() {
beammp_info("Lua not started yet, please try again in a second"); beammp_info("Lua not started yet, please try again in a second");
} else { } else {
auto Future = mLuaEngine->EnqueueScript(mStateId, std::make_shared<std::string>(cmd)); auto Future = mLuaEngine->EnqueueScript(mStateId, std::make_shared<std::string>(cmd));
// wait for it to finish while (!Future->Ready) {
/*while (!Future->Ready) { std::this_thread::sleep_for(std::chrono::milliseconds(1));
std::this_thread::sleep_for(std::chrono::milliseconds(1)); }
} if (Future->Error) {
if (Future->Error) { beammp_lua_error(Future->ErrorMessage);
beammp_error(Future->ErrorMessage); }
}*/
} }
} }
}; };
+56 -26
View File
@@ -148,6 +148,54 @@ std::vector<std::shared_ptr<TLuaResult>> TLuaEngine::TriggerEvent(const std::str
return Results; return Results;
} }
std::set<std::string> 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<std::vector<std::shared_ptr<TLuaResult>>>("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<std::vector<std::shared_ptr<TLuaResult>>>("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) TLuaEngine::StateThreadData::StateThreadData(const std::string& Name, std::atomic_bool& Shutdown, TLuaStateId StateId, TLuaEngine& Engine)
: mName(Name) : mName(Name)
, mShutdown(Shutdown) , mShutdown(Shutdown)
@@ -167,31 +215,11 @@ TLuaEngine::StateThreadData::StateThreadData(const std::string& Name, std::atomi
}); });
Table.set_function("TriggerGlobalEvent", Table.set_function("TriggerGlobalEvent",
[&](const std::string& EventName) -> sol::table { [&](const std::string& EventName) -> sol::table {
auto Return = mEngine->TriggerEvent(EventName); return Lua_TriggerGlobalEvent(EventName);
beammp_debug("Triggering event \"" + EventName + "\" in \"" + mStateId + "\""); });
sol::state_view StateView(mState); Table.set_function("TriggerLocalEvent",
sol::table AsyncEventReturn = StateView.create_table(); [&](const std::string& EventName) -> sol::table {
AsyncEventReturn["ReturnValueImpl"] = Return; return Lua_TriggerLocalEvent(EventName);
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<std::vector<std::shared_ptr<TLuaResult>>>("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;
}); });
Table.create_named("Settings", Table.create_named("Settings",
"Debug", 0, "Debug", 0,
@@ -214,9 +242,10 @@ std::shared_ptr<TLuaResult> TLuaEngine::StateThreadData::EnqueueScript(const std
std::shared_ptr<TLuaResult> TLuaEngine::StateThreadData::EnqueueFunctionCall(const std::string& FunctionName) { std::shared_ptr<TLuaResult> TLuaEngine::StateThreadData::EnqueueFunctionCall(const std::string& FunctionName) {
beammp_debug("calling \"" + FunctionName + "\" in \"" + mName + "\""); beammp_debug("calling \"" + FunctionName + "\" in \"" + mName + "\"");
std::unique_lock Lock(mStateFunctionQueueMutex);
auto Result = std::make_shared<TLuaResult>(); auto Result = std::make_shared<TLuaResult>();
Result->StateId = mStateId; Result->StateId = mStateId;
Result->Function = FunctionName;
std::unique_lock Lock(mStateFunctionQueueMutex);
mStateFunctionQueue.push({ FunctionName, Result }); mStateFunctionQueue.push({ FunctionName, Result });
return Result; return Result;
} }
@@ -277,6 +306,7 @@ void TLuaEngine::StateThreadData::operator()() {
} }
} }
} }
std::this_thread::sleep_for(std::chrono::milliseconds(10));
} }
} }