From 8c15b87628e674e467679f2a257f2e0356ae5956 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucca=20Jim=C3=A9nez=20K=C3=B6nings?= Date: Wed, 15 May 2024 12:52:09 +0200 Subject: [PATCH] Refactor all references to settings to use new `Settings` type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lucca Jiménez Könings --- include/Common.h | 9 +- include/TSettings.h | 10 +- src/Common.cpp | 16 ++-- src/Compat.cpp | 2 +- src/LuaAPI.cpp | 29 +++--- src/TConfig.cpp | 197 +++++++++++++-------------------------- src/TConsole.cpp | 83 ++++++++--------- src/THeartbeatThread.cpp | 27 +++--- src/TLuaEngine.cpp | 10 +- src/TNetwork.cpp | 16 ++-- src/TResourceManager.cpp | 2 +- src/TServer.cpp | 2 +- src/main.cpp | 8 +- 13 files changed, 168 insertions(+), 243 deletions(-) diff --git a/include/Common.h b/include/Common.h index 3127011..56565e3 100644 --- a/include/Common.h +++ b/include/Common.h @@ -102,8 +102,7 @@ public: static std::string PPS() { return mPPS; } static void SetPPS(const std::string& NewPPS) { mPPS = NewPPS; } - static TSettings Settings; - static inline struct Settings SettingsSingleton { }; + static inline struct Settings Settings { }; static std::vector GetBackendUrlsInOrder() { return { @@ -225,13 +224,13 @@ void RegisterThread(const std::string& str); #define luaprint(x) Application::Console().Write(_this_location + std::string("[LUA] ") + (x)) #define beammp_debug(x) \ do { \ - if (Application::Settings.DebugModeEnabled) { \ + if (Application::Settings.getAsBool(Settings::Key::General_Debug)) { \ Application::Console().Write(_this_location + std::string("[DEBUG] ") + (x)); \ } \ } while (false) #define beammp_event(x) \ do { \ - if (Application::Settings.DebugModeEnabled) { \ + if (Application::Settings.getAsBool(Settings::Key::General_Debug)) { \ Application::Console().Write(_this_location + std::string("[EVENT] ") + (x)); \ } \ } while (false) @@ -239,7 +238,7 @@ void RegisterThread(const std::string& str); #if defined(DEBUG) #define beammp_trace(x) \ do { \ - if (Application::Settings.DebugModeEnabled) { \ + if (Application::Settings.getAsBool(Settings::Key::General_Debug)) { \ Application::Console().Write(_this_location + std::string("[TRACE] ") + (x)); \ } \ } while (false) diff --git a/include/TSettings.h b/include/TSettings.h index aec0b79..e6e191b 100644 --- a/include/TSettings.h +++ b/include/TSettings.h @@ -17,6 +17,7 @@ // along with this program. If not, see . #pragma once +#include "Sync.h" #include #include #include @@ -24,7 +25,6 @@ #include #include #include -#include "Sync.h" struct ComposedKey { std::string Category; @@ -83,9 +83,9 @@ struct Settings { General_Debug }; - Sync> SettingsMap = std::unordered_map{ - { General_Description, "BeamMP Default Description" }, - { General_Tags, "Freeroam" }, + Sync> SettingsMap = std::unordered_map { + { General_Description, std::string("BeamMP Default Description") }, + { General_Tags, std::string("Freeroam") }, { General_MaxPlayers, 8 }, { General_Name, "BeamMP Server" }, { General_Map, "/levels/gridmap_v2/info.json" }, @@ -112,7 +112,7 @@ struct Settings { SettingsAccessMask // Console read/write permissions >; - Sync> InputAccessMapping = std::unordered_map{ + Sync> InputAccessMapping = std::unordered_map { { { "General", "Description" }, { General_Description, write } }, { { "General", "Tags" }, { General_Tags, write } }, { { "General", "MaxPlayers" }, { General_MaxPlayers, write } }, diff --git a/src/Common.cpp b/src/Common.cpp index c2ac242..f4a4319 100644 --- a/src/Common.cpp +++ b/src/Common.cpp @@ -33,8 +33,6 @@ #include "CustomAssert.h" #include "Http.h" -Application::TSettings Application::Settings = {}; - void Application::RegisterShutdownHandler(const TShutdownHandler& Handler) { std::unique_lock Lock(mShutdownHandlersMutex); if (Handler) { @@ -256,7 +254,7 @@ static std::mutex ThreadNameMapMutex {}; std::string ThreadName(bool DebugModeOverride) { auto Lock = std::unique_lock(ThreadNameMapMutex); - if (DebugModeOverride || Application::Settings.DebugModeEnabled) { + if (DebugModeOverride || Application::Settings.getAsBool(Settings::Key::General_Debug)) { auto id = std::this_thread::get_id(); if (threadNameMap.find(id) != threadNameMap.end()) { // found @@ -268,21 +266,21 @@ std::string ThreadName(bool DebugModeOverride) { TEST_CASE("ThreadName") { RegisterThread("MyThread"); - auto OrigDebug = Application::Settings.DebugModeEnabled; + auto OrigDebug = Application::Settings.getAsBool(Settings::Key::General_Debug); // ThreadName adds a space at the end, legacy but we need it still SUBCASE("Debug mode enabled") { - Application::Settings.DebugModeEnabled = true; + Application::Settings.set(Settings::Key::General_Debug, true); CHECK(ThreadName(true) == "MyThread "); CHECK(ThreadName(false) == "MyThread "); } SUBCASE("Debug mode disabled") { - Application::Settings.DebugModeEnabled = false; + Application::Settings.set(Settings::Key::General_Debug, false); CHECK(ThreadName(true) == "MyThread "); CHECK(ThreadName(false) == ""); } // cleanup - Application::Settings.DebugModeEnabled = OrigDebug; + Application::Settings.set(Settings::Key::General_Debug, OrigDebug); } void RegisterThread(const std::string& str) { @@ -296,7 +294,7 @@ void RegisterThread(const std::string& str) { #elif defined(BEAMMP_FREEBSD) ThreadId = std::to_string(getpid()); #endif - if (Application::Settings.DebugModeEnabled) { + if (Application::Settings.getAsBool(Settings::Key::General_Debug)) { std::ofstream ThreadFile(".Threads.log", std::ios::app); ThreadFile << ("Thread \"" + str + "\" is TID " + ThreadId) << std::endl; } @@ -329,7 +327,7 @@ TEST_CASE("Version::AsString") { } void LogChatMessage(const std::string& name, int id, const std::string& msg) { - if (Application::Settings.LogChat) { + if (Application::Settings.getAsBool(Settings::Key::General_LogChat)) { std::stringstream ss; ss << ThreadName(); ss << "[CHAT] "; diff --git a/src/Compat.cpp b/src/Compat.cpp index 5f95a16..145828f 100644 --- a/src/Compat.cpp +++ b/src/Compat.cpp @@ -61,7 +61,7 @@ TEST_CASE("init and reset termios") { CHECK_EQ(current.c_lflag, original.c_lflag); #ifndef BEAMMP_FREEBSD // The 'c_line' attribute seems to only exist on Linux, so we need to omit it on other platforms CHECK_EQ(current.c_line, original.c_line); -#endif +#endif CHECK_EQ(current.c_oflag, original.c_oflag); CHECK_EQ(current.c_ospeed, original.c_ospeed); } diff --git a/src/LuaAPI.cpp b/src/LuaAPI.cpp index a395f64..2e99655 100644 --- a/src/LuaAPI.cpp +++ b/src/LuaAPI.cpp @@ -21,6 +21,7 @@ #include "Common.h" #include "CustomAssert.h" #include "TLuaEngine.h" +#include "TSettings.h" #include @@ -226,56 +227,56 @@ void LuaAPI::MP::Set(int ConfigID, sol::object NewValue) { switch (ConfigID) { case 0: // debug if (NewValue.is()) { - Application::Settings.DebugModeEnabled = NewValue.as(); - beammp_info(std::string("Set `Debug` to ") + (Application::Settings.DebugModeEnabled ? "true" : "false")); + Application::Settings.set(Settings::Key::General_Debug, NewValue.as()); + beammp_info(std::string("Set `Debug` to ") + (Application::Settings.getAsBool(Settings::Key::General_Debug) ? "true" : "false")); } else { beammp_lua_error("set invalid argument [2] expected boolean"); } break; case 1: // private if (NewValue.is()) { - Application::Settings.Private = NewValue.as(); - beammp_info(std::string("Set `Private` to ") + (Application::Settings.Private ? "true" : "false")); + Application::Settings.set(Settings::Key::General_Private, NewValue.as()); + beammp_info(std::string("Set `Private` to ") + (Application::Settings.getAsBool(Settings::Key::General_Private) ? "true" : "false")); } else { beammp_lua_error("set invalid argument [2] expected boolean"); } break; case 2: // max cars if (NewValue.is()) { - Application::Settings.MaxCars = NewValue.as(); - beammp_info(std::string("Set `MaxCars` to ") + std::to_string(Application::Settings.MaxCars)); + Application::Settings.set(Settings::Key::General_MaxCars, NewValue.as()); + beammp_info(std::string("Set `MaxCars` to ") + std::to_string(Application::Settings.getAsInt(Settings::Key::General_MaxCars))); } else { beammp_lua_error("set invalid argument [2] expected integer"); } break; case 3: // max players if (NewValue.is()) { - Application::Settings.MaxPlayers = NewValue.as(); - beammp_info(std::string("Set `MaxPlayers` to ") + std::to_string(Application::Settings.MaxPlayers)); + Application::Settings.set(Settings::Key::General_MaxPlayers, NewValue.as()); + beammp_info(std::string("Set `MaxPlayers` to ") + std::to_string(Application::Settings.getAsInt(Settings::Key::General_MaxPlayers))); } else { beammp_lua_error("set invalid argument [2] expected integer"); } break; case 4: // Map if (NewValue.is()) { - Application::Settings.MapName = NewValue.as(); - beammp_info(std::string("Set `Map` to ") + Application::Settings.MapName); + Application::Settings.set(Settings::Key::General_Map, NewValue.as()); + beammp_info(std::string("Set `Map` to ") + Application::Settings.getAsString(Settings::Key::General_Map)); } else { beammp_lua_error("set invalid argument [2] expected string"); } break; case 5: // Name if (NewValue.is()) { - Application::Settings.ServerName = NewValue.as(); - beammp_info(std::string("Set `Name` to ") + Application::Settings.ServerName); + Application::Settings.set(Settings::Key::General_Name, NewValue.as()); + beammp_info(std::string("Set `Name` to ") + Application::Settings.getAsString(Settings::Key::General_Name)); } else { beammp_lua_error("set invalid argument [2] expected string"); } break; case 6: // Desc if (NewValue.is()) { - Application::Settings.ServerDesc = NewValue.as(); - beammp_info(std::string("Set `Description` to ") + Application::Settings.ServerDesc); + Application::Settings.set(Settings::Key::General_Description, NewValue.as()); + beammp_info(std::string("Set `Description` to ") + Application::Settings.getAsString(Settings::Key::General_Description)); } else { beammp_lua_error("set invalid argument [2] expected string"); } diff --git a/src/TConfig.cpp b/src/TConfig.cpp index f0722c3..daf8b7e 100644 --- a/src/TConfig.cpp +++ b/src/TConfig.cpp @@ -20,11 +20,14 @@ #include "Env.h" #include "TConfig.h" +#include "TSettings.h" #include +#include #include #include #include #include +#include // General static constexpr std::string_view StrDebug = "Debug"; @@ -120,29 +123,29 @@ void SetComment(CommentsT& Comments, const std::string& Comment) { void TConfig::FlushToFile() { // auto data = toml::parse(mConfigFileName); auto data = toml::value {}; - data["General"][StrAuthKey.data()] = Application::Settings.Key; + data["General"][StrAuthKey.data()] = Application::Settings.getAsString(Settings::Key::General_AuthKey); SetComment(data["General"][StrAuthKey.data()].comments(), " AuthKey has to be filled out in order to run the server"); - data["General"][StrLogChat.data()] = Application::Settings.LogChat; + data["General"][StrLogChat.data()] = Application::Settings.getAsBool(Settings::Key::General_LogChat); SetComment(data["General"][StrLogChat.data()].comments(), " Whether to log chat messages in the console / log"); - data["General"][StrDebug.data()] = Application::Settings.DebugModeEnabled; - data["General"][StrPrivate.data()] = Application::Settings.Private; - data["General"][StrPort.data()] = Application::Settings.Port; - data["General"][StrName.data()] = Application::Settings.ServerName; + data["General"][StrDebug.data()] = Application::Settings.getAsBool(Settings::Key::General_Debug); + data["General"][StrPrivate.data()] = Application::Settings.getAsBool(Settings::Key::General_Private); + data["General"][StrPort.data()] = Application::Settings.getAsInt(Settings::Key::General_Port); + data["General"][StrName.data()] = Application::Settings.getAsString(Settings::Key::General_Name); SetComment(data["General"][StrTags.data()].comments(), " Add custom identifying tags to your server to make it easier to find. Format should be TagA,TagB,TagC. Note the comma seperation."); - data["General"][StrTags.data()] = Application::Settings.ServerTags; - data["General"][StrMaxCars.data()] = Application::Settings.MaxCars; - data["General"][StrMaxPlayers.data()] = Application::Settings.MaxPlayers; - data["General"][StrMap.data()] = Application::Settings.MapName; - data["General"][StrDescription.data()] = Application::Settings.ServerDesc; - data["General"][StrResourceFolder.data()] = Application::Settings.Resource; + data["General"][StrTags.data()] = Application::Settings.getAsString(Settings::Key::General_Tags); + data["General"][StrMaxCars.data()] = Application::Settings.getAsInt(Settings::Key::General_MaxCars); + data["General"][StrMaxPlayers.data()] = Application::Settings.getAsInt(Settings::Key::General_MaxCars); + data["General"][StrMap.data()] = Application::Settings.getAsString(Settings::Key::General_Map); + data["General"][StrDescription.data()] = Application::Settings.getAsString(Settings::Key::General_Description); + data["General"][StrResourceFolder.data()] = Application::Settings.getAsString(Settings::Key::General_ResourceFolder); // data["General"][StrPassword.data()] = Application::Settings.Password; // SetComment(data["General"][StrPassword.data()].comments(), " Sets a password on this server, which restricts people from joining. To join, a player must enter this exact password. Leave empty ("") to disable the password."); // Misc - data["Misc"][StrHideUpdateMessages.data()] = Application::Settings.HideUpdateMessages; + data["Misc"][StrHideUpdateMessages.data()] = Application::Settings.getAsBool(Settings::Key::Misc_ImScaredOfUpdates); SetComment(data["Misc"][StrHideUpdateMessages.data()].comments(), " Hides the periodic update message which notifies you of a new server version. You should really keep this on and always update as soon as possible. For more information visit https://wiki.beammp.com/en/home/server-maintenance#updating-the-server. An update message will always appear at startup regardless."); - data["Misc"][StrSendErrors.data()] = Application::Settings.SendErrors; + data["Misc"][StrSendErrors.data()] = Application::Settings.getAsBool(Settings::Key::Misc_SendErrors); SetComment(data["Misc"][StrSendErrors.data()].comments(), " If SendErrors is `true`, the server will send helpful info about crashes and other issues back to the BeamMP developers. This info may include your config, who is on your server at the time of the error, and similar general information. This kind of data is vital in helping us diagnose and fix issues faster. This has no impact on server performance. You can opt-out of this system by setting this to `false`"); - data["Misc"][StrSendErrorsMessageEnabled.data()] = Application::Settings.SendErrorsMessageEnabled; + data["Misc"][StrSendErrorsMessageEnabled.data()] = Application::Settings.getAsBool(Settings::Key::Misc_SendErrorsShowMessage); SetComment(data["Misc"][StrSendErrorsMessageEnabled.data()].comments(), " You can turn on/off the SendErrors message you get on startup here"); std::stringstream Ss; Ss << "# This is the BeamMP-Server config file.\n" @@ -190,76 +193,59 @@ overloaded(Ts...) -> overloaded; void TConfig::TryReadValue(toml::value& Table, const std::string& Category, const std::string_view& Key, const std::string_view& Env, Settings::Key key) { if (!Env.empty()) { - if (const char* envp = std::getenv(Env.data()); envp != nullptr && std::strcmp(envp, "") != 0) { + if (const char* envp = std::getenv(Env.data()); + envp != nullptr && std::strcmp(envp, "") != 0) { std::visit( overloaded { [&envp, &key](std::string) { - Application::SettingsSingleton.set(key, std::string(envp)); + Application::Settings.set(key, std::string(envp)); }, [&envp, &key](int) { - Application::SettingsSingleton.set(key, int(std::strtol(envp, nullptr, 10))); + Application::Settings.set(key, int(std::strtol(envp, nullptr, 10))); }, [&envp, &key](bool) { auto Str = std::string(envp); - Application::SettingsSingleton.set(key, bool(Str == "1" || Str == "true")); + Application::Settings.set(key, bool(Str == "1" || Str == "true")); } }, - Application::SettingsSingleton.get(key)); - } - } else { - std::visit( - overloaded { - [&Table, &Category, &Key, &key](std::string) { - if (Table[Category.c_str()][Key.data()].is_string()) - Application::SettingsSingleton.set(key, Table[Category.c_str()][Key.data()].as_string()); - else - beammp_warnf("Value '{}.{}' has unexpected type, expected type 'string'", Category, Key); - }, - [&Table, &Category, &Key, &key](int) { - if (Table[Category.c_str()][Key.data()].is_integer()) - Application::SettingsSingleton.set(key, int(Table[Category.c_str()][Key.data()].as_integer())); - else - beammp_warnf("Value '{}.{}' has unexpected type, expected type 'integer'", Category, Key); - }, - [&Table, &Category, &Key, &key](bool) { - if (Table[Category.c_str()][Key.data()].is_boolean()) - Application::SettingsSingleton.set(key, Table[Category.c_str()][Key.data()].as_boolean()); - else - beammp_warnf("Value '{}.{}' has unexpected type, expected type 'boolean'", Category, Key); - } }, - Application::SettingsSingleton.get(key)); + Application::Settings.get(key)); + return; + } } + + std::visit([&Table, &Category, &Key, &key](auto&& arg) { + using T = std::decay_t; + if constexpr (std::is_same_v) { + if (Table[Category.c_str()][Key.data()].is_string()) + Application::Settings.set(key, Table[Category.c_str()][Key.data()].as_string()); + else + beammp_warnf("Value '{}.{}' has unexpected type, expected type 'string'", Category, Key); + } else if constexpr (std::is_same_v) { + if (Table[Category.c_str()][Key.data()].is_integer()) + Application::Settings.set(key, int(Table[Category.c_str()][Key.data()].as_integer())); + else + beammp_warnf("Value '{}.{}' has unexpected type, expected type 'integer'", Category, Key); + } else if constexpr (std::is_same_v) { + if (Table[Category.c_str()][Key.data()].is_boolean()) + Application::Settings.set(key, Table[Category.c_str()][Key.data()].as_boolean()); + else + beammp_warnf("Value '{}.{}' has unexpected type, expected type 'boolean'", Category, Key); + } else { + throw std::logic_error { "Invalid type for config value during read attempt" }; + } + }, + Application::Settings.get(key)); } void TConfig::ParseFromFile(std::string_view name) { try { toml::value data {}; - if (!mDisableConfig) { + if (!mDisableConfig) { // todo: rename mDisableCofig to configEnabled data = toml::parse(name.data()); } + // GENERAL - TryReadValue(data, "General", StrDebug, EnvStrDebug, Application::Settings.DebugModeEnabled); - TryReadValue(data, "General", StrPrivate, EnvStrPrivate, Application::Settings.Private); - 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); - TryReadValue(data, "General", StrName, EnvStrName, Application::Settings.ServerName); - TryReadValue(data, "General", StrDescription, EnvStrDescription, Application::Settings.ServerDesc); - TryReadValue(data, "General", StrTags, EnvStrTags, Application::Settings.ServerTags); - TryReadValue(data, "General", StrResourceFolder, EnvStrResourceFolder, Application::Settings.Resource); - TryReadValue(data, "General", StrAuthKey, EnvStrAuthKey, Application::Settings.Key); - TryReadValue(data, "General", StrLogChat, EnvStrLogChat, Application::Settings.LogChat); - TryReadValue(data, "General", StrPassword, "", Application::Settings.Password); - // Misc - TryReadValue(data, "Misc", StrSendErrors, "", Application::Settings.SendErrors); - TryReadValue(data, "Misc", StrHideUpdateMessages, "", Application::Settings.HideUpdateMessages); - TryReadValue(data, "Misc", StrSendErrorsMessageEnabled, "", Application::Settings.SendErrorsMessageEnabled); // Read into new Settings Singleton TryReadValue(data, "General", StrDebug, EnvStrDebug, Settings::Key::General_Debug); @@ -291,7 +277,7 @@ void TConfig::ParseFromFile(std::string_view name) { FlushToFile(); } // all good so far, let's check if there's a key - if (Application::Settings.Key.empty()) { + if (Application::Settings.getAsString(Settings::Key::General_AuthKey).empty()) { if (mDisableConfig) { beammp_error("No AuthKey specified in the environment."); } else { @@ -302,7 +288,7 @@ void TConfig::ParseFromFile(std::string_view name) { return; } Application::SetSubsystemStatus("Config", Application::Status::Good); - if (Application::Settings.Key.size() != 36) { + if (Application::Settings.getAsString(Settings::Key::General_AuthKey).size() != 36) { beammp_warn("AuthKey specified is the wrong length and likely isn't valid."); } } @@ -311,77 +297,24 @@ 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)); - beammp_debug(std::string(StrMaxCars) + ": " + std::to_string(Application::Settings.MaxCars)); - beammp_debug(std::string(StrMaxPlayers) + ": " + std::to_string(Application::Settings.MaxPlayers)); - beammp_debug(std::string(StrMap) + ": \"" + Application::Settings.MapName + "\""); - beammp_debug(std::string(StrName) + ": \"" + Application::Settings.ServerName + "\""); - beammp_debug(std::string(StrDescription) + ": \"" + Application::Settings.ServerDesc + "\""); + beammp_debug(std::string(StrDebug) + ": " + std::string(Application::Settings.getAsBool(Settings::Key::General_Debug) ? "true" : "false")); + beammp_debug(std::string(StrPrivate) + ": " + std::string(Application::Settings.getAsBool(Settings::Key::General_Private) ? "true" : "false")); + beammp_debug(std::string(StrPort) + ": " + std::to_string(Application::Settings.getAsInt(Settings::Key::General_Port))); + beammp_debug(std::string(StrMaxCars) + ": " + std::to_string(Application::Settings.getAsInt(Settings::Key::General_MaxCars))); + beammp_debug(std::string(StrMaxPlayers) + ": " + std::to_string(Application::Settings.getAsInt(Settings::Key::General_MaxPlayers))); + beammp_debug(std::string(StrMap) + ": \"" + Application::Settings.getAsString(Settings::Key::General_Map) + "\""); + beammp_debug(std::string(StrName) + ": \"" + Application::Settings.getAsString(Settings::Key::General_Name) + "\""); + beammp_debug(std::string(StrDescription) + ": \"" + Application::Settings.getAsString(Settings::Key::General_Description) + "\""); beammp_debug(std::string(StrTags) + ": " + TagsAsPrettyArray()); - beammp_debug(std::string(StrLogChat) + ": \"" + (Application::Settings.LogChat ? "true" : "false") + "\""); - beammp_debug(std::string(StrResourceFolder) + ": \"" + Application::Settings.Resource + "\""); + beammp_debug(std::string(StrLogChat) + ": \"" + (Application::Settings.getAsBool(Settings::Key::General_LogChat) ? "true" : "false") + "\""); + beammp_debug(std::string(StrResourceFolder) + ": \"" + Application::Settings.getAsString(Settings::Key::General_ResourceFolder) + "\""); // special! - beammp_debug("Key Length: " + std::to_string(Application::Settings.Key.length()) + ""); - beammp_debug("Password Protected: " + std::string(Application::Settings.Password.empty() ? "false" : "true")); + beammp_debug("Key Length: " + std::to_string(Application::Settings.getAsString(Settings::Key::General_AuthKey).length()) + ""); } -void TConfig::ParseOldFormat() { - std::ifstream File("Server.cfg"); - // read all, strip comments - std::string Content; - for (;;) { - std::string Line; - std::getline(File, Line); - if (!Line.empty() && Line.at(0) != '#') { - Line = Line.substr(0, Line.find_first_of('#')); - Content += Line + "\n"; - } - if (!File.good()) { - break; - } - } - std::stringstream Str(Content); - std::string Key, Ignore, Value; - for (;;) { - Str >> Key >> std::ws >> Ignore >> std::ws; - std::getline(Str, Value); - if (Str.eof()) { - break; - } - std::stringstream ValueStream(Value); - ValueStream >> std::ws; // strip leading whitespace if any - Value = ValueStream.str(); - if (Key == "Debug") { - Application::Settings.DebugModeEnabled = Value.find("true") != std::string::npos; - } else if (Key == "Private") { - Application::Settings.Private = Value.find("true") != std::string::npos; - } else if (Key == "Port") { - ValueStream >> Application::Settings.Port; - } else if (Key == "Cars") { - ValueStream >> Application::Settings.MaxCars; - } else if (Key == "MaxPlayers") { - ValueStream >> Application::Settings.MaxPlayers; - } else if (Key == "Map") { - Application::Settings.MapName = Value.substr(1, Value.size() - 3); - } else if (Key == "Name") { - Application::Settings.ServerName = Value.substr(1, Value.size() - 3); - } else if (Key == "Desc") { - Application::Settings.ServerDesc = Value.substr(1, Value.size() - 3); - } else if (Key == "use") { - Application::Settings.Resource = Value.substr(1, Value.size() - 3); - } else if (Key == "AuthKey") { - Application::Settings.Key = Value.substr(1, Value.size() - 3); - } else { - beammp_warn("unknown key in old auth file (ignored): " + Key); - } - Str >> std::ws; - } -} std::string TConfig::TagsAsPrettyArray() const { std::vector TagsArray = {}; - SplitString(Application::Settings.ServerTags, ',', TagsArray); + SplitString(Application::Settings.getAsString(Settings::General_Tags), ',', TagsArray); std::string Pretty = {}; for (size_t i = 0; i < TagsArray.size() - 1; ++i) { Pretty += '\"' + TagsArray[i] + "\", "; diff --git a/src/TConsole.cpp b/src/TConsole.cpp index ad7f4d8..679bca3 100644 --- a/src/TConsole.cpp +++ b/src/TConsole.cpp @@ -78,7 +78,7 @@ static std::string GetDate() { auto local_tm = std::localtime(&tt); char buf[30]; std::string date; - if (Application::Settings.DebugModeEnabled) { + if (Application::Settings.getAsBool(Settings::Key::General_Debug)) { std::strftime(buf, sizeof(buf), "[%d/%m/%y %T.", local_tm); date += buf; auto seconds = std::chrono::time_point_cast(now); @@ -402,11 +402,10 @@ void TConsole::Command_Settings(const std::string&, const std::vector - for(const auto& [composedKey, keyACL] : Application::SettingsSingleton.getACLMap()){ + } else if (args.front() == "list") { + // std::unordered_map + for (const auto& [composedKey, keyACL] : Application::Settings.getACLMap()) { // even though we have the value, we want to ignore it in order to make use of access // control checks - - if(keyACL.second != Settings::SettingsAccessMask::noaccess){ - - try{ - - Settings::SettingsAccessControl acl = Application::SettingsSingleton.getConsoleInputAccessMapping(composedKey); - Settings::SettingsTypeVariant keyType = Application::SettingsSingleton.get(acl.first); - std::visit( - overloaded { - [&composedKey](std::string keyValue) { - Application::Console().WriteRaw(fmt::format("{} = {}", composedKey, keyValue)); - }, - [&composedKey](int keyValue) { - Application::Console().WriteRaw(fmt::format("{} = {}", composedKey, keyValue)); - }, - [&composedKey](bool keyValue) { - Application::Console().WriteRaw(fmt::format("{} = {}", composedKey, keyValue)); - } + if (keyACL.second != Settings::SettingsAccessMask::noaccess) { - }, - keyType); - }catch(std::logic_error& e){ - beammp_errorf("Error when getting key: {}", e.what()); - } + try { + + Settings::SettingsAccessControl acl = Application::Settings.getConsoleInputAccessMapping(composedKey); + Settings::SettingsTypeVariant keyType = Application::Settings.get(acl.first); + + std::visit( + overloaded { + [&composedKey](std::string keyValue) { + Application::Console().WriteRaw(fmt::format("{} = {}", composedKey, keyValue)); + }, + [&composedKey](int keyValue) { + Application::Console().WriteRaw(fmt::format("{} = {}", composedKey, keyValue)); + }, + [&composedKey](bool keyValue) { + Application::Console().WriteRaw(fmt::format("{} = {}", composedKey, keyValue)); + } + + }, + keyType); + } catch (std::logic_error& e) { + beammp_errorf("Error when getting key: {}", e.what()); + } } } - }else { + } else { beammp_errorf("Unknown argument for cammand 'settings': {}", args.front()); Application::Console().WriteRaw("BeamMP-Server Console: " + std::string(sHelpString)); @@ -515,7 +514,7 @@ void TConsole::Command_Say(const std::string& FullCmd) { if (FullCmd.size() > 3) { auto Message = FullCmd.substr(4); LuaAPI::MP::SendChatMessage(-1, Message); - if (!Application::Settings.LogChat) { + if (!Application::Settings.getAsBool(Settings::Key::General_LogChat)) { Application::Console().WriteRaw("Chat message sent!"); } } diff --git a/src/THeartbeatThread.cpp b/src/THeartbeatThread.cpp index 77a3348..4148439 100644 --- a/src/THeartbeatThread.cpp +++ b/src/THeartbeatThread.cpp @@ -64,7 +64,7 @@ void THeartbeatThread::operator()() { T = Http::POST(Url, 443, Target, Body, "application/x-www-form-urlencoded", &ResponseCode, { { "api-v", "2" } }); Doc.Parse(T.data(), T.size()); if (Doc.HasParseError() || !Doc.IsObject()) { - if (!Application::Settings.Private) { + if (!Application::Settings.getAsBool(Settings::Key::General_Private)) { beammp_trace("Backend response failed to parse as valid json"); beammp_trace("Response was: `" + T + "`"); } @@ -104,12 +104,12 @@ void THeartbeatThread::operator()() { beammp_error("Missing/invalid json members in backend response"); } } else { - if (!Application::Settings.Private) { + if (!Application::Settings.getAsBool(Settings::Key::General_Private)) { beammp_warn("Backend failed to respond to a heartbeat. Your server may temporarily disappear from the server list. This is not an error, and will likely resolve itself soon. Direct connect will still work."); } } - if (Ok && !isAuth && !Application::Settings.Private) { + if (Ok && !isAuth && !Application::Settings.getAsBool(Settings::Key::General_Private)) { if (Status == "2000") { beammp_info(("Authenticated! " + Message)); isAuth = true; @@ -123,10 +123,10 @@ void THeartbeatThread::operator()() { beammp_error("Backend REFUSED the auth key. Reason: " + Message); } } - if (isAuth || Application::Settings.Private) { + if (isAuth || Application::Settings.getAsBool(Settings::Key::General_Private)) { Application::SetSubsystemStatus("Heartbeat", Application::Status::Good); } - if (!Application::Settings.HideUpdateMessages && UpdateReminderCounter % 5) { + if (!Application::Settings.getAsBool(Settings::Key::Misc_ImScaredOfUpdates) && UpdateReminderCounter % 5) { Application::CheckForUpdates(); } } @@ -135,22 +135,21 @@ void THeartbeatThread::operator()() { std::string THeartbeatThread::GenerateCall() { std::stringstream Ret; - Ret << "uuid=" << Application::Settings.Key + Ret << "uuid=" << Application::Settings.getAsString(Settings::Key::General_AuthKey) << "&players=" << mServer.ClientCount() - << "&maxplayers=" << Application::Settings.MaxPlayers - << "&port=" << Application::Settings.Port - << "&map=" << Application::Settings.MapName - << "&private=" << (Application::Settings.Private ? "true" : "false") + << "&maxplayers=" << Application::Settings.getAsInt(Settings::Key::General_MaxPlayers) + << "&port=" << Application::Settings.getAsInt(Settings::Key::General_Port) + << "&map=" << Application::Settings.getAsString(Settings::Key::General_Map) + << "&private=" << (Application::Settings.getAsBool(Settings::Key::General_Private) ? "true" : "false") << "&version=" << Application::ServerVersionString() << "&clientversion=" << std::to_string(Application::ClientMajorVersion()) + ".0" // FIXME: Wtf. - << "&name=" << Application::Settings.ServerName - << "&tags=" << Application::Settings.ServerTags + << "&name=" << Application::Settings.getAsString(Settings::Key::General_Name) + << "&tags=" << Application::Settings.getAsString(Settings::Key::General_Tags) << "&modlist=" << mResourceManager.TrimmedList() << "&modstotalsize=" << mResourceManager.MaxModSize() << "&modstotal=" << mResourceManager.ModsLoaded() << "&playerslist=" << GetPlayers() - << "&desc=" << Application::Settings.ServerDesc - << "&pass=" << (Application::Settings.Password.empty() ? "false" : "true"); + << "&desc=" << Application::Settings.getAsString(Settings::Key::General_Description); return Ret.str(); } THeartbeatThread::THeartbeatThread(TResourceManager& ResourceManager, TServer& Server) diff --git a/src/TLuaEngine.cpp b/src/TLuaEngine.cpp index 031e5cc..121044b 100644 --- a/src/TLuaEngine.cpp +++ b/src/TLuaEngine.cpp @@ -35,11 +35,11 @@ TLuaEngine* LuaAPI::MP::Engine; TLuaEngine::TLuaEngine() - : mResourceServerPath(fs::path(Application::Settings.Resource) / "Server") { + : mResourceServerPath(fs::path(Application::Settings.getAsString(Settings::Key::General_ResourceFolder)) / "Server") { Application::SetSubsystemStatus("LuaEngine", Application::Status::Starting); LuaAPI::MP::Engine = this; - if (!fs::exists(Application::Settings.Resource)) { - fs::create_directory(Application::Settings.Resource); + if (!fs::exists(Application::Settings.getAsString(Settings::Key::General_ResourceFolder))) { + fs::create_directory(Application::Settings.getAsString(Settings::Key::General_ResourceFolder)); } if (!fs::exists(mResourceServerPath)) { fs::create_directory(mResourceServerPath); @@ -55,7 +55,7 @@ TLuaEngine::TLuaEngine() } TEST_CASE("TLuaEngine ctor & dtor") { - Application::Settings.Resource = "beammp_server_test_resources"; + Application::Settings.set(Settings::Key::General_ResourceFolder, "beammp_server_test_resources"); TLuaEngine engine; Application::GracefullyShutdown(); } @@ -836,7 +836,7 @@ TLuaEngine::StateThreadData::StateThreadData(const std::string& Name, TLuaStateI ToPrint += LuaAPI::LuaToString(static_cast(arg)); ToPrint += "\t"; } - if (Application::Settings.DebugModeEnabled) { + if (Application::Settings.getAsBool(Settings::Key::General_Debug)) { beammp_lua_log("DEBUG", mStateId, ToPrint); } }); diff --git a/src/TNetwork.cpp b/src/TNetwork.cpp index a18b506..114d59c 100644 --- a/src/TNetwork.cpp +++ b/src/TNetwork.cpp @@ -80,7 +80,7 @@ TNetwork::TNetwork(TServer& Server, TPPSMonitor& PPSMonitor, TResourceManager& R void TNetwork::UDPServerMain() { RegisterThread("UDPServer"); - ip::udp::endpoint UdpListenEndpoint(ip::address::from_string("0.0.0.0"), Application::Settings.Port); + ip::udp::endpoint UdpListenEndpoint(ip::address::from_string("0.0.0.0"), Application::Settings.getAsInt(Settings::Key::General_Port)); boost::system::error_code ec; mUDPSock.open(UdpListenEndpoint.protocol(), ec); if (ec) { @@ -95,8 +95,8 @@ void TNetwork::UDPServerMain() { Application::GracefullyShutdown(); } Application::SetSubsystemStatus("UDPNetwork", Application::Status::Good); - beammp_info(("Vehicle data network online on port ") + std::to_string(Application::Settings.Port) + (" with a Max of ") - + std::to_string(Application::Settings.MaxPlayers) + (" Clients")); + beammp_info(("Vehicle data network online on port ") + std::to_string(Application::Settings.getAsInt(Settings::Key::General_Port)) + (" with a Max of ") + + std::to_string(Application::Settings.getAsInt(Settings::Key::General_MaxPlayers)) + (" Clients")); while (!Application::IsShuttingDown()) { try { ip::udp::endpoint client {}; @@ -133,7 +133,7 @@ void TNetwork::UDPServerMain() { void TNetwork::TCPServerMain() { RegisterThread("TCPServer"); - ip::tcp::endpoint ListenEp(ip::address::from_string("0.0.0.0"), Application::Settings.Port); + ip::tcp::endpoint ListenEp(ip::address::from_string("0.0.0.0"), Application::Settings.getAsInt(Settings::Key::General_Port)); ip::tcp::socket Listener(mServer.IoCtx()); boost::system::error_code ec; Listener.open(ListenEp.protocol(), ec); @@ -376,7 +376,7 @@ std::shared_ptr TNetwork::Authentication(TConnection&& RawConnection) { return {}; } - if (mServer.ClientCount() < size_t(Application::Settings.MaxPlayers)) { + if (mServer.ClientCount() < size_t(Application::Settings.getAsInt(Settings::Key::General_MaxPlayers))) { beammp_info("Identification success"); mServer.InsertClient(Client); TCPClient(Client); @@ -569,7 +569,7 @@ void TNetwork::TCPClient(const std::weak_ptr& c) { } void TNetwork::UpdatePlayer(TClient& Client) { - std::string Packet = ("Ss") + std::to_string(mServer.ClientCount()) + "/" + std::to_string(Application::Settings.MaxPlayers) + ":"; + std::string Packet = ("Ss") + std::to_string(mServer.ClientCount()) + "/" + std::to_string(Application::Settings.getAsInt(Settings::Key::General_MaxPlayers)) + ":"; mServer.ForEachClient([&](const std::weak_ptr& ClientPtr) -> bool { ReadLock Lock(mServer.GetClientMutex()); if (!ClientPtr.expired()) { @@ -644,7 +644,7 @@ void TNetwork::OnConnect(const std::weak_ptr& c) { SyncResources(*LockedClient); if (LockedClient->IsDisconnected()) return; - (void)Respond(*LockedClient, StringToVector("M" + Application::Settings.MapName), true); // Send the Map on connect + (void)Respond(*LockedClient, StringToVector("M" + Application::Settings.getAsString(Settings::Key::General_Map)), true); // Send the Map on connect beammp_info(LockedClient->GetName() + " : Connected"); LuaAPI::MP::Engine->ReportErrors(LuaAPI::MP::Engine->TriggerEvent("onPlayerJoining", "", LockedClient->GetID())); } @@ -703,7 +703,7 @@ void TNetwork::SendFile(TClient& c, const std::string& UnsafeName) { return; } auto FileName = fs::path(UnsafeName).filename().string(); - FileName = Application::Settings.Resource + "/Client/" + FileName; + FileName = Application::Settings.getAsString(Settings::Key::General_ResourceFolder) + "/Client/" + FileName; if (!std::filesystem::exists(FileName)) { if (!TCPSend(c, StringToVector("CO"))) { diff --git a/src/TResourceManager.cpp b/src/TResourceManager.cpp index 00fff82..5582af3 100644 --- a/src/TResourceManager.cpp +++ b/src/TResourceManager.cpp @@ -25,7 +25,7 @@ namespace fs = std::filesystem; TResourceManager::TResourceManager() { Application::SetSubsystemStatus("ResourceManager", Application::Status::Starting); - std::string Path = Application::Settings.Resource + "/Client"; + std::string Path = Application::Settings.getAsString(Settings::Key::General_ResourceFolder) + "/Client"; if (!fs::exists(Path)) fs::create_directories(Path); for (const auto& entry : fs::directory_iterator(Path)) { diff --git a/src/TServer.cpp b/src/TServer.cpp index 9b9138d..215ae0a 100644 --- a/src/TServer.cpp +++ b/src/TServer.cpp @@ -286,7 +286,7 @@ bool TServer::ShouldSpawn(TClient& c, const std::string& CarJson, int ID) { c.SetUnicycleID(ID); return true; } else { - return c.GetCarCount() < Application::Settings.MaxCars; + return c.GetCarCount() < Application::Settings.getAsInt(Settings::Key::General_MaxCars); } } diff --git a/src/main.cpp b/src/main.cpp index cb5003d..b93ff77 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -151,7 +151,7 @@ int BeamMPServerMain(MainArguments Arguments) { beammp_errorf("Custom port requested via --port is invalid: '{}'", Port.value()); return 1; } else { - Application::Settings.Port = P; + Application::Settings.set(Settings::Key::General_Port, P); beammp_info("Custom port requested via commandline arguments: " + Port.value()); } } @@ -197,11 +197,7 @@ int BeamMPServerMain(MainArguments Arguments) { PPSMonitor.SetNetwork(Network); Application::CheckForUpdates(); - TPluginMonitor PluginMonitor(fs::path(Application::Settings.Resource) / "Server", LuaEngine); - - if (Application::Settings.HTTPServerEnabled) { - Http::Server::THttpServerInstance HttpServerInstance {}; - } + TPluginMonitor PluginMonitor(fs::path(Application::Settings.getAsString(Settings::Key::General_ResourceFolder)) / "Server", LuaEngine); Application::SetSubsystemStatus("Main", Application::Status::Good); RegisterThread("Main(Waiting)");