mirror of
https://github.com/N64Recomp/N64ModernRuntime.git
synced 2025-10-30 08:02:29 +00:00
Auto-enabled mods.
This commit is contained in:
parent
5bde72d8ac
commit
e814ad6f83
3 changed files with 80 additions and 4 deletions
|
|
@ -326,6 +326,7 @@ namespace recomp {
|
|||
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);
|
||||
bool is_mod_auto_enabled(const std::string& mod_id);
|
||||
size_t num_opened_mods();
|
||||
std::vector<ModLoadErrorDetails> load_mods(const GameEntry& game_entry, uint8_t* rdram, int32_t load_address, uint32_t& ram_used);
|
||||
void unload_mods();
|
||||
|
|
@ -369,6 +370,7 @@ namespace recomp {
|
|||
std::mutex opened_mods_mutex;
|
||||
std::unordered_set<std::string> mod_ids;
|
||||
std::unordered_set<std::string> enabled_mods;
|
||||
std::unordered_set<std::string> auto_enabled_mods;
|
||||
std::unordered_map<recomp_func_t*, PatchData> patched_funcs;
|
||||
std::unordered_map<std::string, size_t> loaded_mods_by_id;
|
||||
std::unique_ptr<std::thread> mod_configuration_thread;
|
||||
|
|
|
|||
|
|
@ -272,8 +272,8 @@ recomp::mods::ModHandle::ModHandle(const ModContext& context, ModManifest&& mani
|
|||
code_handle(),
|
||||
recompiler_context{std::make_unique<N64Recomp::Context>()},
|
||||
content_types{std::move(content_types)},
|
||||
game_indices{std::move(game_indices)},
|
||||
thumbnail{std::move(thumbnail)}
|
||||
thumbnail{ std::move(thumbnail) },
|
||||
game_indices{std::move(game_indices)}
|
||||
{
|
||||
runtime_toggleable = true;
|
||||
for (ModContentTypeId type : this->content_types) {
|
||||
|
|
@ -630,6 +630,7 @@ void recomp::mods::ModContext::close_mods() {
|
|||
opened_mods_order.clear();
|
||||
mod_ids.clear();
|
||||
enabled_mods.clear();
|
||||
auto_enabled_mods.clear();
|
||||
}
|
||||
|
||||
bool save_mod_config_storage(const std::filesystem::path &path, const std::string &mod_id, const recomp::Version &mod_version, const recomp::mods::ConfigStorage &config_storage, const recomp::mods::ConfigSchema &config_schema) {
|
||||
|
|
@ -959,21 +960,90 @@ void recomp::mods::ModContext::enable_mod(const std::string& mod_id, bool enable
|
|||
|
||||
if (enabled) {
|
||||
bool was_enabled = enabled_mods.emplace(mod_id).second;
|
||||
|
||||
// If mods have been loaded and a mod was successfully enabled by this call, call the on_enabled handlers for its content types.
|
||||
if (was_enabled && mods_loaded) {
|
||||
for (ModContentTypeId type_id : mod.content_types) {
|
||||
content_types[type_id.value].on_enabled(*this, mod);
|
||||
}
|
||||
}
|
||||
|
||||
if (was_enabled) {
|
||||
std::vector<std::string> mod_stack;
|
||||
mod_stack.emplace_back(mod_id);
|
||||
while (!mod_stack.empty()) {
|
||||
std::string mod_from_stack = std::move(mod_stack.back());
|
||||
mod_stack.pop_back();
|
||||
|
||||
auto mod_from_stack_it = opened_mods_by_id.find(mod_from_stack);
|
||||
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 (!auto_enabled_mods.contains(dependency.mod_id)) {
|
||||
auto_enabled_mods.emplace(dependency.mod_id);
|
||||
mod_stack.emplace_back(dependency.mod_id);
|
||||
|
||||
if (mods_loaded) {
|
||||
for (ModContentTypeId type_id : mod_from_stack_handle.content_types) {
|
||||
content_types[type_id.value].on_enabled(*this, mod_from_stack_handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
bool was_disabled = enabled_mods.erase(mod_id) != 0;
|
||||
|
||||
// If mods have been loaded and a mod was successfully disabled by this call, call the on_disabled handlers for its content types.
|
||||
if (was_disabled && mods_loaded) {
|
||||
for (ModContentTypeId type_id : mod.content_types) {
|
||||
content_types[type_id.value].on_disabled(*this, mod);
|
||||
}
|
||||
}
|
||||
|
||||
if (was_disabled) {
|
||||
// The algorithm needs to be run again with a new set of auto-enabled mods from scratch for all enabled mods.
|
||||
std::unordered_set<std::string> new_auto_enabled_mods;
|
||||
for (const std::string &enabled_mod_id : enabled_mods) {
|
||||
std::vector<std::string> mod_stack;
|
||||
mod_stack.emplace_back(enabled_mod_id);
|
||||
while (!mod_stack.empty()) {
|
||||
std::string mod_from_stack = std::move(mod_stack.back());
|
||||
mod_stack.pop_back();
|
||||
|
||||
auto mod_from_stack_it = opened_mods_by_id.find(mod_from_stack);
|
||||
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 (!new_auto_enabled_mods.contains(dependency.mod_id)) {
|
||||
new_auto_enabled_mods.emplace(dependency.mod_id);
|
||||
mod_stack.emplace_back(dependency.mod_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mods_loaded) {
|
||||
// Before replacing the old set with the new one, whatever does not exist in the new set anymore should trigger it's on_disabled callback.
|
||||
for (const std::string &enabled_mod_id : auto_enabled_mods) {
|
||||
if (!new_auto_enabled_mods.contains(enabled_mod_id)) {
|
||||
auto enabled_mod_it = opened_mods_by_id.find(enabled_mod_id);
|
||||
if (enabled_mod_it != opened_mods_by_id.end()) {
|
||||
const ModHandle &enabled_mod_handle = opened_mods[enabled_mod_it->second];
|
||||
for (ModContentTypeId type_id : enabled_mod_handle.content_types) {
|
||||
content_types[type_id.value].on_disabled(*this, enabled_mod_handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto_enabled_mods = new_auto_enabled_mods;
|
||||
}
|
||||
}
|
||||
|
||||
if (trigger_save) {
|
||||
|
|
@ -985,6 +1055,10 @@ bool recomp::mods::ModContext::is_mod_enabled(const std::string& mod_id) {
|
|||
return enabled_mods.contains(mod_id);
|
||||
}
|
||||
|
||||
bool recomp::mods::ModContext::is_mod_auto_enabled(const std::string& mod_id) {
|
||||
return auto_enabled_mods.contains(mod_id);
|
||||
}
|
||||
|
||||
size_t recomp::mods::ModContext::num_opened_mods() {
|
||||
return opened_mods.size();
|
||||
}
|
||||
|
|
@ -1338,7 +1412,7 @@ std::vector<recomp::mods::ModLoadErrorDetails> recomp::mods::ModContext::load_mo
|
|||
// Find and load active mods.
|
||||
for (size_t mod_index = 0; mod_index < opened_mods.size(); mod_index++) {
|
||||
auto& mod = opened_mods[mod_index];
|
||||
if (mod.is_for_game(mod_game_index) && enabled_mods.contains(mod.manifest.mod_id)) {
|
||||
if (mod.is_for_game(mod_game_index) && (enabled_mods.contains(mod.manifest.mod_id) || auto_enabled_mods.contains(mod.manifest.mod_id))) {
|
||||
active_mods.push_back(mod_index);
|
||||
loaded_mods_by_id.emplace(mod.manifest.mod_id, mod_index);
|
||||
|
||||
|
|
|
|||
|
|
@ -517,7 +517,7 @@ bool recomp::mods::is_mod_enabled(const std::string& mod_id) {
|
|||
|
||||
bool recomp::mods::is_mod_auto_enabled(const std::string& mod_id) {
|
||||
std::lock_guard lock{ mod_context_mutex };
|
||||
return false; // TODO
|
||||
return mod_context->is_mod_auto_enabled(mod_id);
|
||||
}
|
||||
|
||||
const recomp::mods::ConfigSchema &recomp::mods::get_mod_config_schema(const std::string &mod_id) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue