diff --git a/Changelog.md b/Changelog.md index e54d460..e764192 100644 --- a/Changelog.md +++ b/Changelog.md @@ -2,7 +2,7 @@ - CHANGED entire plugin Lua implementation (rewrite) - CHANGED moved *all* functions into MP.\* -- CHANGED all files of a Lua plugin to share a Lua state +- CHANGED all files of a Lua plugin to share a Lua state (no more state-per-file) - ADDED `MP.GetOSName() -> string`: Returns "Linux", "Windows" or "Other" - ADDED `MP.GetServerVersion() -> string`: Returns major,minor,patch version - ADDED `MP.IsPlayerGuest(id) -> boolean`: Whether player with id is a guest diff --git a/include/TLuaEngine.h b/include/TLuaEngine.h index 8251a05..569122b 100644 --- a/include/TLuaEngine.h +++ b/include/TLuaEngine.h @@ -60,7 +60,8 @@ public: void EnsureStateExists(TLuaStateId StateId, const std::string& Name, bool DontCallOnInit = false); void RegisterEvent(const std::string& EventName, TLuaStateId StateId, const std::string& FunctionName); template - [[nodiscard]] std::vector> TriggerEvent(const std::string& EventName, ArgsT&&... Args) { + [[nodiscard]] std::vector> TriggerEvent(const std::string& EventName, TLuaStateId IgnoreId, ArgsT&&... Args) { + beammp_info("TriggerEvent called from: "); std::unique_lock Lock(mEventsMutex); if (mEvents.find(EventName) == mEvents.end()) { return {}; @@ -69,7 +70,9 @@ public: for (const auto& Event : mEvents.at(EventName)) { for (const auto& Function : Event.second) { beammp_debug("TriggerEvent: triggering \"" + Function + "\" on \"" + Event.first + "\""); - Results.push_back(EnqueueFunctionCall(Event.first, Function, { std::forward(Args)... })); + if (Event.first != IgnoreId) { + Results.push_back(EnqueueFunctionCall(Event.first, Function, { std::forward(Args)... })); + } } } return Results; @@ -95,8 +98,8 @@ private: void operator()() override; private: - sol::table Lua_TriggerGlobalEvent(const std::string& EventName); - sol::table Lua_TriggerLocalEvent(const std::string& EventName); + sol::table Lua_TriggerGlobalEvent(const std::string& EventName, sol::variadic_args EventArgs); + sol::table Lua_TriggerLocalEvent(const std::string& EventName, sol::variadic_args EventArgs); sol::table Lua_GetPlayerIdentifiers(int ID); sol::table Lua_GetPlayers(); std::string Lua_GetPlayerName(int ID); diff --git a/src/LuaAPI.cpp b/src/LuaAPI.cpp index fbf34cc..2c8472a 100644 --- a/src/LuaAPI.cpp +++ b/src/LuaAPI.cpp @@ -3,6 +3,9 @@ #include "Common.h" #include "TLuaEngine.h" +#define SOL_ALL_SAFETIES_ON 1 +#include + static std::string LuaToString(const sol::object Value, size_t Indent = 1) { switch (Value.get_type()) { case sol::type::userdata: { diff --git a/src/TLuaEngine.cpp b/src/TLuaEngine.cpp index fbcb938..1ac0fe2 100644 --- a/src/TLuaEngine.cpp +++ b/src/TLuaEngine.cpp @@ -42,7 +42,7 @@ void TLuaEngine::operator()() { // lua engine main thread CollectAndInitPlugins(); // now call all onInit's - auto Futures = TriggerEvent("onInit"); + auto Futures = TriggerEvent("onInit", ""); WaitForAll(Futures); for (const auto& Future : Futures) { if (Future->Error && Future->ErrorMessage != BeamMPFnNotFoundError) { @@ -83,7 +83,7 @@ void TLuaEngine::CollectAndInitPlugins() { beammp_error("\"" + Dir.path().string() + "\" is not a directory, skipping"); } else { beammp_debug("found plugin directory: " + Path.string()); - TLuaPluginConfig Config { GenerateUniqueStateId() }; + TLuaPluginConfig Config { Path.string() }; FindAndParseConfig(Path, Config); InitializePlugin(Path, Config); } @@ -148,8 +148,26 @@ std::set TLuaEngine::GetEventHandlersForState(const std::string& Ev return mEvents[EventName][StateId]; } -sol::table TLuaEngine::StateThreadData::Lua_TriggerGlobalEvent(const std::string& EventName) { - auto Return = mEngine->TriggerEvent(EventName); +sol::table TLuaEngine::StateThreadData::Lua_TriggerGlobalEvent(const std::string& EventName, sol::variadic_args EventArgs) { + auto Return = mEngine->TriggerEvent(EventName, mStateId, EventArgs); + // TODO Synchronous call to the event handlers + auto MyHandlers = mEngine->GetEventHandlersForState(EventName, mStateId); + for (const auto& Handler : MyHandlers) { + auto Fn = mStateView[Handler]; + if (Fn.valid()) { + auto LuaResult = Fn(EventArgs); + auto Result = std::make_shared(); + Result->Ready = true; + if (LuaResult.valid()) { + Result->Error = false; + Result->Result = LuaResult; + } else { + Result->Error = true; + Result->ErrorMessage = "Function result in TriggerGlobalEvent was invalid"; + } + Return.push_back(Result); + } + } beammp_debug("Triggering event \"" + EventName + "\" in \"" + mStateId + "\""); sol::state_view StateView(mState); sol::table AsyncEventReturn = StateView.create_table(); @@ -180,12 +198,13 @@ sol::table TLuaEngine::StateThreadData::Lua_TriggerGlobalEvent(const std::string return AsyncEventReturn; } -sol::table TLuaEngine::StateThreadData::Lua_TriggerLocalEvent(const std::string& EventName) { +sol::table TLuaEngine::StateThreadData::Lua_TriggerLocalEvent(const std::string& EventName, sol::variadic_args EventArgs) { + // TODO: make asynchronous? sol::table Result = mStateView.create_table(); for (const auto& Handler : mEngine->GetEventHandlersForState(EventName, mStateId)) { auto Fn = mStateView[Handler]; if (Fn.valid() && Fn.get_type() == sol::type::function) { - Result.add(Fn()); + Result.add(Fn(EventArgs)); } } return Result; @@ -282,11 +301,11 @@ TLuaEngine::StateThreadData::StateThreadData(const std::string& Name, std::atomi Table.set_function("RegisterEvent", [this](const std::string& EventName, const std::string& FunctionName) { RegisterEvent(EventName, FunctionName); }); - Table.set_function("TriggerGlobalEvent", [&](const std::string& EventName) -> sol::table { - return Lua_TriggerGlobalEvent(EventName); + Table.set_function("TriggerGlobalEvent", [&](const std::string& EventName, sol::variadic_args EventArgs) -> sol::table { + return Lua_TriggerGlobalEvent(EventName, EventArgs); }); - Table.set_function("TriggerLocalEvent", [&](const std::string& EventName) -> sol::table { - return Lua_TriggerLocalEvent(EventName); + Table.set_function("TriggerLocalEvent", [&](const std::string& EventName, sol::variadic_args EventArgs) -> sol::table { + return Lua_TriggerLocalEvent(EventName, EventArgs); }); Table.set_function("TriggerClientEvent", &LuaAPI::MP::TriggerClientEvent); Table.set_function("GetPlayerCount", &LuaAPI::MP::GetPlayerCount); diff --git a/src/TNetwork.cpp b/src/TNetwork.cpp index c31f334..4c08fc6 100644 --- a/src/TNetwork.cpp +++ b/src/TNetwork.cpp @@ -307,7 +307,7 @@ void TNetwork::Authentication(const TConnection& ClientConnection) { return true; }); - auto Futures = LuaAPI::MP::Engine->TriggerEvent("onPlayerAuth", Client->GetName(), Client->GetRoles(), Client->IsGuest()); + auto Futures = LuaAPI::MP::Engine->TriggerEvent("onPlayerAuth", "", Client->GetName(), Client->GetRoles(), Client->IsGuest()); TLuaEngine::WaitForAll(Futures); bool NotAllowed = std::any_of(Futures.begin(), Futures.end(), [](const std::shared_ptr& Result) { @@ -570,7 +570,7 @@ void TNetwork::OnDisconnect(const std::weak_ptr& ClientPtr, bool kicked Packet = ("L") + c.GetName() + (" left the server!"); SendToAll(&c, Packet, false, true); Packet.clear(); - auto Futures = LuaAPI::MP::Engine->TriggerEvent("onPlayerDisconnect", c.GetID()); + auto Futures = LuaAPI::MP::Engine->TriggerEvent("onPlayerDisconnect", "", c.GetID()); beammp_ignore(Futures); if (c.GetTCPSock()) CloseSocketProper(c.GetTCPSock()); @@ -605,13 +605,13 @@ void TNetwork::OnConnect(const std::weak_ptr& c) { auto LockedClient = c.lock(); LockedClient->SetID(OpenID()); beammp_info("Assigned ID " + std::to_string(LockedClient->GetID()) + " to " + LockedClient->GetName()); - beammp_ignore(LuaAPI::MP::Engine->TriggerEvent("onPlayerConnecting", LockedClient->GetID())); + beammp_ignore(LuaAPI::MP::Engine->TriggerEvent("onPlayerConnecting", "", LockedClient->GetID())); SyncResources(*LockedClient); if (LockedClient->GetStatus() < 0) return; (void)Respond(*LockedClient, "M" + Application::Settings.MapName, true); //Send the Map on connect beammp_info(LockedClient->GetName() + " : Connected"); - beammp_ignore(LuaAPI::MP::Engine->TriggerEvent("onPlayerJoining", LockedClient->GetID())); + beammp_ignore(LuaAPI::MP::Engine->TriggerEvent("onPlayerJoining", "", LockedClient->GetID())); } void TNetwork::SyncResources(TClient& c) { @@ -810,7 +810,7 @@ bool TNetwork::SyncClient(const std::weak_ptr& c) { // ignore error (void)SendToAll(LockedClient.get(), ("JWelcome ") + LockedClient->GetName() + "!", false, true); - beammp_ignore(LuaAPI::MP::Engine->TriggerEvent("onPlayerJoin", LockedClient->GetID())); + beammp_ignore(LuaAPI::MP::Engine->TriggerEvent("onPlayerJoin", "", LockedClient->GetID())); LockedClient->SetIsSyncing(true); bool Return = false; bool res = true; diff --git a/src/TServer.cpp b/src/TServer.cpp index f2acee6..abf328a 100644 --- a/src/TServer.cpp +++ b/src/TServer.cpp @@ -124,7 +124,7 @@ void TServer::GlobalParser(const std::weak_ptr& Client, std::string Pac beammp_debug(std::string(("got 'C' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")")); if (Packet.length() < 4 || Packet.find(':', 3) == std::string::npos) break; - auto Futures = LuaAPI::MP::Engine->TriggerEvent("onChatMessage", LockedClient->GetID(), LockedClient->GetName(), Packet.substr(Packet.find(':', 3) + 1)); + auto Futures = LuaAPI::MP::Engine->TriggerEvent("onChatMessage", "", LockedClient->GetID(), LockedClient->GetName(), Packet.substr(Packet.find(':', 3) + 1)); TLuaEngine::WaitForAll(Futures); LogChatMessage(LockedClient->GetName(), LockedClient->GetID(), Packet.substr(Packet.find(':', 3) + 1)); // FIXME: this needs to be adjusted once lua is merged if (std::any_of(Futures.begin(), Futures.end(), @@ -162,7 +162,7 @@ void TServer::HandleEvent(TClient& c, const std::string& Data) { Name = t; break; case 2: - beammp_ignore(LuaAPI::MP::Engine->TriggerEvent(Name, c.GetID(), t)); + beammp_ignore(LuaAPI::MP::Engine->TriggerEvent(Name, "", c.GetID(), t)); break; default: break; @@ -213,7 +213,7 @@ void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Networ std::string CarJson = Packet.substr(5); Packet = "Os:" + c.GetRoles() + ":" + c.GetName() + ":" + std::to_string(c.GetID()) + "-" + std::to_string(CarID) + ":" + CarJson; - auto Futures = LuaAPI::MP::Engine->TriggerEvent("onVehicleSpawn", c.GetID(), CarID, Packet.substr(3)); + auto Futures = LuaAPI::MP::Engine->TriggerEvent("onVehicleSpawn", "", c.GetID(), CarID, Packet.substr(3)); TLuaEngine::WaitForAll(Futures); bool ShouldntSpawn = std::any_of(Futures.begin(), Futures.end(), [](const std::shared_ptr& Result) { @@ -244,7 +244,7 @@ void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Networ VID = stoi(vid); } if (PID != -1 && VID != -1 && PID == c.GetID()) { - auto Futures = LuaAPI::MP::Engine->TriggerEvent("onVehicleEdited", c.GetID(), VID, Packet.substr(3)); + auto Futures = LuaAPI::MP::Engine->TriggerEvent("onVehicleEdited", "", c.GetID(), VID, Packet.substr(3)); TLuaEngine::WaitForAll(Futures); bool ShouldntAllow = std::any_of(Futures.begin(), Futures.end(), [](const std::shared_ptr& Result) { @@ -282,7 +282,7 @@ void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Networ c.SetUnicycleID(-1); } Network.SendToAll(nullptr, Packet, true, true); - beammp_ignore(LuaAPI::MP::Engine->TriggerEvent("onVehicleDeleted", c.GetID(), VID)); + beammp_ignore(LuaAPI::MP::Engine->TriggerEvent("onVehicleDeleted", "", c.GetID(), VID)); c.DeleteCar(VID); beammp_debug(c.GetName() + (" deleted car with ID ") + std::to_string(VID)); } @@ -300,7 +300,7 @@ void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Networ if (PID != -1 && VID != -1 && PID == c.GetID()) { Data = Data.substr(Data.find('{')); - beammp_ignore(LuaAPI::MP::Engine->TriggerEvent("onVehicleReset", c.GetID(), VID, Data)); + beammp_ignore(LuaAPI::MP::Engine->TriggerEvent("onVehicleReset", "", c.GetID(), VID, Data)); Network.SendToAll(&c, Packet, false, true); } return; diff --git a/src/main.cpp b/src/main.cpp index 5d2a092..d8c5255 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -28,7 +28,7 @@ int main(int argc, char** argv) try { bool Shutdown = false; Application::RegisterShutdownHandler([&Shutdown] { Shutdown = true; }); Application::RegisterShutdownHandler([] { - auto Futures = LuaAPI::MP::Engine->TriggerEvent("onShutdown"); + auto Futures = LuaAPI::MP::Engine->TriggerEvent("onShutdown", ""); TLuaEngine::WaitForAll(Futures); });