From 3989961ff97f941c730b0d804dfc1f894bce55b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucca=20Jim=C3=A9nez=20K=C3=B6nings?= Date: Mon, 26 Feb 2024 03:16:57 +0100 Subject: [PATCH] Add `get` and `set` to console command `settings` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lucca Jiménez Könings --- include/TSettings.h | 64 +++++++++++++++++++++++++++ src/TConfig.cpp | 2 +- src/TConsole.cpp | 103 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 167 insertions(+), 2 deletions(-) diff --git a/include/TSettings.h b/include/TSettings.h index 305ca76..81857fe 100644 --- a/include/TSettings.h +++ b/include/TSettings.h @@ -171,6 +171,70 @@ struct Settings { } SettingsMap.at(key) = value; } + + const std::unordered_map& getACLMap() const { + return InputAccessMapping; + } + SettingsAccessControl getConsoleInputAccessMapping(const std::string& keyName) { + if (!InputAccessMapping.contains(keyName)) { + throw std::logic_error { "Unknown key name accessed in Settings::getConsoleInputAccessMapping" }; + } else if (InputAccessMapping.at(keyName).second == SettingsAccessMask::noaccess) { + throw std::logic_error { "Key " + keyName + " is not accessible from within the runtime!" }; + } + return InputAccessMapping.at(keyName); + } + + void setConsoleInputAccessMapping(const std::string& keyName, std::string value) { + if (!InputAccessMapping.contains(keyName)) { + throw std::logic_error { "Unknown key name accessed in Settings::setConsoleInputAccessMapping" }; + } else if (InputAccessMapping.at(keyName).second == SettingsAccessMask::noaccess) { + throw std::logic_error { "Key " + keyName + " is not accessible from within the runtime!" }; + } else if (InputAccessMapping.at(keyName).second == SettingsAccessMask::read) { + throw std::logic_error { "Key " + keyName + " is not writeable from within the runtime!" }; + } + + Key key = InputAccessMapping.at(keyName).first; + + if (!std::holds_alternative(SettingsMap.at(key))) { + throw std::logic_error { "Wrong value type in Settings::setConsoleInputAccessMapping: expected std::string" }; + } + + SettingsMap.at(key) = value; + } + void setConsoleInputAccessMapping(const std::string& keyName, int value) { + if (!InputAccessMapping.contains(keyName)) { + throw std::logic_error { "Unknown key name accessed in Settings::setConsoleInputAccessMapping" }; + } else if (InputAccessMapping.at(keyName).second == SettingsAccessMask::noaccess) { + throw std::logic_error { "Key " + keyName + " is not accessible from within the runtime!" }; + } else if (InputAccessMapping.at(keyName).second == SettingsAccessMask::read) { + throw std::logic_error { "Key " + keyName + " is not writeable from within the runtime!" }; + } + + Key key = InputAccessMapping.at(keyName).first; + + if (!std::holds_alternative(SettingsMap.at(key))) { + throw std::logic_error { "Wrong value type in Settings::setConsoleInputAccessMapping: expected int" }; + } + + SettingsMap.at(key) = value; + } + void setConsoleInputAccessMapping(const std::string& keyName, bool value) { + if (!InputAccessMapping.contains(keyName)) { + throw std::logic_error { "Unknown key name accessed in Settings::setConsoleInputAccessMapping" }; + } else if (InputAccessMapping.at(keyName).second == SettingsAccessMask::noaccess) { + throw std::logic_error { "Key " + keyName + " is not accessible from within the runtime!" }; + } else if (InputAccessMapping.at(keyName).second == SettingsAccessMask::read) { + throw std::logic_error { "Key " + keyName + " is not writeable from within the runtime!" }; + } + + Key key = InputAccessMapping.at(keyName).first; + + if (!std::holds_alternative(SettingsMap.at(key))) { + throw std::logic_error { "Wrong value type in Settings::setConsoleInputAccessMapping: expected bool" }; + } + + SettingsMap.at(key) = value; + } }; /*struct TSettings { diff --git a/src/TConfig.cpp b/src/TConfig.cpp index 3bad985..923b770 100644 --- a/src/TConfig.cpp +++ b/src/TConfig.cpp @@ -238,7 +238,7 @@ template 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) { - + beammp_infof("SettingsSingletonMap Size: {}", Application::SettingsSingleton.SettingsMap.size()); if (!Env.empty()) { if (const char* envp = std::getenv(Env.data()); envp != nullptr && std::strcmp(envp, "") != 0) { diff --git a/src/TConsole.cpp b/src/TConsole.cpp index 9c6561e..ff50760 100644 --- a/src/TConsole.cpp +++ b/src/TConsole.cpp @@ -28,6 +28,7 @@ #include #include #include +#include static inline bool StringStartsWith(const std::string& What, const std::string& StartsWith) { return What.size() >= StartsWith.size() && What.substr(0, StartsWith.size()) == StartsWith; @@ -366,8 +367,108 @@ std::tuple> TConsole::ParseCommand(const s return { Command, Args }; } +template +struct overloaded : Ts... { + using Ts::operator()...; +}; +template +overloaded(Ts...) -> overloaded; + void TConsole::Command_Settings(const std::string&, const std::vector& args) { - if (!EnsureArgsCount(args, 1, 2)) { + + for (const std::string& arg : args) + beammp_infof("Argument: {}", arg); + + static constexpr const char* sHelpString = R"( + Settings: + settings help displays this help + settings list lists all settings + settings get prints current value of specified setting + settings set sets specified setting to value + )"; + + if (args.size() == 0) { + beammp_errorf("No arguments specified for command 'settings'!"); + Application::Console().WriteRaw("BeamMP-Server Console: " + std::string(sHelpString)); + return; + } + + if (args.front() == "help") { + + Application::Console().WriteRaw("BeamMP-Server Console: " + std::string(sHelpString)); + return; + } else if (args.front() == "get") { + if (args.size() == 1) { + beammp_errorf("'settings get' needs at least one argument!"); + + Application::Console().WriteRaw("BeamMP-Server Console: " + std::string(sHelpString)); + return; + } + + try { + Settings::SettingsAccessControl acl = Application::SettingsSingleton.getConsoleInputAccessMapping(args.at(1)); + Settings::SettingsTypeVariant keyType = Application::SettingsSingleton.get(acl.first); + + std::visit( + overloaded { + [&args](std::string keyValue) { + Application::Console().WriteRaw(fmt::format("{} = {}", args.at(1), keyValue)); + }, + [&args](int keyValue) { + Application::Console().WriteRaw(fmt::format("{} = {}", args.at(1), keyValue)); + }, + [&args](bool keyValue) { + Application::Console().WriteRaw(fmt::format("{} = {}", args.at(1), keyValue)); + } + + }, + keyType); + + } catch (std::logic_error& e) { + beammp_errorf("Error when getting key: {}", e.what()); + return; + } + } else if (args.front() == "set") { + if (args.size() == 1) { + beammp_errorf("'settings set' needs at least two arguments!"); + + Application::Console().WriteRaw("BeamMP-Server Console: " + std::string(sHelpString)); + return; + } + + try { + + Settings::SettingsAccessControl acl = Application::SettingsSingleton.getConsoleInputAccessMapping(args.at(1)); + Settings::SettingsTypeVariant keyType = Application::SettingsSingleton.get(acl.first); + + std::visit( + overloaded { + [&args](std::string keyValue) { + Application::SettingsSingleton.setConsoleInputAccessMapping(args.at(1), std::string(args.at(2))); + Application::Console().WriteRaw(fmt::format("{} := {}", args.at(1), std::string(args.at(2)))); + }, + [&args](int keyValue) { + Application::SettingsSingleton.setConsoleInputAccessMapping(args.at(1), std::stoi(args.at(2))); + Application::Console().WriteRaw(fmt::format("{} := {}", args.at(1), std::stoi(args.at(2)))); + }, + [&args](bool keyValue) { + // todo: implement other way to convert from string to bool + Application::SettingsSingleton.setConsoleInputAccessMapping(args.at(1), std::stoi(args.at(2))); + Application::Console().WriteRaw(fmt::format("{} := {}", args.at(1), std::stoi(args.at(2)))); + } + + }, + keyType); + + } catch (std::logic_error& e) { + beammp_errorf("Error when setting key: {}", e.what()); + return; + } + + } else { + beammp_errorf("Unknown argument for cammand 'settings': {}", args.front()); + + Application::Console().WriteRaw("BeamMP-Server Console: " + std::string(sHelpString)); return; } }