#include #include "loader/component_loader.hpp" #include "config.hpp" #include "console.hpp" #include "language.hpp" #include #include #include #define OLD_CONFIG_FILE "players2/default/h2_mod.json" namespace config { namespace { using validate_type_callback_t = std::function; using validate_callback_t = std::function; struct field_definition_t { field_type type; field_value default_value; std::optional validate_value = {}; }; template std::pair define_field(const std::string& name, Args&&... args) { return std::make_pair(name, field_definition_t{std::forward(args)...}); } std::unordered_map field_definitions = { {define_field("language", field_type::string, language::get_default_language(), language::is_valid_language)}, }; std::string get_config_file_path() { return (utils::properties::get_appdata_path() / "config.json").generic_string(); } } nlohmann::json validate_config_field(const std::string& key, const nlohmann::json& value) { const auto iter = field_definitions.find(key); if (iter == field_definitions.end()) { return value; } if (value.type() != iter->second.type) { return iter->second.default_value; } if (iter->second.validate_value.has_value()) { const auto& validate_value = iter->second.validate_value.value(); if (!validate_value(value)) { iter->second.default_value; } } return value; } nlohmann::json get_default_value(const std::string& key) { const auto iter = field_definitions.find(key); if (iter == field_definitions.end()) { return {}; } return iter->second.default_value; } nlohmann::json get_raw(const std::string& key) { const auto cfg = read_config(); if (!cfg.is_object() || !cfg.contains(key)) { return get_default_value(key); } return validate_config_field(key, cfg[key]); } void write_config(const nlohmann::json& json) { try { const auto path = get_config_file_path(); const auto str = json.dump(4); utils::io::write_file(path, str, false); } catch (const std::exception& e) { console::error("Failed to write config file: %s\n", e.what()); } } nlohmann::json read_config() { const auto path = get_config_file_path(); if (!utils::io::file_exists(path)) { return {}; } try { const auto data = utils::io::read_file(path); return nlohmann::json::parse(data); } catch (const std::exception& e) { console::error("Failed to parse config file: %s\n", e.what()); utils::io::write_file(path, "{}", false); } return {}; } class component final : public component_interface { public: void post_unpack() override { if (utils::io::file_exists(OLD_CONFIG_FILE)) { const auto data = utils::io::read_file(OLD_CONFIG_FILE); utils::io::write_file(get_config_file_path(), data); utils::io::remove_file(OLD_CONFIG_FILE); } } }; } REGISTER_COMPONENT(config::component)