mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2026-06-17 14:12:25 +00:00
Lua: Call local eventhandlers synchronously when TriggerGlobalEvent is called from inside a handling state
This commit is contained in:
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
- CHANGED entire plugin Lua implementation (rewrite)
|
- CHANGED entire plugin Lua implementation (rewrite)
|
||||||
- CHANGED moved *all* functions into MP.\*
|
- 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.GetOSName() -> string`: Returns "Linux", "Windows" or "Other"
|
||||||
- ADDED `MP.GetServerVersion() -> string`: Returns major,minor,patch version
|
- ADDED `MP.GetServerVersion() -> string`: Returns major,minor,patch version
|
||||||
- ADDED `MP.IsPlayerGuest(id) -> boolean`: Whether player with id is a guest
|
- ADDED `MP.IsPlayerGuest(id) -> boolean`: Whether player with id is a guest
|
||||||
|
|||||||
@@ -60,7 +60,8 @@ 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);
|
||||||
template <typename... ArgsT>
|
template <typename... ArgsT>
|
||||||
[[nodiscard]] std::vector<std::shared_ptr<TLuaResult>> TriggerEvent(const std::string& EventName, ArgsT&&... Args) {
|
[[nodiscard]] std::vector<std::shared_ptr<TLuaResult>> TriggerEvent(const std::string& EventName, TLuaStateId IgnoreId, ArgsT&&... Args) {
|
||||||
|
beammp_info("TriggerEvent called from: ");
|
||||||
std::unique_lock Lock(mEventsMutex);
|
std::unique_lock Lock(mEventsMutex);
|
||||||
if (mEvents.find(EventName) == mEvents.end()) {
|
if (mEvents.find(EventName) == mEvents.end()) {
|
||||||
return {};
|
return {};
|
||||||
@@ -69,7 +70,9 @@ public:
|
|||||||
for (const auto& Event : mEvents.at(EventName)) {
|
for (const auto& Event : mEvents.at(EventName)) {
|
||||||
for (const auto& Function : Event.second) {
|
for (const auto& Function : Event.second) {
|
||||||
beammp_debug("TriggerEvent: triggering \"" + Function + "\" on \"" + Event.first + "\"");
|
beammp_debug("TriggerEvent: triggering \"" + Function + "\" on \"" + Event.first + "\"");
|
||||||
Results.push_back(EnqueueFunctionCall(Event.first, Function, { std::forward<ArgsT>(Args)... }));
|
if (Event.first != IgnoreId) {
|
||||||
|
Results.push_back(EnqueueFunctionCall(Event.first, Function, { std::forward<ArgsT>(Args)... }));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Results;
|
return Results;
|
||||||
@@ -95,8 +98,8 @@ private:
|
|||||||
void operator()() override;
|
void operator()() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sol::table Lua_TriggerGlobalEvent(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::table Lua_TriggerLocalEvent(const std::string& EventName, sol::variadic_args EventArgs);
|
||||||
sol::table Lua_GetPlayerIdentifiers(int ID);
|
sol::table Lua_GetPlayerIdentifiers(int ID);
|
||||||
sol::table Lua_GetPlayers();
|
sol::table Lua_GetPlayers();
|
||||||
std::string Lua_GetPlayerName(int ID);
|
std::string Lua_GetPlayerName(int ID);
|
||||||
|
|||||||
@@ -3,6 +3,9 @@
|
|||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "TLuaEngine.h"
|
#include "TLuaEngine.h"
|
||||||
|
|
||||||
|
#define SOL_ALL_SAFETIES_ON 1
|
||||||
|
#include <sol/sol.hpp>
|
||||||
|
|
||||||
static std::string LuaToString(const sol::object Value, size_t Indent = 1) {
|
static std::string LuaToString(const sol::object Value, size_t Indent = 1) {
|
||||||
switch (Value.get_type()) {
|
switch (Value.get_type()) {
|
||||||
case sol::type::userdata: {
|
case sol::type::userdata: {
|
||||||
|
|||||||
+29
-10
@@ -42,7 +42,7 @@ void TLuaEngine::operator()() {
|
|||||||
// lua engine main thread
|
// lua engine main thread
|
||||||
CollectAndInitPlugins();
|
CollectAndInitPlugins();
|
||||||
// now call all onInit's
|
// now call all onInit's
|
||||||
auto Futures = TriggerEvent("onInit");
|
auto Futures = TriggerEvent("onInit", "");
|
||||||
WaitForAll(Futures);
|
WaitForAll(Futures);
|
||||||
for (const auto& Future : Futures) {
|
for (const auto& Future : Futures) {
|
||||||
if (Future->Error && Future->ErrorMessage != BeamMPFnNotFoundError) {
|
if (Future->Error && Future->ErrorMessage != BeamMPFnNotFoundError) {
|
||||||
@@ -83,7 +83,7 @@ void TLuaEngine::CollectAndInitPlugins() {
|
|||||||
beammp_error("\"" + Dir.path().string() + "\" is not a directory, skipping");
|
beammp_error("\"" + Dir.path().string() + "\" is not a directory, skipping");
|
||||||
} else {
|
} else {
|
||||||
beammp_debug("found plugin directory: " + Path.string());
|
beammp_debug("found plugin directory: " + Path.string());
|
||||||
TLuaPluginConfig Config { GenerateUniqueStateId() };
|
TLuaPluginConfig Config { Path.string() };
|
||||||
FindAndParseConfig(Path, Config);
|
FindAndParseConfig(Path, Config);
|
||||||
InitializePlugin(Path, Config);
|
InitializePlugin(Path, Config);
|
||||||
}
|
}
|
||||||
@@ -148,8 +148,26 @@ std::set<std::string> TLuaEngine::GetEventHandlersForState(const std::string& Ev
|
|||||||
return mEvents[EventName][StateId];
|
return mEvents[EventName][StateId];
|
||||||
}
|
}
|
||||||
|
|
||||||
sol::table TLuaEngine::StateThreadData::Lua_TriggerGlobalEvent(const std::string& EventName) {
|
sol::table TLuaEngine::StateThreadData::Lua_TriggerGlobalEvent(const std::string& EventName, sol::variadic_args EventArgs) {
|
||||||
auto Return = mEngine->TriggerEvent(EventName);
|
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<TLuaResult>();
|
||||||
|
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 + "\"");
|
beammp_debug("Triggering event \"" + EventName + "\" in \"" + mStateId + "\"");
|
||||||
sol::state_view StateView(mState);
|
sol::state_view StateView(mState);
|
||||||
sol::table AsyncEventReturn = StateView.create_table();
|
sol::table AsyncEventReturn = StateView.create_table();
|
||||||
@@ -180,12 +198,13 @@ sol::table TLuaEngine::StateThreadData::Lua_TriggerGlobalEvent(const std::string
|
|||||||
return AsyncEventReturn;
|
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();
|
sol::table Result = mStateView.create_table();
|
||||||
for (const auto& Handler : mEngine->GetEventHandlersForState(EventName, mStateId)) {
|
for (const auto& Handler : mEngine->GetEventHandlersForState(EventName, mStateId)) {
|
||||||
auto Fn = mStateView[Handler];
|
auto Fn = mStateView[Handler];
|
||||||
if (Fn.valid() && Fn.get_type() == sol::type::function) {
|
if (Fn.valid() && Fn.get_type() == sol::type::function) {
|
||||||
Result.add(Fn());
|
Result.add(Fn(EventArgs));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Result;
|
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) {
|
Table.set_function("RegisterEvent", [this](const std::string& EventName, const std::string& FunctionName) {
|
||||||
RegisterEvent(EventName, FunctionName);
|
RegisterEvent(EventName, FunctionName);
|
||||||
});
|
});
|
||||||
Table.set_function("TriggerGlobalEvent", [&](const std::string& EventName) -> sol::table {
|
Table.set_function("TriggerGlobalEvent", [&](const std::string& EventName, sol::variadic_args EventArgs) -> sol::table {
|
||||||
return Lua_TriggerGlobalEvent(EventName);
|
return Lua_TriggerGlobalEvent(EventName, EventArgs);
|
||||||
});
|
});
|
||||||
Table.set_function("TriggerLocalEvent", [&](const std::string& EventName) -> sol::table {
|
Table.set_function("TriggerLocalEvent", [&](const std::string& EventName, sol::variadic_args EventArgs) -> sol::table {
|
||||||
return Lua_TriggerLocalEvent(EventName);
|
return Lua_TriggerLocalEvent(EventName, EventArgs);
|
||||||
});
|
});
|
||||||
Table.set_function("TriggerClientEvent", &LuaAPI::MP::TriggerClientEvent);
|
Table.set_function("TriggerClientEvent", &LuaAPI::MP::TriggerClientEvent);
|
||||||
Table.set_function("GetPlayerCount", &LuaAPI::MP::GetPlayerCount);
|
Table.set_function("GetPlayerCount", &LuaAPI::MP::GetPlayerCount);
|
||||||
|
|||||||
+5
-5
@@ -307,7 +307,7 @@ void TNetwork::Authentication(const TConnection& ClientConnection) {
|
|||||||
return true;
|
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);
|
TLuaEngine::WaitForAll(Futures);
|
||||||
bool NotAllowed = std::any_of(Futures.begin(), Futures.end(),
|
bool NotAllowed = std::any_of(Futures.begin(), Futures.end(),
|
||||||
[](const std::shared_ptr<TLuaResult>& Result) {
|
[](const std::shared_ptr<TLuaResult>& Result) {
|
||||||
@@ -570,7 +570,7 @@ void TNetwork::OnDisconnect(const std::weak_ptr<TClient>& ClientPtr, bool kicked
|
|||||||
Packet = ("L") + c.GetName() + (" left the server!");
|
Packet = ("L") + c.GetName() + (" left the server!");
|
||||||
SendToAll(&c, Packet, false, true);
|
SendToAll(&c, Packet, false, true);
|
||||||
Packet.clear();
|
Packet.clear();
|
||||||
auto Futures = LuaAPI::MP::Engine->TriggerEvent("onPlayerDisconnect", c.GetID());
|
auto Futures = LuaAPI::MP::Engine->TriggerEvent("onPlayerDisconnect", "", c.GetID());
|
||||||
beammp_ignore(Futures);
|
beammp_ignore(Futures);
|
||||||
if (c.GetTCPSock())
|
if (c.GetTCPSock())
|
||||||
CloseSocketProper(c.GetTCPSock());
|
CloseSocketProper(c.GetTCPSock());
|
||||||
@@ -605,13 +605,13 @@ void TNetwork::OnConnect(const std::weak_ptr<TClient>& c) {
|
|||||||
auto LockedClient = c.lock();
|
auto LockedClient = c.lock();
|
||||||
LockedClient->SetID(OpenID());
|
LockedClient->SetID(OpenID());
|
||||||
beammp_info("Assigned ID " + std::to_string(LockedClient->GetID()) + " to " + LockedClient->GetName());
|
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);
|
SyncResources(*LockedClient);
|
||||||
if (LockedClient->GetStatus() < 0)
|
if (LockedClient->GetStatus() < 0)
|
||||||
return;
|
return;
|
||||||
(void)Respond(*LockedClient, "M" + Application::Settings.MapName, true); //Send the Map on connect
|
(void)Respond(*LockedClient, "M" + Application::Settings.MapName, true); //Send the Map on connect
|
||||||
beammp_info(LockedClient->GetName() + " : Connected");
|
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) {
|
void TNetwork::SyncResources(TClient& c) {
|
||||||
@@ -810,7 +810,7 @@ bool TNetwork::SyncClient(const std::weak_ptr<TClient>& c) {
|
|||||||
// ignore error
|
// ignore error
|
||||||
(void)SendToAll(LockedClient.get(), ("JWelcome ") + LockedClient->GetName() + "!", false, true);
|
(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);
|
LockedClient->SetIsSyncing(true);
|
||||||
bool Return = false;
|
bool Return = false;
|
||||||
bool res = true;
|
bool res = true;
|
||||||
|
|||||||
+6
-6
@@ -124,7 +124,7 @@ void TServer::GlobalParser(const std::weak_ptr<TClient>& Client, std::string Pac
|
|||||||
beammp_debug(std::string(("got 'C' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")"));
|
beammp_debug(std::string(("got 'C' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")"));
|
||||||
if (Packet.length() < 4 || Packet.find(':', 3) == std::string::npos)
|
if (Packet.length() < 4 || Packet.find(':', 3) == std::string::npos)
|
||||||
break;
|
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);
|
TLuaEngine::WaitForAll(Futures);
|
||||||
LogChatMessage(LockedClient->GetName(), LockedClient->GetID(), Packet.substr(Packet.find(':', 3) + 1)); // FIXME: this needs to be adjusted once lua is merged
|
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(),
|
if (std::any_of(Futures.begin(), Futures.end(),
|
||||||
@@ -162,7 +162,7 @@ void TServer::HandleEvent(TClient& c, const std::string& Data) {
|
|||||||
Name = t;
|
Name = t;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
beammp_ignore(LuaAPI::MP::Engine->TriggerEvent(Name, c.GetID(), t));
|
beammp_ignore(LuaAPI::MP::Engine->TriggerEvent(Name, "", c.GetID(), t));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -213,7 +213,7 @@ void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Networ
|
|||||||
|
|
||||||
std::string CarJson = Packet.substr(5);
|
std::string CarJson = Packet.substr(5);
|
||||||
Packet = "Os:" + c.GetRoles() + ":" + c.GetName() + ":" + std::to_string(c.GetID()) + "-" + std::to_string(CarID) + ":" + CarJson;
|
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);
|
TLuaEngine::WaitForAll(Futures);
|
||||||
bool ShouldntSpawn = std::any_of(Futures.begin(), Futures.end(),
|
bool ShouldntSpawn = std::any_of(Futures.begin(), Futures.end(),
|
||||||
[](const std::shared_ptr<TLuaResult>& Result) {
|
[](const std::shared_ptr<TLuaResult>& Result) {
|
||||||
@@ -244,7 +244,7 @@ void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Networ
|
|||||||
VID = stoi(vid);
|
VID = stoi(vid);
|
||||||
}
|
}
|
||||||
if (PID != -1 && VID != -1 && PID == c.GetID()) {
|
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);
|
TLuaEngine::WaitForAll(Futures);
|
||||||
bool ShouldntAllow = std::any_of(Futures.begin(), Futures.end(),
|
bool ShouldntAllow = std::any_of(Futures.begin(), Futures.end(),
|
||||||
[](const std::shared_ptr<TLuaResult>& Result) {
|
[](const std::shared_ptr<TLuaResult>& Result) {
|
||||||
@@ -282,7 +282,7 @@ void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Networ
|
|||||||
c.SetUnicycleID(-1);
|
c.SetUnicycleID(-1);
|
||||||
}
|
}
|
||||||
Network.SendToAll(nullptr, Packet, true, true);
|
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);
|
c.DeleteCar(VID);
|
||||||
beammp_debug(c.GetName() + (" deleted car with ID ") + std::to_string(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()) {
|
if (PID != -1 && VID != -1 && PID == c.GetID()) {
|
||||||
Data = Data.substr(Data.find('{'));
|
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);
|
Network.SendToAll(&c, Packet, false, true);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|||||||
+1
-1
@@ -28,7 +28,7 @@ int main(int argc, char** argv) try {
|
|||||||
bool Shutdown = false;
|
bool Shutdown = false;
|
||||||
Application::RegisterShutdownHandler([&Shutdown] { Shutdown = true; });
|
Application::RegisterShutdownHandler([&Shutdown] { Shutdown = true; });
|
||||||
Application::RegisterShutdownHandler([] {
|
Application::RegisterShutdownHandler([] {
|
||||||
auto Futures = LuaAPI::MP::Engine->TriggerEvent("onShutdown");
|
auto Futures = LuaAPI::MP::Engine->TriggerEvent("onShutdown", "");
|
||||||
TLuaEngine::WaitForAll(Futures);
|
TLuaEngine::WaitForAll(Futures);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user