diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d138f2..a436374 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,9 @@ cmake_minimum_required(VERSION 3.10) project(Server) set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") file(GLOB source_files "src/*.cpp" "src/*/*.cpp" "include/*.h" "include/*/*.h" "include/*.hpp" "include/*/*.hpp") add_executable(${PROJECT_NAME} ${source_files}) target_include_directories(${PROJECT_NAME} PUBLIC $) set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "BeamMP-Server") -target_link_libraries(${PROJECT_NAME} libcurl_a urlmon ws2_32 lua53 zlibstatic) +target_link_libraries(${PROJECT_NAME} libcurl_a urlmon ws2_32 lua53 zlibstatic) \ No newline at end of file diff --git a/include/Logger.h b/include/Logger.h index 5c3a52f..cf26ba5 100644 --- a/include/Logger.h +++ b/include/Logger.h @@ -5,6 +5,7 @@ #include #include void InitLog(); +void ConsoleOut(const std::string& msg); void except(const std::string& toPrint); void debug(const std::string& toPrint); void error(const std::string& toPrint); diff --git a/include/Lua/LuaSystem.hpp b/include/Lua/LuaSystem.hpp index 77c1954..e7f1461 100644 --- a/include/Lua/LuaSystem.hpp +++ b/include/Lua/LuaSystem.hpp @@ -49,11 +49,13 @@ public: void SetLastWrite(fs::file_time_type time); bool IsRegistered(const std::string&Event); void SetPluginName(const std::string&Name); + void Execute(const std::string& Command); void SetFileName(const std::string&Name); fs::file_time_type GetLastWrite(); std::string GetPluginName(); std::string GetFileName(); bool StopThread = false; + bool Console = false; lua_State* GetState(); char* GetOrigin(); std::mutex Lock; diff --git a/include/Startup.h b/include/Startup.h index 89a1bf0..7f0a54c 100644 --- a/include/Startup.h +++ b/include/Startup.h @@ -3,6 +3,7 @@ /// #pragma once void InitServer(int argc, char* argv[]); +void ConsoleInit(); void InitConfig(); void InitLua(); void InitRes(); diff --git a/src/Console.cpp b/src/Console.cpp new file mode 100644 index 0000000..1d01193 --- /dev/null +++ b/src/Console.cpp @@ -0,0 +1,93 @@ +/// +/// Created by Anonymous275 on 10/29/2020 +/// + +#include "Lua/LuaSystem.hpp" +#include +#include "Logger.h" +#include +#include +#include +#include +#include + +std::vector QConsoleOut; +std::string CInputBuff; +std::mutex MLock; +Lua* LuaConsole; +void HandleInput(const std::string& cmd){ + if (cmd == "exit") { + exit(0); + }else LuaConsole->Execute(cmd); +} + +void ProcessOut(){ + static size_t len = 2; + if(QConsoleOut.empty() && len == CInputBuff.length())return; + printf("%c[2K\r", 27); + for(const std::string& msg : QConsoleOut) + if(!msg.empty())std::cout << msg; + MLock.lock(); + QConsoleOut.clear(); + MLock.unlock(); + std::cout << "> " << CInputBuff; + len = CInputBuff.length(); +} + +void ConsoleOut(const std::string& msg){ + MLock.lock(); + QConsoleOut.emplace_back(msg); + MLock.unlock(); +} + +[[noreturn]] void OutputRefresh(){ + while(true){ + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + ProcessOut(); + } +} +void SetupConsole(){ + DWORD outMode = 0; + HANDLE stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE); + if (stdoutHandle == INVALID_HANDLE_VALUE){ + error("Invalid handle"); + std::this_thread::sleep_for(std::chrono::seconds(3)); + exit(GetLastError()); + } + if (!GetConsoleMode(stdoutHandle, &outMode)){ + error("Invalid console mode"); + std::this_thread::sleep_for(std::chrono::seconds(3)); + exit(GetLastError()); + } + // Enable ANSI escape codes + outMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; + if (!SetConsoleMode(stdoutHandle, outMode)) { + error("failed to set console mode"); + std::this_thread::sleep_for(std::chrono::seconds(3)); + exit(GetLastError()); + } +} +[[noreturn]] void ReadCin(){ + while (true){ + int In = _getch(); + if (In == 13) { + if(!CInputBuff.empty()) { + HandleInput(CInputBuff); + CInputBuff.clear(); + } + }else if(In == 8){ + if(!CInputBuff.empty())CInputBuff.pop_back(); + }else CInputBuff += char(In); + } +} +void ConsoleInit(){ + SetupConsole(); + LuaConsole = new Lua(); + LuaConsole->Console = true; + LuaConsole->Init(); + printf("> "); + std::thread In(ReadCin); + In.detach(); + std::thread Out(OutputRefresh); + Out.detach(); +} \ No newline at end of file diff --git a/src/Init/Startup.cpp b/src/Init/Startup.cpp index 8abaf6a..7e7a7ee 100644 --- a/src/Init/Startup.cpp +++ b/src/Init/Startup.cpp @@ -8,7 +8,7 @@ std::string CustomIP; std::string GetSVer(){ - static std::string r = Sec("0.63.5"); + static std::string r = Sec("0.64"); return r; } std::string GetCVer(){ diff --git a/src/Lua/LuaSystem.cpp b/src/Lua/LuaSystem.cpp index 6101341..1d7e44c 100644 --- a/src/Lua/LuaSystem.cpp +++ b/src/Lua/LuaSystem.cpp @@ -5,6 +5,7 @@ #include "Lua/LuaSystem.hpp" #include "Security/Enc.h" #include "Client.hpp" +#include "Settings.h" #include "Network.h" #include "Logger.h" #include @@ -38,7 +39,9 @@ Lua* GetScript(lua_State *L){ } void SendError(lua_State *L,const std::string&msg){ Lua* S = GetScript(L); - std::string a = S->GetFileName().substr(S->GetFileName().find('\\')); + std::string a; + if(S == nullptr)a = Sec("Console"); + else a = S->GetFileName().substr(S->GetFileName().find('\\')); warn(a + Sec(" | Incorrect Call of ") + msg); } int Trigger(Lua*lua,const std::string& R, LuaArg*arg){ @@ -76,7 +79,14 @@ int TriggerLuaEvent(const std::string& Event,bool local,Lua*Caller,LuaArg* arg,b } return R; } - +bool ConsoleCheck(lua_State *L, int r){ + if (r != LUA_OK){ + std::string msg = lua_tostring(L, -1); + warn(Sec("Console | ") + msg); + return false; + } + return true; +} bool CheckLua(lua_State *L, int r){ if (r != LUA_OK){ std::string msg = lua_tostring(L, -1); @@ -348,9 +358,8 @@ int lua_RemoteEvent(lua_State *L){ } 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){ - SendToAll(nullptr,Packet,true,true); - }else{ + if(ID == -1)SendToAll(nullptr,Packet,true,true); + else{ Client *c = GetClient(ID); if(c == nullptr){ SendError(L,Sec("TriggerClientEvent invalid Player ID")); @@ -360,6 +369,91 @@ int lua_RemoteEvent(lua_State *L){ } return 0; } +int lua_ServerExit(lua_State *L){ + exit(0); +} +int lua_Set(lua_State *L){ + int Args = lua_gettop(L); + if(Args != 2){ + SendError(L,Sec("set invalid argument count expected 2 got ") + std::to_string(Args)); + return 0; + } + if(!lua_isnumber(L,1)){ + SendError(L,Sec("set invalid argument [1] expected number")); + return 0; + } + Lua* Src = GetScript(L); + std::string Name; + if(Src == nullptr)Name = Sec("Console"); + else Name = Src->GetPluginName(); + int C = int(lua_tointeger(L,1)); + switch(C){ + case 0: //debug + if(lua_isboolean(L,2)){ + Debug = lua_toboolean(L,2); + info(Name + Sec(" | Debug -> ") + (Debug?"true":"false")); + } + else SendError(L,Sec("set invalid argument [2] expected boolean for ID : 0")); + break; + case 1: //private + if(lua_isboolean(L,2)){ + Private = lua_toboolean(L,2); + info(Name + Sec(" | Private -> ") + (Private?"true":"false")); + } + else SendError(L,Sec("set invalid argument [2] expected boolean for ID : 1")); + break; + case 2: //max cars + if(lua_isnumber(L,2)){ + MaxCars = int(lua_tointeger(L,2)); + info(Name + Sec(" | MaxCars -> ") + std::to_string(MaxCars)); + } + else SendError(L,Sec("set invalid argument [2] expected number for ID : 2")); + break; + case 3: //max players + if(lua_isnumber(L,2)){ + MaxPlayers = int(lua_tointeger(L,2)); + info(Name + Sec(" | MaxPlayers -> ") + std::to_string(MaxPlayers)); + } + else SendError(L,Sec("set invalid argument [2] expected number for ID : 3")); + break; + case 4: //Map + if(lua_isstring(L,2)){ + MapName = lua_tostring(L,2); + info(Name + Sec(" | MapName -> ") + MapName); + } + else SendError(L,Sec("set invalid argument [2] expected string for ID : 4")); + break; + case 5: //Name + if(lua_isstring(L,2)){ + ServerName = lua_tostring(L,2); + info(Name + Sec(" | ServerName -> ") + ServerName); + } + else SendError(L,Sec("set invalid argument [2] expected string for ID : 5")); + break; + case 6: //Desc + if(lua_isstring(L,2)){ + ServerDesc = lua_tostring(L,2); + info(Name + Sec(" | ServerDesc -> ") + ServerDesc); + } + else SendError(L,Sec("set invalid argument [2] expected string for ID : 6")); + break; + default: + warn(Sec("Invalid config ID : ") + std::to_string(C)); + break; + } + + return 0; +} +extern "C" { + int lua_Print(lua_State *L) { + int Arg = lua_gettop(L); + for (int i = 1; i <= Arg; i++){ + ConsoleOut(lua_tostring(L, i) + std::string("\n")); + } + return 0; + } +} + void Lua::Init(){ luaL_openlibs(luaState); lua_register(luaState,"TriggerGlobalEvent",lua_TriggerEventG); @@ -378,10 +472,17 @@ void Lua::Init(){ lua_register(luaState,"StopThread",lua_StopThread); lua_register(luaState,"DropPlayer",lua_dropPlayer); lua_register(luaState,"GetPlayerHWID",lua_HWID); + lua_register(luaState,"exit",lua_ServerExit); lua_register(luaState,"Sleep",lua_Sleep); - Reload(); + lua_register(luaState,"print",lua_Print); + lua_register(luaState,"Set",lua_Set); + if(!Console)Reload(); +} +void Lua::Execute(const std::string& Command){ + if(ConsoleCheck(luaState,luaL_dostring(luaState,Command.c_str()))){ + lua_settop(luaState, 0); + } } - void Lua::Reload(){ if(CheckLua(luaState,luaL_dofile(luaState,FileName.c_str()))){ CallFunction(this,Sec("onInit"), nullptr); diff --git a/src/logger.cpp b/src/logger.cpp index 61d91a7..222e038 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -7,6 +7,8 @@ #include #include #include +#include + std::string getDate() { typedef std::chrono::duration>::type> days; std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); @@ -43,6 +45,7 @@ void InitLog(){ error(Sec("logger file init failed!")); }else LFS.close(); } +std::mutex LogLock; void addToLog(const std::string& Line){ std::ofstream LFS; LFS.open (Sec("Server.log"), std::ios_base::app); @@ -50,31 +53,41 @@ void addToLog(const std::string& Line){ LFS.close(); } void info(const std::string& toPrint) { + LogLock.lock(); std::string Print = getDate() + Sec("[INFO] ") + toPrint + "\n"; - std::cout << Print; + ConsoleOut(Print); addToLog(Print); + LogLock.unlock(); } void debug(const std::string& toPrint) { if(!Debug)return; + LogLock.lock(); std::string Print = getDate() + Sec("[DEBUG] ") + toPrint + "\n"; - std::cout << Print; + ConsoleOut(Print); addToLog(Print); + LogLock.unlock(); } void warn(const std::string& toPrint){ + LogLock.lock(); std::string Print = getDate() + Sec("[WARN] ") + toPrint + "\n"; - std::cout << Print; + ConsoleOut(Print); addToLog(Print); + LogLock.unlock(); } void error(const std::string& toPrint) { static int ECounter = 0; + LogLock.lock(); std::string Print = getDate() + Sec("[ERROR] ") + toPrint + "\n"; - std::cout << Print; + ConsoleOut(Print); addToLog(Print); if(ECounter > 10)exit(7); ECounter++; + LogLock.unlock(); } void except(const std::string& toPrint) { + LogLock.lock(); std::string Print = getDate() + Sec("[EXCEP] ") + toPrint + "\n"; - std::cout << Print; + ConsoleOut(Print); addToLog(Print); + LogLock.unlock(); } diff --git a/src/main.cpp b/src/main.cpp index e1bb2a5..ec81acd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,8 +8,11 @@ } } int main(int argc, char* argv[]) { - std::thread t1(loop); - t1.detach(); + #ifdef DEBUG + std::thread t1(loop); + t1.detach(); + #endif + ConsoleInit(); InitServer(argc,argv); InitConfig(); InitLua();