mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2026-04-08 16:56:08 +00:00
Lua: working events, global and local
This commit is contained in:
@@ -8,10 +8,10 @@
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <toml11/toml.hpp>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
#define SOL_ALL_SAFETIES_ON 1
|
||||
#include <sol/sol.hpp>
|
||||
@@ -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<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";
|
||||
|
||||
@@ -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<TLuaResult> EnqueueScript(const std::shared_ptr<std::string>& Script);
|
||||
[[nodiscard]] std::shared_ptr<TLuaResult> 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;
|
||||
|
||||
@@ -7,6 +7,8 @@ static std::string LuaToString(const sol::object& Value, size_t Indent = 1) {
|
||||
return Value.as<std::string>();
|
||||
case sol::type::number:
|
||||
return std::to_string(Value.as<float>());
|
||||
case sol::type::nil:
|
||||
return "<nil>";
|
||||
case sol::type::boolean:
|
||||
return Value.as<bool>() ? "true" : "false";
|
||||
case sol::type::table: {
|
||||
|
||||
@@ -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<std::string>(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -148,6 +148,54 @@ std::vector<std::shared_ptr<TLuaResult>> TLuaEngine::TriggerEvent(const std::str
|
||||
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)
|
||||
: 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<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;
|
||||
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<TLuaResult> TLuaEngine::StateThreadData::EnqueueScript(const std
|
||||
|
||||
std::shared_ptr<TLuaResult> TLuaEngine::StateThreadData::EnqueueFunctionCall(const std::string& FunctionName) {
|
||||
beammp_debug("calling \"" + FunctionName + "\" in \"" + mName + "\"");
|
||||
std::unique_lock Lock(mStateFunctionQueueMutex);
|
||||
auto Result = std::make_shared<TLuaResult>();
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user