diff --git a/librecomp/include/librecomp/mods.hpp b/librecomp/include/librecomp/mods.hpp index d0bda55..d26b0d1 100644 --- a/librecomp/include/librecomp/mods.hpp +++ b/librecomp/include/librecomp/mods.hpp @@ -153,6 +153,14 @@ namespace recomp { WrongVersion = 3 }; + enum class DeprecationStatus { + // Status is unknown. + Unknown, + + // The mod was integrated as part of the project. + Integrated + }; + struct ModFileHandle { virtual ~ModFileHandle() = default; virtual std::vector read_file(const std::string& filepath, bool& exists) const = 0; @@ -321,12 +329,15 @@ namespace recomp { void register_game(const std::string& mod_game_id); void register_embedded_mod(const std::string& mod_id, std::span mod_bytes); + void register_deprecated_mod(const std::string& mod_id, DeprecationStatus deprecation_status); std::vector scan_mod_folder(const std::filesystem::path& mod_folder); void close_mods(); void load_mods_config(); void enable_mod(const std::string& mod_id, bool enabled, bool trigger_save); bool is_mod_enabled(const std::string& mod_id) const; bool is_mod_auto_enabled(const std::string& mod_id) const; + bool is_mod_deprecated(const std::string& mod_id) const; + DeprecationStatus get_mod_deprecation_status(const std::string& mod_id) const; size_t num_opened_mods(); std::vector load_mods(const GameEntry& game_entry, const std::string& game_mode_id, uint8_t* rdram, int32_t load_address, uint32_t& ram_used); void unload_mods(); @@ -393,6 +404,7 @@ namespace recomp { std::unordered_set mod_ids; std::unordered_set enabled_mods; std::unordered_set auto_enabled_mods; + std::unordered_map deprecated_mods; std::unordered_map patched_funcs; std::unordered_map loaded_mods_by_id; std::unique_ptr mod_configuration_thread; @@ -597,7 +609,8 @@ namespace recomp { CodeModLoadError validate_api_version(uint32_t api_version, std::string& error_param); void initialize_mods(); - void register_embedded_mod(const std::string &mod_id, std::span mod_bytes); + void register_embedded_mod(const std::string& mod_id, std::span mod_bytes); + void register_deprecated_mod(const std::string &mod_id, recomp::mods::DeprecationStatus deprecation_status); void scan_mods(); void close_mods(); std::filesystem::path get_mods_directory(); @@ -609,6 +622,9 @@ namespace recomp { void enable_mod(const std::string& mod_id, bool enabled); bool is_mod_enabled(const std::string& mod_id); bool is_mod_auto_enabled(const std::string& mod_id); + bool is_mod_deprecated(const std::string& mod_id); + DeprecationStatus get_mod_deprecation_status(const std::string& mod_id); + std::string deprecation_status_to_message(DeprecationStatus deprecation_status); const config::ConfigSchema &get_mod_config_schema(const std::string &mod_id); config::Config *get_mod_config(const std::string &mod_id); const std::vector &get_mod_thumbnail(const std::string &mod_id); diff --git a/librecomp/src/mods.cpp b/librecomp/src/mods.cpp index 2883661..9310160 100644 --- a/librecomp/src/mods.cpp +++ b/librecomp/src/mods.cpp @@ -636,6 +636,10 @@ void recomp::mods::ModContext::register_embedded_mod(const std::string &mod_id, embedded_mod_bytes.emplace(mod_id, mod_bytes); } +void recomp::mods::ModContext::register_deprecated_mod(const std::string& mod_id, DeprecationStatus deprecation_status) { + deprecated_mods[mod_id] = deprecation_status; +} + void recomp::mods::ModContext::close_mods() { std::unique_lock lock(opened_mods_mutex); opened_mods_by_id.clear(); @@ -1037,6 +1041,11 @@ void recomp::mods::ModContext::enable_mod(const std::string& mod_id, bool enable return; } + // Do nothing if this mod was deprecated. + if (is_mod_deprecated(mod_id)) { + return; + } + if (enabled) { bool was_enabled = enabled_mods.emplace(mod_id).second; @@ -1061,7 +1070,7 @@ void recomp::mods::ModContext::enable_mod(const std::string& mod_id, bool enable if (mod_from_stack_it != opened_mods_by_id.end()) { const ModHandle &mod_from_stack_handle = opened_mods[mod_from_stack_it->second]; for (const Dependency &dependency : mod_from_stack_handle.manifest.dependencies) { - if (!dependency.optional && !auto_enabled_mods.contains(dependency.mod_id)) { + if (!dependency.optional && !auto_enabled_mods.contains(dependency.mod_id) && !is_mod_deprecated(dependency.mod_id)) { auto_enabled_mods.emplace(dependency.mod_id); mod_stack.emplace_back(dependency.mod_id); @@ -1106,7 +1115,7 @@ void recomp::mods::ModContext::enable_mod(const std::string& mod_id, bool enable if (mod_from_stack_it != opened_mods_by_id.end()) { const ModHandle &mod_from_stack_handle = opened_mods[mod_from_stack_it->second]; for (const Dependency &dependency : mod_from_stack_handle.manifest.dependencies) { - if (!dependency.optional && !new_auto_enabled_mods.contains(dependency.mod_id)) { + if (!dependency.optional && !new_auto_enabled_mods.contains(dependency.mod_id) && !is_mod_deprecated(dependency.mod_id)) { new_auto_enabled_mods.emplace(dependency.mod_id); mod_stack.emplace_back(dependency.mod_id); } @@ -1150,6 +1159,20 @@ bool recomp::mods::ModContext::is_mod_auto_enabled(const std::string& mod_id) co return auto_enabled_mods.contains(mod_id); } +bool recomp::mods::ModContext::is_mod_deprecated(const std::string& mod_id) const { + return get_mod_deprecation_status(mod_id) != DeprecationStatus::Unknown; +} + +recomp::mods::DeprecationStatus recomp::mods::ModContext::get_mod_deprecation_status(const std::string& mod_id) const { + auto it = deprecated_mods.find(mod_id); + if (it != deprecated_mods.end()) { + return it->second; + } + else { + return recomp::mods::DeprecationStatus::Unknown; + } +} + size_t recomp::mods::ModContext::num_opened_mods() { return opened_mods.size(); } diff --git a/librecomp/src/recomp.cpp b/librecomp/src/recomp.cpp index 52456d2..e42ce19 100644 --- a/librecomp/src/recomp.cpp +++ b/librecomp/src/recomp.cpp @@ -102,6 +102,11 @@ void recomp::mods::register_embedded_mod(const std::string &mod_id, std::spanregister_embedded_mod(mod_id, mod_bytes); } +void recomp::mods::register_deprecated_mod(const std::string& mod_id, recomp::mods::DeprecationStatus deprecation_status) { + std::lock_guard lock(mod_context_mutex); + mod_context->register_deprecated_mod(mod_id, deprecation_status); +} + void recomp::mods::scan_mods() { std::vector mod_open_errors; { @@ -570,6 +575,25 @@ bool recomp::mods::is_mod_auto_enabled(const std::string& mod_id) { return mod_context->is_mod_auto_enabled(mod_id); } +bool recomp::mods::is_mod_deprecated(const std::string& mod_id) { + std::lock_guard lock{ mod_context_mutex }; + return mod_context->is_mod_deprecated(mod_id); +} + +recomp::mods::DeprecationStatus recomp::mods::get_mod_deprecation_status(const std::string& mod_id) { + std::lock_guard lock{ mod_context_mutex }; + return mod_context->get_mod_deprecation_status(mod_id); +} + +std::string recomp::mods::deprecation_status_to_message(DeprecationStatus deprecation_status) { + switch (deprecation_status) { + case DeprecationStatus::Integrated: + return "This mod has already been integrated into the game"; + default: + return "Reason is unknown"; + } +} + const recomp::config::ConfigSchema &recomp::mods::get_mod_config_schema(const std::string &mod_id) { std::lock_guard lock{ mod_context_mutex }; return mod_context->get_mod_config_schema(mod_id);