#include "TLuaFile.h" #include "Client.h" #include "Common.h" #include "CustomAssert.h" #include "TLuaEngine.h" #include "TNetwork.h" #include "TServer.h" #include #include // TODO: REWRITE void SendError(TLuaEngine& Engine, lua_State* L, const std::string& msg); std::any CallFunction(TLuaFile* lua, const std::string& FuncName, std::shared_ptr Arg); std::any TriggerLuaEvent(TLuaEngine& Engine, const std::string& Event, bool local, TLuaFile* Caller, std::shared_ptr arg, bool Wait); extern TLuaEngine* TheEngine; static TLuaEngine& Engine() { Assert(TheEngine); return *TheEngine; } std::shared_ptr CreateArg(lua_State* L, int T, int S) { if (S > T) return nullptr; std::shared_ptr temp(new TLuaArg); for (int C = S; C <= T; C++) { if (lua_isstring(L, C)) { temp->args.emplace_back(std::string(lua_tostring(L, C))); } else if (lua_isinteger(L, C)) { temp->args.emplace_back(int(lua_tointeger(L, C))); } else if (lua_isboolean(L, C)) { temp->args.emplace_back(bool(lua_toboolean(L, C))); } else if (lua_isnumber(L, C)) { temp->args.emplace_back(float(lua_tonumber(L, C))); } } return temp; } void ClearStack(lua_State* L) { lua_settop(L, 0); } std::any Trigger(TLuaFile* lua, const std::string& R, std::shared_ptr arg) { RegisterThread(lua->GetFileName()); std::lock_guard lockGuard(lua->Lock); std::packaged_task)> task([lua, R](std::shared_ptr arg) { return CallFunction(lua, R, arg); }); std::future f1 = task.get_future(); std::thread t(std::move(task), arg); t.detach(); auto status = f1.wait_for(std::chrono::seconds(5)); if (status != std::future_status::timeout) return f1.get(); SendError(lua->Engine(), lua->GetState(), R + " took too long to respond"); return 0; } std::any FutureWait(TLuaFile* lua, const std::string& R, std::shared_ptr arg, bool Wait) { Assert(lua); std::packaged_task)> task([lua, R](std::shared_ptr arg) { return Trigger(lua, R, arg); }); std::future f1 = task.get_future(); std::thread t(std::move(task), arg); t.detach(); int T = 0; if (Wait) T = 6; auto status = f1.wait_for(std::chrono::seconds(T)); if (status != std::future_status::timeout) return f1.get(); return 0; } std::any TriggerLuaEvent(const std::string& Event, bool local, TLuaFile* Caller, std::shared_ptr arg, bool Wait) { std::any R; std::string Type; int Ret = 0; for (auto& Script : Engine().LuaFiles()) { if (Script->IsRegistered(Event)) { if (local) { if (Script->GetPluginName() == Caller->GetPluginName()) { R = FutureWait(Script.get(), Script->GetRegistered(Event), arg, Wait); Type = R.type().name(); if (Type.find("int") != std::string::npos) { if (std::any_cast(R)) Ret++; } else if (Event == "onPlayerAuth") return R; } } else { R = FutureWait(Script.get(), Script->GetRegistered(Event), arg, Wait); Type = R.type().name(); if (Type.find("int") != std::string::npos) { if (std::any_cast(R)) Ret++; } else if (Event == "onPlayerAuth") return R; } } } return Ret; } bool ConsoleCheck(lua_State* L, int r) { if (r != LUA_OK) { std::string msg = lua_tostring(L, -1); warn(("_Console | ") + msg); return false; } return true; } bool CheckLua(lua_State* L, int r) { if (r != LUA_OK) { std::string msg = lua_tostring(L, -1); auto MaybeS = Engine().GetScript(L); if (MaybeS.has_value()) { TLuaFile& S = MaybeS.value(); std::string a = fs::path(S.GetFileName()).filename().string(); warn(a + " | " + msg); return false; } // What the fuck, what do we do?! AssertNotReachable(); } return true; } int lua_RegisterEvent(lua_State* L) { int Args = lua_gettop(L); auto MaybeScript = Engine().GetScript(L); Assert(MaybeScript.has_value()); TLuaFile& Script = MaybeScript.value(); if (Args == 2 && lua_isstring(L, 1) && lua_isstring(L, 2)) { Script.RegisterEvent(lua_tostring(L, 1), lua_tostring(L, 2)); } else SendError(Engine(), L, "RegisterEvent invalid argument count expected 2 got " + std::to_string(Args)); return 0; } int lua_TriggerEventL(lua_State* L) { int Args = lua_gettop(L); auto MaybeScript = Engine().GetScript(L); Assert(MaybeScript.has_value()); TLuaFile& Script = MaybeScript.value(); if (Args > 0) { if (lua_isstring(L, 1)) { TriggerLuaEvent(lua_tostring(L, 1), true, &Script, CreateArg(L, Args, 2), false); } else SendError(Engine(), L, ("TriggerLocalEvent wrong argument [1] need string")); } else { SendError(Engine(), L, ("TriggerLocalEvent not enough arguments expected 1 got 0")); } return 0; } int lua_TriggerEventG(lua_State* L) { int Args = lua_gettop(L); auto MaybeScript = Engine().GetScript(L); Assert(MaybeScript.has_value()); TLuaFile& Script = MaybeScript.value(); if (Args > 0) { if (lua_isstring(L, 1)) { TriggerLuaEvent(lua_tostring(L, 1), false, &Script, CreateArg(L, Args, 2), false); } else SendError(Engine(), L, ("TriggerGlobalEvent wrong argument [1] need string")); } else SendError(Engine(), L, ("TriggerGlobalEvent not enough arguments")); return 0; } void SafeExecution(TLuaFile* lua, const std::string& FuncName) { lua_State* luaState = lua->GetState(); lua_getglobal(luaState, FuncName.c_str()); if (lua_isfunction(luaState, -1)) { int R = lua_pcall(luaState, 0, 0, 0); CheckLua(luaState, R); } ClearStack(luaState); } void ExecuteAsync(TLuaFile* lua, const std::string& FuncName) { std::lock_guard lockGuard(lua->Lock); SafeExecution(lua, FuncName); } void CallAsync(TLuaFile* lua, const std::string& Func, int U) { RegisterThread(lua->GetFileName()); lua->SetStopThread(false); int D = 1000 / U; while (!lua->GetStopThread()) { ExecuteAsync(lua, Func); std::this_thread::sleep_for(std::chrono::milliseconds(D)); } } int lua_StopThread(lua_State* L) { auto MaybeScript = Engine().GetScript(L); Assert(MaybeScript.has_value()); // ugly, but whatever, this is safe as fuck MaybeScript.value().get().SetStopThread(true); return 0; } int lua_CreateThread(lua_State* L) { int Args = lua_gettop(L); if (Args > 1) { if (lua_isstring(L, 1)) { std::string STR = lua_tostring(L, 1); if (lua_isinteger(L, 2) || lua_isnumber(L, 2)) { int U = int(lua_tointeger(L, 2)); if (U > 0 && U < 501) { auto MaybeScript = Engine().GetScript(L); Assert(MaybeScript.has_value()); TLuaFile& Script = MaybeScript.value(); std::thread t1(CallAsync, &Script, STR, U); t1.detach(); } else SendError(Engine(), L, ("CreateThread wrong argument [2] number must be between 1 and 500")); } else SendError(Engine(), L, ("CreateThread wrong argument [2] need number")); } else SendError(Engine(), L, ("CreateThread wrong argument [1] need string")); } else SendError(Engine(), L, ("CreateThread not enough arguments")); return 0; } int lua_Sleep(lua_State* L) { if (lua_isnumber(L, 1)) { int t = int(lua_tonumber(L, 1)); std::this_thread::sleep_for(std::chrono::milliseconds(t)); } else { SendError(Engine(), L, ("Sleep not enough arguments")); return 0; } return 1; } std::optional> GetClient(TServer& Server, int ID) { std::optional> MaybeClient { std::nullopt }; Server.ForEachClient([&](std::weak_ptr CPtr) -> bool { ReadLock Lock(Server.GetClientMutex()); if (!CPtr.expired()) { auto C = CPtr.lock(); if (C->GetID() == ID) { MaybeClient = CPtr; return false; } } return true; }); return MaybeClient; } // CONTINUE int lua_isConnected(lua_State* L) { if (lua_isnumber(L, 1)) { int ID = int(lua_tonumber(L, 1)); auto MaybeClient = GetClient(Engine().Server(), ID); if (MaybeClient && !MaybeClient.value().expired()) lua_pushboolean(L, MaybeClient.value().lock()->IsConnected()); else return 0; } else { SendError(Engine(), L, ("isConnected not enough arguments")); return 0; } return 1; } int lua_GetPlayerName(lua_State* L) { if (lua_isnumber(L, 1)) { int ID = int(lua_tonumber(L, 1)); auto MaybeClient = GetClient(Engine().Server(), ID); if (MaybeClient && !MaybeClient.value().expired()) lua_pushstring(L, MaybeClient.value().lock()->GetName().c_str()); else return 0; } else { SendError(Engine(), L, ("GetPlayerName not enough arguments")); return 0; } return 1; } int lua_GetPlayerCount(lua_State* L) { lua_pushinteger(L, Engine().Server().ClientCount()); return 1; } int lua_GetGuest(lua_State* L) { if (lua_isnumber(L, 1)) { int ID = int(lua_tonumber(L, 1)); auto MaybeClient = GetClient(Engine().Server(), ID); if (MaybeClient && !MaybeClient.value().expired()) lua_pushboolean(L, MaybeClient.value().lock()->IsGuest()); else return 0; } else { SendError(Engine(), L, "GetGuest not enough arguments"); return 0; } return 1; } int lua_GetAllPlayers(lua_State* L) { lua_newtable(L); Engine().Server().ForEachClient([&](const std::weak_ptr& ClientPtr) -> bool { std::shared_ptr Client; { ReadLock Lock(Engine().Server().GetClientMutex()); if (ClientPtr.expired()) return true; Client = ClientPtr.lock(); } lua_pushinteger(L, Client->GetID()); lua_pushstring(L, Client->GetName().c_str()); lua_settable(L, -3); return true; }); if (Engine().Server().ClientCount() == 0) return 0; return 1; } int lua_GetIdentifiers(lua_State* L) { if (lua_isnumber(L, 1)) { auto MaybeClient = GetClient(Engine().Server(), int(lua_tonumber(L, 1))); if (MaybeClient && !MaybeClient.value().expired()) { auto IDs = MaybeClient.value().lock()->GetIdentifiers(); if (IDs.empty()) return 0; lua_newtable(L); for (const std::string& ID : IDs) { lua_pushstring(L, ID.substr(0, ID.find(':')).c_str()); lua_pushstring(L, ID.c_str()); lua_settable(L, -3); } } else return 0; } else { SendError(Engine(), L, "lua_GetIdentifiers wrong arguments"); return 0; } return 1; } int lua_GetCars(lua_State* L) { if (lua_isnumber(L, 1)) { int ID = int(lua_tonumber(L, 1)); auto MaybeClient = GetClient(Engine().Server(), ID); if (MaybeClient && !MaybeClient.value().expired()) { auto Client = MaybeClient.value().lock(); TClient::TSetOfVehicleData VehicleData; { // Vehicle Data Lock Scope auto LockedData = Client->GetAllCars(); VehicleData = *LockedData.VehicleData; } // End Vehicle Data Lock Scope if (VehicleData.empty()) return 0; lua_newtable(L); for (const auto& v : VehicleData) { lua_pushinteger(L, v.ID()); lua_pushstring(L, v.Data().substr(3).c_str()); lua_settable(L, -3); } } else return 0; } else { SendError(Engine(), L, ("GetPlayerVehicles wrong arguments")); return 0; } return 1; } int lua_dropPlayer(lua_State* L) { int Args = lua_gettop(L); if (lua_isnumber(L, 1)) { int ID = int(lua_tonumber(L, 1)); auto MaybeClient = GetClient(Engine().Server(), ID); if (!MaybeClient || MaybeClient.value().expired()) return 0; std::string Reason; if (Args > 1 && lua_isstring(L, 2)) { Reason = std::string((" Reason : ")) + lua_tostring(L, 2); } auto c = MaybeClient.value().lock(); Engine().Network().Respond(*c, "C:Server:You have been Kicked from the server! " + Reason, true); c->SetStatus(-2); info(("Closing socket due to kick")); CloseSocketProper(c->GetTCPSock()); } else SendError(Engine(), L, ("DropPlayer not enough arguments")); return 0; } int lua_sendChat(lua_State* L) { if (lua_isinteger(L, 1) || lua_isnumber(L, 1)) { if (lua_isstring(L, 2)) { int ID = int(lua_tointeger(L, 1)); if (ID == -1) { std::string Packet = "C:Server: " + std::string(lua_tostring(L, 2)); Engine().Network().SendToAll(nullptr, Packet, true, true); } else { auto MaybeClient = GetClient(Engine().Server(), ID); if (MaybeClient && !MaybeClient.value().expired()) { auto c = MaybeClient.value().lock(); if (!c->IsSynced()) return 0; std::string Packet = "C:Server: " + std::string(lua_tostring(L, 2)); Engine().Network().Respond(*c, Packet, true); } else SendError(Engine(), L, ("SendChatMessage invalid argument [1] invalid ID")); } } else SendError(Engine(), L, ("SendChatMessage invalid argument [2] expected string")); } else SendError(Engine(), L, ("SendChatMessage invalid argument [1] expected number")); return 0; } int lua_RemoveVehicle(lua_State* L) { int Args = lua_gettop(L); if (Args != 2) { SendError(Engine(), L, ("RemoveVehicle invalid argument count expected 2 got ") + std::to_string(Args)); return 0; } if ((lua_isinteger(L, 1) || lua_isnumber(L, 1)) && (lua_isinteger(L, 2) || lua_isnumber(L, 2))) { int PID = int(lua_tointeger(L, 1)); int VID = int(lua_tointeger(L, 2)); auto MaybeClient = GetClient(Engine().Server(), PID); if (!MaybeClient || MaybeClient.value().expired()) { SendError(Engine(), L, ("RemoveVehicle invalid Player ID")); return 0; } auto c = MaybeClient.value().lock(); if (!c->GetCarData(VID).empty()) { std::string Destroy = "Od:" + std::to_string(PID) + "-" + std::to_string(VID); Engine().Network().SendToAll(nullptr, Destroy, true, true); c->DeleteCar(VID); } } else SendError(Engine(), L, ("RemoveVehicle invalid argument expected number")); return 0; } int lua_HWID(lua_State* L) { lua_pushinteger(L, -1); return 1; } int lua_RemoteEvent(lua_State* L) { int Args = lua_gettop(L); if (Args != 3) { SendError(Engine(), L, ("TriggerClientEvent invalid argument count expected 3 got ") + std::to_string(Args)); return 0; } if (!lua_isnumber(L, 1)) { SendError(Engine(), L, ("TriggerClientEvent invalid argument [1] expected number")); return 0; } if (!lua_isstring(L, 2)) { SendError(Engine(), L, ("TriggerClientEvent invalid argument [2] expected string")); return 0; } if (!lua_isstring(L, 3)) { SendError(Engine(), L, ("TriggerClientEvent invalid argument [3] expected string")); return 0; } int ID = int(lua_tointeger(L, 1)); std::string Packet = "E:" + std::string(lua_tostring(L, 2)) + ":" + std::string(lua_tostring(L, 3)); if (ID == -1) Engine().Network().SendToAll(nullptr, Packet, true, true); else { auto MaybeClient = GetClient(Engine().Server(), ID); if (!MaybeClient || MaybeClient.value().expired()) { SendError(Engine(), L, ("TriggerClientEvent invalid Player ID")); return 0; } auto c = MaybeClient.value().lock(); Engine().Network().Respond(*c, Packet, true); } return 0; } int lua_ServerExit(lua_State* L) { if (lua_gettop(L) > 0) { if (lua_isnumber(L, 1)) { _Exit(int(lua_tointeger(L, 1))); } } _Exit(0); } int lua_Set(lua_State* L) { int Args = lua_gettop(L); if (Args != 2) { SendError(Engine(), L, ("set invalid argument count expected 2 got ") + std::to_string(Args)); return 0; } if (!lua_isnumber(L, 1)) { SendError(Engine(), L, ("set invalid argument [1] expected number")); return 0; } auto MaybeSrc = Engine().GetScript(L); std::string Name; if (!MaybeSrc.has_value()) { Name = ("_Console"); } else { Name = MaybeSrc.value().get().GetPluginName(); } int C = int(lua_tointeger(L, 1)); switch (C) { case 0: //debug if (lua_isboolean(L, 2)) { Application::Settings.DebugModeEnabled = lua_toboolean(L, 2); info(Name + (" | Debug -> ") + (Application::Settings.DebugModeEnabled ? "true" : "false")); } else SendError(Engine(), L, ("set invalid argument [2] expected boolean for ID : 0")); break; case 1: //private if (lua_isboolean(L, 2)) { Application::Settings.Private = lua_toboolean(L, 2); info(Name + (" | Private -> ") + (Application::Settings.Private ? "true" : "false")); } else SendError(Engine(), L, ("set invalid argument [2] expected boolean for ID : 1")); break; case 2: //max cars if (lua_isnumber(L, 2)) { Application::Settings.MaxCars = int(lua_tointeger(L, 2)); info(Name + (" | MaxCars -> ") + std::to_string(Application::Settings.MaxCars)); } else SendError(Engine(), L, ("set invalid argument [2] expected number for ID : 2")); break; case 3: //max players if (lua_isnumber(L, 2)) { Application::Settings.MaxPlayers = int(lua_tointeger(L, 2)); info(Name + (" | MaxPlayers -> ") + std::to_string(Application::Settings.MaxPlayers)); } else SendError(Engine(), L, ("set invalid argument [2] expected number for ID : 3")); break; case 4: //Map if (lua_isstring(L, 2)) { Application::Settings.MapName = lua_tostring(L, 2); info(Name + (" | MapName -> ") + Application::Settings.MapName); } else SendError(Engine(), L, ("set invalid argument [2] expected string for ID : 4")); break; case 5: //Name if (lua_isstring(L, 2)) { Application::Settings.ServerName = lua_tostring(L, 2); info(Name + (" | ServerName -> ") + Application::Settings.ServerName); } else SendError(Engine(), L, ("set invalid argument [2] expected string for ID : 5")); break; case 6: //Desc if (lua_isstring(L, 2)) { Application::Settings.ServerDesc = lua_tostring(L, 2); info(Name + (" | ServerDesc -> ") + Application::Settings.ServerDesc); } else SendError(Engine(), L, ("set invalid argument [2] expected string for ID : 6")); break; default: warn(("Invalid config ID : ") + std::to_string(C)); break; } return 0; } extern "C" { int lua_Print(lua_State* L) { int Arg = lua_gettop(L); std::string to_print; for (int i = 1; i <= Arg; i++) { if (lua_isstring(L, i)) { to_print += lua_tostring(L, i); } else if (lua_isinteger(L, i)) { to_print += std::to_string(lua_tointeger(L, 1)); } else if (lua_isnumber(L, i)) { to_print += std::to_string(lua_tonumber(L, 1)); } else if (lua_isboolean(L, i)) { to_print += lua_toboolean(L, i) ? "true" : "false"; } else if (lua_isfunction(L, i)) { std::stringstream ss; ss << std::hex << reinterpret_cast(lua_tocfunction(L, i)); to_print += "function: " + ss.str(); } else if (lua_istable(L, i)) { std::stringstream ss; ss << std::hex << reinterpret_cast(lua_topointer(L, i)); to_print += "table: " + ss.str(); } else if (lua_isnoneornil(L, i)) { to_print += "nil"; } else if (lua_isthread(L, i)) { std::stringstream ss; ss << std::hex << reinterpret_cast(lua_tothread(L, i)); to_print += "thread: " + ss.str(); } else { to_print += "(unknown)"; } if (i + 1 <= Arg) { to_print += "\t"; } } luaprint(to_print); return 0; } } int lua_TempFix(lua_State* L); void TLuaFile::Init(const std::string& PluginName, const std::string& FileName, fs::file_time_type LastWrote) { // set global engine for lua_* functions if (!TheEngine) { TheEngine = &mEngine; } Assert(mLuaState); if (!PluginName.empty()) { SetPluginName(PluginName); } if (!FileName.empty()) { SetFileName(FileName); } SetLastWrite(LastWrote); Load(); } TLuaFile::TLuaFile(TLuaEngine& Engine, bool Console) : mEngine(Engine) , mLuaState(luaL_newstate()) { if (Console) { mConsole = Console; Load(); } } void TLuaFile::Execute(const std::string& Command) { if (ConsoleCheck(mLuaState, luaL_dostring(mLuaState, Command.c_str()))) { lua_settop(mLuaState, 0); } } void TLuaFile::Reload() { if (CheckLua(mLuaState, luaL_dofile(mLuaState, mFileName.c_str()))) { CallFunction(this, ("onInit"), nullptr); } } std::string TLuaFile::GetOrigin() { return fs::path(GetFileName()).filename().string(); } std::any CallFunction(TLuaFile* lua, const std::string& FuncName, std::shared_ptr Arg) { RegisterThread(lua->GetFileName()); lua_State* luaState = lua->GetState(); lua_getglobal(luaState, FuncName.c_str()); if (lua_isfunction(luaState, -1)) { int Size = 0; if (Arg != nullptr) { Size = int(Arg->args.size()); Arg->PushArgs(luaState); } int R = lua_pcall(luaState, Size, 1, 0); if (CheckLua(luaState, R)) { if (lua_isnumber(luaState, -1)) { return int(lua_tointeger(luaState, -1)); } else if (lua_isstring(luaState, -1)) { return std::string(lua_tostring(luaState, -1)); } } } ClearStack(luaState); return 0; } void TLuaFile::SetPluginName(const std::string& Name) { mPluginName = Name; } void TLuaFile::SetFileName(const std::string& Name) { mFileName = Name; } void TLuaFile::Load() { Assert(mLuaState); luaL_openlibs(mLuaState); lua_register(mLuaState, "GetPlayerIdentifiers", lua_GetIdentifiers); lua_register(mLuaState, "TriggerGlobalEvent", lua_TriggerEventG); lua_register(mLuaState, "TriggerLocalEvent", lua_TriggerEventL); lua_register(mLuaState, "TriggerClientEvent", lua_RemoteEvent); lua_register(mLuaState, "GetPlayerCount", lua_GetPlayerCount); lua_register(mLuaState, "isPlayerConnected", lua_isConnected); lua_register(mLuaState, "RegisterEvent", lua_RegisterEvent); lua_register(mLuaState, "GetPlayerName", lua_GetPlayerName); lua_register(mLuaState, "RemoveVehicle", lua_RemoveVehicle); lua_register(mLuaState, "GetPlayerDiscordID", lua_TempFix); lua_register(mLuaState, "CreateThread", lua_CreateThread); lua_register(mLuaState, "GetPlayerVehicles", lua_GetCars); lua_register(mLuaState, "SendChatMessage", lua_sendChat); lua_register(mLuaState, "GetPlayers", lua_GetAllPlayers); lua_register(mLuaState, "GetPlayerGuest", lua_GetGuest); lua_register(mLuaState, "StopThread", lua_StopThread); lua_register(mLuaState, "DropPlayer", lua_dropPlayer); lua_register(mLuaState, "GetPlayerHWID", lua_HWID); lua_register(mLuaState, "exit", lua_ServerExit); lua_register(mLuaState, "Sleep", lua_Sleep); lua_register(mLuaState, "print", lua_Print); lua_register(mLuaState, "Set", lua_Set); if (!mConsole) Reload(); } void TLuaFile::RegisterEvent(const std::string& Event, const std::string& FunctionName) { mRegisteredEvents.insert(std::make_pair(Event, FunctionName)); } void TLuaFile::UnRegisterEvent(const std::string& Event) { for (const std::pair& a : mRegisteredEvents) { if (a.first == Event) { mRegisteredEvents.erase(a); break; } } } bool TLuaFile::IsRegistered(const std::string& Event) { for (const std::pair& a : mRegisteredEvents) { if (a.first == Event) return true; } return false; } std::string TLuaFile::GetRegistered(const std::string& Event) const { for (const std::pair& a : mRegisteredEvents) { if (a.first == Event) return a.second; } return ""; } std::string TLuaFile::GetFileName() const { return mFileName; } std::string TLuaFile::GetPluginName() const { return mPluginName; } lua_State* TLuaFile::GetState() { return mLuaState; } const lua_State* TLuaFile::GetState() const { return mLuaState; } void TLuaFile::SetLastWrite(fs::file_time_type time) { mLastWrote = time; } fs::file_time_type TLuaFile::GetLastWrite() { return mLastWrote; } TLuaFile::~TLuaFile() { info("closing lua state"); lua_close(mLuaState); } void SendError(TLuaEngine& Engine, lua_State* L, const std::string& msg) { Assert(L); auto MaybeS = Engine.GetScript(L); std::string a; if (!MaybeS.has_value()) { a = ("_Console"); } else { TLuaFile& S = MaybeS.value(); a = fs::path(S.GetFileName()).filename().string(); } warn(a + (" | Incorrect Call of ") + msg); } int lua_TempFix(lua_State* L) { if (lua_isnumber(L, 1)) { int ID = int(lua_tonumber(L, 1)); auto MaybeClient = GetClient(Engine().Server(), ID); if (!MaybeClient || MaybeClient.value().expired()) return 0; std::string Ret; auto c = MaybeClient.value().lock(); if (c->IsGuest()) { Ret = "Guest-" + c->GetName(); } else Ret = c->GetName(); lua_pushstring(L, Ret.c_str()); } else SendError(Engine(), L, "GetDID not enough arguments"); return 1; } void TLuaArg::PushArgs(lua_State* State) { for (std::any arg : args) { if (!arg.has_value()) return; std::string Type = arg.type().name(); if (Type.find("bool") != std::string::npos) { lua_pushboolean(State, std::any_cast(arg)); } if (Type.find("basic_string") != std::string::npos || Type.find("char") != std::string::npos) { lua_pushstring(State, std::any_cast(arg).c_str()); } if (Type.find("int") != std::string::npos) { lua_pushinteger(State, std::any_cast(arg)); } if (Type.find("float") != std::string::npos) { lua_pushnumber(State, std::any_cast(arg)); } } }