Lua: Almost Working events, all triggers working

This commit is contained in:
Lion Kortlepel 2021-09-17 00:21:43 +02:00
parent cb1eb40def
commit a44050f0f1
No known key found for this signature in database
GPG Key ID: 4322FF2B4C71259B
9 changed files with 157 additions and 93 deletions

View File

@ -133,6 +133,9 @@ void RegisterThread(const std::string str);
Application::Console().Write(_this_location + std::string("[DEBUG] ") + (x)); \ Application::Console().Write(_this_location + std::string("[DEBUG] ") + (x)); \
} \ } \
} while (false) } while (false)
// for those times when you just need to ignore something :^)
// explicity disables a [[nodiscard]] warning
#define beammp_ignore(x) (void)x
#define Biggest 30000 #define Biggest 30000
std::string Comp(std::string Data); std::string Comp(std::string Data);

View File

@ -6,12 +6,12 @@
namespace LuaAPI { namespace LuaAPI {
void Print(sol::variadic_args); void Print(sol::variadic_args);
namespace MP { namespace MP {
static inline TLuaEngine* Engine { nullptr }; extern TLuaEngine* Engine;
std::string GetOSName(); std::string GetOSName();
std::tuple<int, int, int> GetServerVersion(); std::tuple<int, int, int> GetServerVersion();
bool TriggerClientEvent(int PlayerID, const std::string& EventName, const std::string& Data); bool TriggerClientEvent(int PlayerID, const std::string& EventName, const std::string& Data);
size_t GetPlayerCount() { return Engine->Server().ClientCount(); } inline size_t GetPlayerCount() { return Engine->Server().ClientCount(); }
void DropPlayer(int ID, std::optional<std::string> MaybeReason); void DropPlayer(int ID, std::optional<std::string> MaybeReason);
void SendChatMessage(int ID, const std::string& Message); void SendChatMessage(int ID, const std::string& Message);
void RemoveVehicle(int PlayerID, int VehicleID); void RemoveVehicle(int PlayerID, int VehicleID);

View File

@ -4,6 +4,7 @@
#include "TServer.h" #include "TServer.h"
#include <any> #include <any>
#include <filesystem> #include <filesystem>
#include <initializer_list>
#include <lua.hpp> #include <lua.hpp>
#include <memory> #include <memory>
#include <mutex> #include <mutex>
@ -40,21 +41,39 @@ struct TLuaPluginConfig {
class TLuaEngine : IThreaded { class TLuaEngine : IThreaded {
public: public:
TLuaEngine(TServer& Server, TNetwork& Network); TLuaEngine();
~TLuaEngine() noexcept { ~TLuaEngine() noexcept {
beammp_debug("Lua Engine terminated"); beammp_debug("Lua Engine terminated");
} }
void operator()() override; void operator()() override;
TNetwork& Network() { return mNetwork; } TNetwork& Network() { return *mNetwork; }
TServer& Server() { return mServer; } TServer& Server() { return *mServer; }
void SetNetwork(TNetwork* Network) { mNetwork = Network; }
void SetServer(TServer* Server) { mServer = Server; }
static void WaitForAll(std::vector<std::shared_ptr<TLuaResult>>& Results);
[[nodiscard]] std::shared_ptr<TLuaResult> EnqueueScript(TLuaStateId StateID, const std::shared_ptr<std::string>& Script); [[nodiscard]] std::shared_ptr<TLuaResult> EnqueueScript(TLuaStateId StateID, const std::shared_ptr<std::string>& Script);
[[nodiscard]] std::shared_ptr<TLuaResult> EnqueueFunctionCall(TLuaStateId StateID, const std::string& FunctionName); [[nodiscard]] std::shared_ptr<TLuaResult> EnqueueFunctionCall(TLuaStateId StateID, const std::string& FunctionName, const std::initializer_list<std::any>& Args);
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); template <typename... ArgsT>
[[nodiscard]] std::vector<std::shared_ptr<TLuaResult>> TriggerEvent(const std::string& EventName, ArgsT&&... Args) {
std::unique_lock Lock(mEventsMutex);
if (mEvents.find(EventName) == mEvents.end()) {
return {};
}
std::vector<std::shared_ptr<TLuaResult>> Results;
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<ArgsT>(Args)... }));
}
}
return Results;
}
std::set<std::string> GetEventHandlersForState(const std::string& EventName, TLuaStateId StateId); 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";
@ -70,7 +89,7 @@ private:
StateThreadData(const StateThreadData&) = delete; StateThreadData(const StateThreadData&) = delete;
~StateThreadData() noexcept { beammp_debug("\"" + mStateId + "\" destroyed"); } ~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, const std::initializer_list<std::any>& Args);
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;
@ -87,14 +106,14 @@ private:
std::thread mThread; std::thread mThread;
std::queue<std::pair<std::shared_ptr<std::string>, std::shared_ptr<TLuaResult>>> mStateExecuteQueue; std::queue<std::pair<std::shared_ptr<std::string>, std::shared_ptr<TLuaResult>>> mStateExecuteQueue;
std::recursive_mutex mStateExecuteQueueMutex; std::recursive_mutex mStateExecuteQueueMutex;
std::queue<std::pair<std::string, std::shared_ptr<TLuaResult>>> mStateFunctionQueue; std::queue<std::tuple<std::string, std::shared_ptr<TLuaResult>, std::initializer_list<std::any>>> mStateFunctionQueue;
std::recursive_mutex mStateFunctionQueueMutex; std::recursive_mutex mStateFunctionQueueMutex;
TLuaEngine* mEngine; TLuaEngine* mEngine;
sol::state_view mStateView { mState }; sol::state_view mStateView { mState };
}; };
TNetwork& mNetwork; TNetwork* mNetwork;
TServer& mServer; TServer* mServer;
std::atomic_bool mShutdown { false }; std::atomic_bool mShutdown { false };
fs::path mResourceServerPath; fs::path mResourceServerPath;
std::vector<TLuaPlugin*> mLuaPlugins; std::vector<TLuaPlugin*> mLuaPlugins;
@ -104,10 +123,4 @@ private:
std::recursive_mutex mEventsMutex; std::recursive_mutex mEventsMutex;
}; };
#include <any> //std::any TriggerLuaEvent(const std::string& Event, bool local, TLuaPlugin* Caller, std::shared_ptr<TLuaArg> arg, bool Wait);
// DEAD CODE
struct TLuaArg {
std::vector<std::any> args;
void PushArgs(lua_State* State);
};
std::any TriggerLuaEvent(const std::string& Event, bool local, TLuaPlugin* Caller, std::shared_ptr<TLuaArg> arg, bool Wait);

View File

@ -4,11 +4,32 @@
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: {
std::stringstream ss;
ss << "[[userdata: " << Value.as<sol::userdata>().pointer() << "]]";
return ss.str();
}
case sol::type::thread: {
std::stringstream ss;
ss << "[[thread: " << Value.as<sol::thread>().pointer() << "]] {"
<< "\n";
for (size_t i = 0; i < Indent; ++i) {
ss << "\t";
}
ss << "status: " << std::to_string(int(Value.as<sol::thread>().status())) << "\n}";
return ss.str();
}
case sol::type::lightuserdata: {
std::stringstream ss;
ss << "[[lightuserdata: " << Value.as<sol::lightuserdata>().pointer() << "]]";
return ss.str();
}
case sol::type::string: case sol::type::string:
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: case sol::type::nil:
case sol::type::none:
return "<nil>"; return "<nil>";
case sol::type::boolean: case sol::type::boolean:
return Value.as<bool>() ? "true" : "false"; return Value.as<bool>() ? "true" : "false";
@ -130,13 +151,13 @@ void LuaAPI::MP::RemoveVehicle(int PID, int VID) {
c->DeleteCar(VID); c->DeleteCar(VID);
} }
} }
/*
void LuaAPI::MP::Set(int ConfigID, sol::object NewValue) { void LuaAPI::MP::Set(int ConfigID, sol::object NewValue) {
switch (ConfigID) { switch (ConfigID) {
case 0: //debug case 0: //debug
if (lua_isboolean(L, 2)) { if (lua_isboolean(L, 2)) {
Application::Settings.DebugModeEnabled = NewValue.as<bool>(); Application::Settings.DebugModeEnabled = NewValue.as<bool>();
beammp_info("Set `Debug` to ") + (Application::Settings.DebugModeEnabled ? "true" : "false")); beammp_info("Set `Debug` to " + (Application::Settings.DebugModeEnabled ? "true" : "false"));
} else } else
SendError(Engine(), L, ("set invalid argument [2] expected boolean for ID : 0")); SendError(Engine(), L, ("set invalid argument [2] expected boolean for ID : 0"));
break; break;
@ -187,6 +208,7 @@ void LuaAPI::MP::Set(int ConfigID, sol::object NewValue) {
break; break;
} }
} }
*/
void LuaAPI::MP::Sleep(size_t Ms) { void LuaAPI::MP::Sleep(size_t Ms) {
std::this_thread::sleep_for(std::chrono::milliseconds(Ms)); std::this_thread::sleep_for(std::chrono::milliseconds(Ms));

View File

@ -84,6 +84,6 @@ void TConsole::WriteRaw(const std::string& str) {
} }
void TConsole::InitializeLuaConsole(TLuaEngine& Engine) { void TConsole::InitializeLuaConsole(TLuaEngine& Engine) {
Engine.EnsureStateExists(mStateId, "Console");
mLuaEngine = &Engine; mLuaEngine = &Engine;
Engine.EnsureStateExists(mStateId, "Console");
} }

View File

@ -14,9 +14,9 @@ static TLuaStateId GenerateUniqueStateId() {
return std::to_string(MTGen64()) + std::to_string(std::chrono::duration_cast<std::chrono::nanoseconds>(Time).count()); return std::to_string(MTGen64()) + std::to_string(std::chrono::duration_cast<std::chrono::nanoseconds>(Time).count());
} }
TLuaEngine::TLuaEngine(TServer& Server, TNetwork& Network) TLuaEngine* LuaAPI::MP::Engine;
: mNetwork(Network)
, mServer(Server) { TLuaEngine::TLuaEngine() {
LuaAPI::MP::Engine = this; LuaAPI::MP::Engine = this;
if (!fs::exists(Application::Settings.Resource)) { if (!fs::exists(Application::Settings.Resource)) {
fs::create_directory(Application::Settings.Resource); fs::create_directory(Application::Settings.Resource);
@ -41,7 +41,7 @@ void TLuaEngine::operator()() {
CollectAndInitPlugins(); CollectAndInitPlugins();
// now call all onInit's // now call all onInit's
for (const auto& Pair : mLuaStates) { for (const auto& Pair : mLuaStates) {
auto Res = EnqueueFunctionCall(Pair.first, "onInit"); auto Res = EnqueueFunctionCall(Pair.first, "onInit", {});
Res->WaitUntilReady(); Res->WaitUntilReady();
if (Res->Error && Res->ErrorMessage != TLuaEngine::BeamMPFnNotFoundError) { if (Res->Error && Res->ErrorMessage != TLuaEngine::BeamMPFnNotFoundError) {
beammp_lua_error("Calling \"onInit\" on \"" + Pair.first + "\" failed: " + Res->ErrorMessage); beammp_lua_error("Calling \"onInit\" on \"" + Pair.first + "\" failed: " + Res->ErrorMessage);
@ -53,16 +53,24 @@ void TLuaEngine::operator()() {
} }
} }
void TLuaEngine::WaitForAll(std::vector<std::shared_ptr<TLuaResult>>& Results) {
for (const auto& Result : Results) {
while (!Result->Ready) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
}
std::shared_ptr<TLuaResult> TLuaEngine::EnqueueScript(TLuaStateId StateID, const std::shared_ptr<std::string>& Script) { std::shared_ptr<TLuaResult> TLuaEngine::EnqueueScript(TLuaStateId StateID, const std::shared_ptr<std::string>& Script) {
std::unique_lock Lock(mLuaStatesMutex); std::unique_lock Lock(mLuaStatesMutex);
beammp_debug("enqueuing script into \"" + StateID + "\""); beammp_debug("enqueuing script into \"" + StateID + "\"");
return mLuaStates.at(StateID)->EnqueueScript(Script); return mLuaStates.at(StateID)->EnqueueScript(Script);
} }
std::shared_ptr<TLuaResult> TLuaEngine::EnqueueFunctionCall(TLuaStateId StateID, const std::string& FunctionName) { std::shared_ptr<TLuaResult> TLuaEngine::EnqueueFunctionCall(TLuaStateId StateID, const std::string& FunctionName, const std::initializer_list<std::any>& Args) {
std::unique_lock Lock(mLuaStatesMutex); std::unique_lock Lock(mLuaStatesMutex);
beammp_debug("calling \"" + FunctionName + "\" in \"" + StateID + "\""); beammp_debug("calling \"" + FunctionName + "\" in \"" + StateID + "\"");
return mLuaStates.at(StateID)->EnqueueFunctionCall(FunctionName); return mLuaStates.at(StateID)->EnqueueFunctionCall(FunctionName, Args);
} }
void TLuaEngine::CollectAndInitPlugins() { void TLuaEngine::CollectAndInitPlugins() {
@ -119,7 +127,7 @@ void TLuaEngine::EnsureStateExists(TLuaStateId StateId, const std::string& Name,
mLuaStates[StateId] = std::move(DataPtr); mLuaStates[StateId] = std::move(DataPtr);
RegisterEvent("onInit", StateId, "onInit"); RegisterEvent("onInit", StateId, "onInit");
if (!DontCallOnInit) { if (!DontCallOnInit) {
auto Res = EnqueueFunctionCall(StateId, "onInit"); auto Res = EnqueueFunctionCall(StateId, "onInit", {});
Res->WaitUntilReady(); Res->WaitUntilReady();
if (Res->Error && Res->ErrorMessage != TLuaEngine::BeamMPFnNotFoundError) { if (Res->Error && Res->ErrorMessage != TLuaEngine::BeamMPFnNotFoundError) {
beammp_lua_error("Calling \"onInit\" on \"" + StateId + "\" failed: " + Res->ErrorMessage); beammp_lua_error("Calling \"onInit\" on \"" + StateId + "\" failed: " + Res->ErrorMessage);
@ -133,21 +141,6 @@ void TLuaEngine::RegisterEvent(const std::string& EventName, TLuaStateId StateId
mEvents[EventName][StateId].insert(FunctionName); mEvents[EventName][StateId].insert(FunctionName);
} }
std::vector<std::shared_ptr<TLuaResult>> TLuaEngine::TriggerEvent(const std::string& EventName) {
std::unique_lock Lock(mEventsMutex);
if (mEvents.find(EventName) == mEvents.end()) {
return {};
}
std::vector<std::shared_ptr<TLuaResult>> Results;
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));
}
}
return Results;
}
std::set<std::string> TLuaEngine::GetEventHandlersForState(const std::string& EventName, TLuaStateId StateId) { std::set<std::string> TLuaEngine::GetEventHandlersForState(const std::string& EventName, TLuaStateId StateId) {
return mEvents[EventName][StateId]; return mEvents[EventName][StateId];
} }
@ -227,8 +220,8 @@ TLuaEngine::StateThreadData::StateThreadData(const std::string& Name, std::atomi
: mName(Name) : mName(Name)
, mShutdown(Shutdown) , mShutdown(Shutdown)
, mStateId(StateId) , mStateId(StateId)
, mState(luaL_newstate())
, mEngine(&Engine) { , mEngine(&Engine) {
mState = luaL_newstate();
luaL_openlibs(mState); luaL_openlibs(mState);
sol::state_view StateView(mState); sol::state_view StateView(mState);
// StateView.globals()["package"].get() // StateView.globals()["package"].get()
@ -262,7 +255,7 @@ TLuaEngine::StateThreadData::StateThreadData(const std::string& Name, std::atomi
return Lua_GetPlayerIdentifiers(ID); return Lua_GetPlayerIdentifiers(ID);
}); });
Table.set_function("Sleep", &LuaAPI::MP::Sleep); Table.set_function("Sleep", &LuaAPI::MP::Sleep);
Table.set_function("Set", &LuaAPI::MP::Set); //Table.set_function("Set", &LuaAPI::MP::Set);
//Table.set_function("HttpsGET", &LuaAPI::MP::HttpsGET); //Table.set_function("HttpsGET", &LuaAPI::MP::HttpsGET);
//Table.set_function("HttpsPOST", &LuaAPI::MP::HttpsPOST); //Table.set_function("HttpsPOST", &LuaAPI::MP::HttpsPOST);
Table.create_named("Settings", Table.create_named("Settings",
@ -284,13 +277,13 @@ std::shared_ptr<TLuaResult> TLuaEngine::StateThreadData::EnqueueScript(const std
return Result; return Result;
} }
std::shared_ptr<TLuaResult> TLuaEngine::StateThreadData::EnqueueFunctionCall(const std::string& FunctionName) { std::shared_ptr<TLuaResult> TLuaEngine::StateThreadData::EnqueueFunctionCall(const std::string& FunctionName, const std::initializer_list<std::any>& Args) {
beammp_debug("calling \"" + FunctionName + "\" in \"" + mName + "\""); beammp_debug("calling \"" + FunctionName + "\" in \"" + mName + "\"");
auto Result = std::make_shared<TLuaResult>(); auto Result = std::make_shared<TLuaResult>();
Result->StateId = mStateId; Result->StateId = mStateId;
Result->Function = FunctionName; Result->Function = FunctionName;
std::unique_lock Lock(mStateFunctionQueueMutex); std::unique_lock Lock(mStateFunctionQueueMutex);
mStateFunctionQueue.push({ FunctionName, Result }); mStateFunctionQueue.push({ FunctionName, Result, Args });
return Result; return Result;
} }
@ -327,26 +320,29 @@ void TLuaEngine::StateThreadData::operator()() {
auto FnNameResultPair = mStateFunctionQueue.front(); auto FnNameResultPair = mStateFunctionQueue.front();
mStateFunctionQueue.pop(); mStateFunctionQueue.pop();
Lock.unlock(); Lock.unlock();
FnNameResultPair.second->StateId = mStateId; auto& StateId = std::get<0>(FnNameResultPair);
beammp_debug("Running function \"" + FnNameResultPair.first + "\""); auto& Result = std::get<1>(FnNameResultPair);
auto& Args = std::get<1>(FnNameResultPair);
Result->StateId = mStateId;
beammp_debug("Running function \"" + std::get<0>(FnNameResultPair) + "\"");
sol::state_view StateView(mState); sol::state_view StateView(mState);
auto Fn = StateView[FnNameResultPair.first]; auto Fn = StateView[StateId];
beammp_debug("Done running function \"" + FnNameResultPair.first + "\""); beammp_debug("Done running function \"" + StateId + "\"");
if (Fn.valid() && Fn.get_type() == sol::type::function) { if (Fn.valid() && Fn.get_type() == sol::type::function) {
auto Res = Fn(); auto Res = Fn(Args);
if (Res.valid()) { if (Res.valid()) {
FnNameResultPair.second->Error = false; Result->Error = false;
FnNameResultPair.second->Result = std::move(Res); Result->Result = std::move(Res);
} else { } else {
FnNameResultPair.second->Error = true; Result->Error = true;
sol::error Err = Res; sol::error Err = Res;
FnNameResultPair.second->ErrorMessage = Err.what(); Result->ErrorMessage = Err.what();
} }
FnNameResultPair.second->Ready = true; Result->Ready = true;
} else { } else {
FnNameResultPair.second->Error = true; Result->Error = true;
FnNameResultPair.second->ErrorMessage = BeamMPFnNotFoundError; // special error kind that we can ignore later Result->ErrorMessage = BeamMPFnNotFoundError; // special error kind that we can ignore later
FnNameResultPair.second->Ready = true; Result->Ready = true;
} }
} }
} }
@ -359,10 +355,3 @@ void TLuaResult::WaitUntilReady() {
std::this_thread::sleep_for(std::chrono::milliseconds(10)); std::this_thread::sleep_for(std::chrono::milliseconds(10));
} }
} }
// AHHH
std::any TriggerLuaEvent(const std::string& Event, bool local, TLuaPlugin* Caller, std::shared_ptr<TLuaArg> arg, bool Wait) {
}
void TLuaArg::PushArgs(lua_State* State) {
}

View File

@ -6,6 +6,8 @@
#include <array> #include <array>
#include <cstring> #include <cstring>
#include "LuaAPI.h"
TNetwork::TNetwork(TServer& Server, TPPSMonitor& PPSMonitor, TResourceManager& ResourceManager) TNetwork::TNetwork(TServer& Server, TPPSMonitor& PPSMonitor, TResourceManager& ResourceManager)
: mServer(Server) : mServer(Server)
, mPPSMonitor(PPSMonitor) , mPPSMonitor(PPSMonitor)
@ -289,14 +291,27 @@ void TNetwork::Authentication(const TConnection& ClientConnection) {
return true; return true;
}); });
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<TLuaResult>& Result) {
return !Result->Error && Result->Result.is<int>() && bool(Result->Result.as<int>());
});
std::string Reason;
bool NotAllowedWithReason = std::any_of(Futures.begin(), Futures.end(),
[&Reason](const std::shared_ptr<TLuaResult>& Result) -> bool {
if (!Result->Error && Result->Result.is<std::string>()) {
Reason = Result->Result.as<std::string>();
return true;
}
return false;
});
auto arg = std::make_unique<TLuaArg>(TLuaArg { { Client->GetName(), Client->GetRoles(), Client->IsGuest() } }); if (NotAllowed) {
std::any Res = TriggerLuaEvent("onPlayerAuth", false, nullptr, std::move(arg), true);
if (Res.type() == typeid(int) && std::any_cast<int>(Res)) {
ClientKick(*Client, "you are not allowed on the server!"); ClientKick(*Client, "you are not allowed on the server!");
return; return;
} else if (Res.type() == typeid(std::string)) { } else if (NotAllowedWithReason) {
ClientKick(*Client, std::any_cast<std::string>(Res)); ClientKick(*Client, Reason);
return; return;
} }
@ -563,7 +578,8 @@ 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();
TriggerLuaEvent(("onPlayerDisconnect"), false, nullptr, std::make_unique<TLuaArg>(TLuaArg { { c.GetID() } }), false); auto Futures = LuaAPI::MP::Engine->TriggerEvent("onPlayerDisconnect", c.GetID());
beammp_ignore(Futures);
if (c.GetTCPSock()) if (c.GetTCPSock())
CloseSocketProper(c.GetTCPSock()); CloseSocketProper(c.GetTCPSock());
if (c.GetDownSock()) if (c.GetDownSock())
@ -597,13 +613,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());
TriggerLuaEvent("onPlayerConnecting", false, nullptr, std::make_unique<TLuaArg>(TLuaArg { { LockedClient->GetID() } }), false); 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");
TriggerLuaEvent("onPlayerJoining", false, nullptr, std::make_unique<TLuaArg>(TLuaArg { { LockedClient->GetID() } }), false); beammp_ignore(LuaAPI::MP::Engine->TriggerEvent("onPlayerJoining", LockedClient->GetID()));
} }
void TNetwork::SyncResources(TClient& c) { void TNetwork::SyncResources(TClient& c) {
@ -802,7 +818,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);
TriggerLuaEvent(("onPlayerJoin"), false, nullptr, std::make_unique<TLuaArg>(TLuaArg { { LockedClient->GetID() } }), false); 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;

View File

@ -7,6 +7,8 @@
#include <any> #include <any>
#include <sstream> #include <sstream>
#include "LuaAPI.h"
#undef GetObject //Fixes Windows #undef GetObject //Fixes Windows
#include "Json.h" #include "Json.h"
@ -119,17 +121,25 @@ void TServer::GlobalParser(const std::weak_ptr<TClient>& Client, std::string Pac
#endif #endif
Network.SendToAll(LockedClient.get(), Packet, false, true); Network.SendToAll(LockedClient.get(), Packet, false, true);
return; return;
case 'C': case 'C': {
#ifdef DEBUG #ifdef DEBUG
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()) + (")"));
#endif #endif
if (Packet.length() < 4 || Packet.find(':', 3) == std::string::npos) if (Packet.length() < 4 || Packet.find(':', 3) == std::string::npos)
break; break;
Res = TriggerLuaEvent("onChatMessage", false, nullptr, std::make_unique<TLuaArg>(TLuaArg { { LockedClient->GetID(), LockedClient->GetName(), Packet.substr(Packet.find(':', 3) + 1) } }), true); auto Futures = LuaAPI::MP::Engine->TriggerEvent("onChatMessage", LockedClient->GetID(), LockedClient->GetName(), Packet.substr(Packet.find(':', 3) + 1));
if (std::any_cast<int>(Res)) TLuaEngine::WaitForAll(Futures);
if (std::any_of(Futures.begin(), Futures.end(),
[](const std::shared_ptr<TLuaResult>& Elem) {
return !Elem->Error
&& Elem->Result.is<int>()
&& bool(Elem->Result.as<int>());
})) {
break; break;
}
Network.SendToAll(nullptr, Packet, true, true); Network.SendToAll(nullptr, Packet, true, true);
return; return;
}
case 'E': case 'E':
#ifdef DEBUG #ifdef DEBUG
beammp_debug(std::string(("got 'E' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")")); beammp_debug(std::string(("got 'E' packet: '")) + Packet + ("' (") + std::to_string(Packet.size()) + (")"));
@ -154,7 +164,7 @@ void TServer::HandleEvent(TClient& c, const std::string& Data) {
Name = t; Name = t;
break; break;
case 2: case 2:
TriggerLuaEvent(Name, false, nullptr, std::make_unique<TLuaArg>(TLuaArg { { c.GetID(), t } }), false); beammp_ignore(LuaAPI::MP::Engine->TriggerEvent(Name, c.GetID(), t));
break; break;
default: default:
break; break;
@ -207,9 +217,14 @@ 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 Res = TriggerLuaEvent(("onVehicleSpawn"), false, nullptr, std::make_unique<TLuaArg>(TLuaArg { { c.GetID(), CarID, Packet.substr(3) } }), true); 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<TLuaResult>& Result) {
return !Result->Error && Result->Result.is<int>() && Result->Result.as<int>() != 0;
});
if (ShouldSpawn(c, CarJson, CarID) && std::any_cast<int>(Res) == 0) { if (ShouldSpawn(c, CarJson, CarID) && !ShouldntSpawn) {
c.AddNewCar(CarID, Packet); c.AddNewCar(CarID, Packet);
Network.SendToAll(nullptr, Packet, true, true); Network.SendToAll(nullptr, Packet, true, true);
} else { } else {
@ -235,14 +250,17 @@ 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 Res = TriggerLuaEvent(("onVehicleEdited"), false, nullptr, auto Futures = LuaAPI::MP::Engine->TriggerEvent("onVehicleEdited", c.GetID(), VID, Packet.substr(3));
std::make_unique<TLuaArg>(TLuaArg { { c.GetID(), VID, Packet.substr(3) } }), TLuaEngine::WaitForAll(Futures);
true); bool ShouldntAllow = std::any_of(Futures.begin(), Futures.end(),
[](const std::shared_ptr<TLuaResult>& Result) {
return !Result->Error && Result->Result.is<int>() && Result->Result.as<int>() != 0;
});
auto FoundPos = Packet.find('{'); auto FoundPos = Packet.find('{');
FoundPos = FoundPos == std::string::npos ? 0 : FoundPos; // attempt at sanitizing this FoundPos = FoundPos == std::string::npos ? 0 : FoundPos; // attempt at sanitizing this
if ((c.GetUnicycleID() != VID || IsUnicycle(c, Packet.substr(FoundPos))) if ((c.GetUnicycleID() != VID || IsUnicycle(c, Packet.substr(FoundPos)))
&& std::any_cast<int>(Res) == 0) { && !ShouldntAllow) {
Network.SendToAll(&c, Packet, false, true); Network.SendToAll(&c, Packet, false, true);
Apply(c, VID, Packet); Apply(c, VID, Packet);
} else { } else {
@ -272,8 +290,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);
TriggerLuaEvent(("onVehicleDeleted"), false, nullptr, beammp_ignore(LuaAPI::MP::Engine->TriggerEvent("onVehicleDeleted", c.GetID(), VID));
std::make_unique<TLuaArg>(TLuaArg { { c.GetID(), VID } }), false);
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));
} }
@ -293,9 +310,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('{'));
TriggerLuaEvent("onVehicleReset", false, nullptr, beammp_ignore(LuaAPI::MP::Engine->TriggerEvent("onVehicleReset", c.GetID(), VID, Data));
std::make_unique<TLuaArg>(TLuaArg { { c.GetID(), VID, Data } }),
false);
Network.SendToAll(&c, Packet, false, true); Network.SendToAll(&c, Packet, false, true);
} }
return; return;

View File

@ -1,5 +1,6 @@
#include "Common.h" #include "Common.h"
#include "Http.h" #include "Http.h"
#include "LuaAPI.h"
#include "TConfig.h" #include "TConfig.h"
#include "THeartbeatThread.h" #include "THeartbeatThread.h"
#include "TLuaEngine.h" #include "TLuaEngine.h"
@ -48,10 +49,15 @@ int main(int argc, char** argv) {
bool Shutdown = false; bool Shutdown = false;
Application::RegisterShutdownHandler([&Shutdown] { Shutdown = true; }); Application::RegisterShutdownHandler([&Shutdown] { Shutdown = true; });
Application::RegisterShutdownHandler([] { TriggerLuaEvent("onShutdown", false, nullptr, {}, true); }); Application::RegisterShutdownHandler([] {
auto Futures = LuaAPI::MP::Engine->TriggerEvent("onShutdown");
TLuaEngine::WaitForAll(Futures);
});
TServer Server(argc, argv); TServer Server(argc, argv);
TConfig Config; TConfig Config;
TLuaEngine LuaEngine;
LuaEngine.SetServer(&Server);
if (Config.Failed()) { if (Config.Failed()) {
beammp_info("Closing in 10 seconds"); beammp_info("Closing in 10 seconds");
@ -64,7 +70,7 @@ int main(int argc, char** argv) {
TPPSMonitor PPSMonitor(Server); TPPSMonitor PPSMonitor(Server);
THeartbeatThread Heartbeat(ResourceManager, Server); THeartbeatThread Heartbeat(ResourceManager, Server);
TNetwork Network(Server, PPSMonitor, ResourceManager); TNetwork Network(Server, PPSMonitor, ResourceManager);
TLuaEngine LuaEngine(Server, Network); LuaEngine.SetNetwork(&Network);
PPSMonitor.SetNetwork(Network); PPSMonitor.SetNetwork(Network);
Application::Console().InitializeLuaConsole(LuaEngine); Application::Console().InitializeLuaConsole(LuaEngine);