diff --git a/CMakeLists.txt b/CMakeLists.txt index e53fab1..2f4e273 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -195,6 +195,7 @@ target_compile_definitions(${PROJECT_NAME} PRIVATE ${PRJ_DEFINITIONS} ${PRJ_WARN ) if(MSVC) + target_compile_options(${PROJECT_NAME} PUBLIC "/bigobj") target_link_options(${PROJECT_NAME} PRIVATE "/SUBSYSTEM:CONSOLE") endif(MSVC) diff --git a/include/Common.h b/include/Common.h index 4c264db..bb28a64 100644 --- a/include/Common.h +++ b/include/Common.h @@ -106,8 +106,6 @@ public: static std::vector GetBackendUrlsInOrder() { return { "backend.beammp.com", - "backup1.beammp.com", - "backup2.beammp.com" }; } @@ -152,7 +150,7 @@ private: static inline std::mutex mShutdownHandlersMutex {}; static inline std::deque mShutdownHandlers {}; - static inline Version mVersion { 3, 2, 2 }; + static inline Version mVersion { 3, 3, 0 }; }; void SplitString(std::string const& str, const char delim, std::vector& out); @@ -214,6 +212,10 @@ void RegisterThread(const std::string& str); do { \ Application::Console().Write(_this_location + std::string("[LUA ERROR] ") + (x)); \ } while (false) + #define beammp_lua_log(level, plugin, x) \ + do { \ + Application::Console().Write(_this_location + fmt::format("[{}] [{}] ", plugin, level) + (x)); \ + } while (false) #define beammp_lua_warn(x) \ do { \ Application::Console().Write(_this_location + std::string("[LUA WARN] ") + (x)); \ @@ -269,6 +271,7 @@ void RegisterThread(const std::string& str); #define beammp_tracef(...) beammp_trace(fmt::format(__VA_ARGS__)) #define beammp_lua_errorf(...) beammp_lua_error(fmt::format(__VA_ARGS__)) #define beammp_lua_warnf(...) beammp_lua_warn(fmt::format(__VA_ARGS__)) + #define beammp_lua_log(level, plugin, x) /* x */ #endif // DOCTEST_CONFIG_DISABLE diff --git a/include/Env.h b/include/Env.h index 2ff56c8..749cb3e 100644 --- a/include/Env.h +++ b/include/Env.h @@ -25,6 +25,8 @@ namespace Env { enum class Key { // provider settings PROVIDER_UPDATE_MESSAGE, + PROVIDER_DISABLE_CONFIG, + PROVIDER_PORT_ENV, }; std::optional Get(Key key); diff --git a/include/TConfig.h b/include/TConfig.h index 35e94c9..0701076 100644 --- a/include/TConfig.h +++ b/include/TConfig.h @@ -35,11 +35,11 @@ public: [[nodiscard]] bool Failed() const { return mFailed; } void FlushToFile(); + void PrintDebug(); private: void CreateConfigFile(); void ParseFromFile(std::string_view name); - void PrintDebug(); void TryReadValue(toml::value& Table, const std::string& Category, const std::string_view& Key, const std::string_view& Env, std::string& OutValue); void TryReadValue(toml::value& Table, const std::string& Category, const std::string_view& Key, const std::string_view& Env, bool& OutValue); void TryReadValue(toml::value& Table, const std::string& Category, const std::string_view& Key, const std::string_view& Env, int& OutValue); @@ -48,5 +48,6 @@ private: std::string TagsAsPrettyArray() const; bool IsDefault(); bool mFailed { false }; + bool mDisableConfig { false }; std::string mConfigFileName; }; diff --git a/src/Env.cpp b/src/Env.cpp index 0008252..a969de3 100644 --- a/src/Env.cpp +++ b/src/Env.cpp @@ -33,6 +33,12 @@ std::string_view Env::ToString(Env::Key key) { case Key::PROVIDER_UPDATE_MESSAGE: return "BEAMMP_PROVIDER_UPDATE_MESSAGE"; break; + case Key::PROVIDER_DISABLE_CONFIG: + return "BEAMMP_PROVIDER_DISABLE_CONFIG"; + break; + case Key::PROVIDER_PORT_ENV: + return "BEAMMP_PROVIDER_PORT_ENV"; + break; } return ""; } diff --git a/src/TConfig.cpp b/src/TConfig.cpp index 14c02e6..7192f87 100644 --- a/src/TConfig.cpp +++ b/src/TConfig.cpp @@ -18,6 +18,7 @@ #include "Common.h" +#include "Env.h" #include "TConfig.h" #include #include @@ -87,7 +88,9 @@ TEST_CASE("TConfig::TConfig") { TConfig::TConfig(const std::string& ConfigFileName) : mConfigFileName(ConfigFileName) { Application::SetSubsystemStatus("Config", Application::Status::Starting); - if (!fs::exists(mConfigFileName) || !fs::is_regular_file(mConfigFileName)) { + auto DisableConfig = Env::Get(Env::Key::PROVIDER_DISABLE_CONFIG).value_or("false"); + mDisableConfig = DisableConfig == "true" || DisableConfig == "1"; + if (!mDisableConfig && (!fs::exists(mConfigFileName) || !fs::is_regular_file(mConfigFileName))) { beammp_info("No config file found! Generating one..."); CreateConfigFile(); } @@ -161,7 +164,9 @@ void TConfig::FlushToFile() { void TConfig::CreateConfigFile() { // build from old config Server.cfg - + if (mDisableConfig) { + return; + } try { if (fs::exists("Server.cfg")) { // parse it (this is weird and bad and should be removed in some future version) @@ -181,6 +186,9 @@ void TConfig::TryReadValue(toml::value& Table, const std::string& Category, cons return; } } + if (mDisableConfig) { + return; + } if (Table[Category.c_str()][Key.data()].is_string()) { OutValue = Table[Category.c_str()][Key.data()].as_string(); } @@ -194,6 +202,9 @@ void TConfig::TryReadValue(toml::value& Table, const std::string& Category, cons return; } } + if (mDisableConfig) { + return; + } if (Table[Category.c_str()][Key.data()].is_boolean()) { OutValue = Table[Category.c_str()][Key.data()].as_boolean(); } @@ -206,6 +217,9 @@ void TConfig::TryReadValue(toml::value& Table, const std::string& Category, cons return; } } + if (mDisableConfig) { + return; + } if (Table[Category.c_str()][Key.data()].is_integer()) { OutValue = int(Table[Category.c_str()][Key.data()].as_integer()); } @@ -213,11 +227,18 @@ void TConfig::TryReadValue(toml::value& Table, const std::string& Category, cons void TConfig::ParseFromFile(std::string_view name) { try { - toml::value data = toml::parse(name.data()); + toml::value data {}; + if (!mDisableConfig) { + data = toml::parse(name.data()); + } // GENERAL TryReadValue(data, "General", StrDebug, EnvStrDebug, Application::Settings.DebugModeEnabled); TryReadValue(data, "General", StrPrivate, EnvStrPrivate, Application::Settings.Private); - TryReadValue(data, "General", StrPort, EnvStrPort, Application::Settings.Port); + if (Env::Get(Env::Key::PROVIDER_PORT_ENV).has_value()) { + TryReadValue(data, "General", StrPort, Env::Get(Env::Key::PROVIDER_PORT_ENV).value(), Application::Settings.Port); + } else { + TryReadValue(data, "General", StrPort, EnvStrPort, Application::Settings.Port); + } TryReadValue(data, "General", StrMaxCars, EnvStrMaxCars, Application::Settings.MaxCars); TryReadValue(data, "General", StrMaxPlayers, EnvStrMaxPlayers, Application::Settings.MaxPlayers); TryReadValue(data, "General", StrMap, EnvStrMap, Application::Settings.MapName); @@ -238,13 +259,18 @@ void TConfig::ParseFromFile(std::string_view name) { Application::SetSubsystemStatus("Config", Application::Status::Bad); return; } - PrintDebug(); // Update in any case - FlushToFile(); + if (!mDisableConfig) { + FlushToFile(); + } // all good so far, let's check if there's a key if (Application::Settings.Key.empty()) { - beammp_error("No AuthKey specified in the \"" + std::string(mConfigFileName) + "\" file. Please get an AuthKey, enter it into the config file, and restart this server."); + if (mDisableConfig) { + beammp_error("No AuthKey specified in the environment."); + } else { + beammp_error("No AuthKey specified in the \"" + std::string(mConfigFileName) + "\" file. Please get an AuthKey, enter it into the config file, and restart this server."); + } Application::SetSubsystemStatus("Config", Application::Status::Bad); mFailed = true; return; @@ -256,6 +282,9 @@ void TConfig::ParseFromFile(std::string_view name) { } void TConfig::PrintDebug() { + if (mDisableConfig) { + beammp_debug("Provider turned off the generation and parsing of the ServerConfig.toml"); + } beammp_debug(std::string(StrDebug) + ": " + std::string(Application::Settings.DebugModeEnabled ? "true" : "false")); beammp_debug(std::string(StrPrivate) + ": " + std::string(Application::Settings.Private ? "true" : "false")); beammp_debug(std::string(StrPort) + ": " + std::to_string(Application::Settings.Port)); diff --git a/src/TLuaEngine.cpp b/src/TLuaEngine.cpp index 5dff14e..031e5cc 100644 --- a/src/TLuaEngine.cpp +++ b/src/TLuaEngine.cpp @@ -18,6 +18,7 @@ #include "TLuaEngine.h" #include "Client.h" +#include "Common.h" #include "CustomAssert.h" #include "Http.h" #include "LuaAPI.h" @@ -829,6 +830,40 @@ TLuaEngine::StateThreadData::StateThreadData(const std::string& Name, TLuaStateI MPTable.set_function("Set", &LuaAPI::MP::Set); auto UtilTable = StateView.create_named_table("Util"); + UtilTable.set_function("LogDebug", [this](sol::variadic_args args) { + std::string ToPrint = ""; + for (const auto& arg : args) { + ToPrint += LuaAPI::LuaToString(static_cast(arg)); + ToPrint += "\t"; + } + if (Application::Settings.DebugModeEnabled) { + beammp_lua_log("DEBUG", mStateId, ToPrint); + } + }); + UtilTable.set_function("LogInfo", [this](sol::variadic_args args) { + std::string ToPrint = ""; + for (const auto& arg : args) { + ToPrint += LuaAPI::LuaToString(static_cast(arg)); + ToPrint += "\t"; + } + beammp_lua_log("INFO", mStateId, ToPrint); + }); + UtilTable.set_function("LogWarn", [this](sol::variadic_args args) { + std::string ToPrint = ""; + for (const auto& arg : args) { + ToPrint += LuaAPI::LuaToString(static_cast(arg)); + ToPrint += "\t"; + } + beammp_lua_log("WARN", mStateId, ToPrint); + }); + UtilTable.set_function("LogError", [this](sol::variadic_args args) { + std::string ToPrint = ""; + for (const auto& arg : args) { + ToPrint += LuaAPI::LuaToString(static_cast(arg)); + ToPrint += "\t"; + } + beammp_lua_log("ERROR", mStateId, ToPrint); + }); UtilTable.set_function("JsonEncode", &LuaAPI::MP::JsonEncode); UtilTable.set_function("JsonDecode", [this](const std::string& str) { return Lua_JsonDecode(str); @@ -1101,7 +1136,7 @@ void TLuaResult::MarkAsReady() { void TLuaResult::WaitUntilReady() { std::unique_lock readyLock(*this->ReadyMutex); // wait if not ready yet - if(!this->Ready) + if (!this->Ready) this->ReadyCondition->wait(readyLock); } diff --git a/src/TPPSMonitor.cpp b/src/TPPSMonitor.cpp index 3fef0a0..b891a22 100644 --- a/src/TPPSMonitor.cpp +++ b/src/TPPSMonitor.cpp @@ -65,10 +65,13 @@ void TPPSMonitor::operator()() { V += c->GetCarCount(); } // kick on "no ping" - if (c->SecondsSinceLastPing() > (20 * 60)) { - beammp_debug("client " + std::string("(") + std::to_string(c->GetID()) + ")" + c->GetName() + " timing out: " + std::to_string(c->SecondsSinceLastPing()) + ", pps: " + Application::PPS()); + if (c->SecondsSinceLastPing() > (20 * 60) ){ + beammp_debugf("client {} ({}) timing out: {}", c->GetID(), c->GetName(), c->SecondsSinceLastPing()); TimedOutClients.push_back(c); - } + } else if (c->IsSynced() && c->SecondsSinceLastPing() > (1 * 60)) { + beammp_debugf("client {} ({}) timing out: {}", c->GetName(), c->GetID(), c->SecondsSinceLastPing()); + TimedOutClients.push_back(c); + } return true; }); diff --git a/src/main.cpp b/src/main.cpp index 311fa26..309eef7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -30,6 +30,7 @@ #include "TResourceManager.h" #include "TServer.h" +#include #include #include @@ -40,6 +41,9 @@ USAGE: ARGUMENTS: --help Displays this help and exits. + --port=1234 + Sets the server's listening TCP and + UDP port. Overrides ENV and ServerConfig. --config=/path/to/ServerConfig.toml Absolute or relative path to the Server Config file, including the @@ -91,6 +95,7 @@ int BeamMPServerMain(MainArguments Arguments) { Parser.RegisterArgument({ "help" }, ArgsParser::NONE); Parser.RegisterArgument({ "version" }, ArgsParser::NONE); Parser.RegisterArgument({ "config" }, ArgsParser::HAS_VALUE); + Parser.RegisterArgument({ "port" }, ArgsParser::HAS_VALUE); Parser.RegisterArgument({ "working-directory" }, ArgsParser::HAS_VALUE); Parser.Parse(Arguments.List); if (!Parser.Verify()) { @@ -124,7 +129,7 @@ int BeamMPServerMain(MainArguments Arguments) { } } } - + TConfig Config(ConfigPath); if (Config.Failed()) { @@ -135,6 +140,24 @@ int BeamMPServerMain(MainArguments Arguments) { } return 1; } + + // override port if provided via arguments + if (Parser.FoundArgument({ "port" })) { + auto Port = Parser.GetValueOfArgument({ "port" }); + if (Port.has_value()) { + auto P = int(std::strtoul(Port.value().c_str(), nullptr, 10)); + if (P == 0 || P < 0 || P > UINT16_MAX) { + beammp_errorf("Custom port requested via --port is invalid: '{}'", Port.value()); + return 1; + } else { + Application::Settings.Port = P; + beammp_info("Custom port requested via commandline arguments: " + Port.value()); + } + } + } + + Config.PrintDebug(); + Application::InitializeConsole(); Application::Console().StartLoggingToFile(); diff --git a/vcpkg b/vcpkg index 6978381..326d8b4 160000 --- a/vcpkg +++ b/vcpkg @@ -1 +1 @@ -Subproject commit 6978381401d33a5ad6a3385895d12e383083712a +Subproject commit 326d8b43e365352ba3ccadf388d989082fe0f2a6