mirror of
				https://github.com/N64Recomp/N64ModernRuntime.git
				synced 2025-10-30 08:02:29 +00:00 
			
		
		
		
	Add callback for mod reordering and functions to get mod file path and order index (#99)
	
		
			
	
		
	
	
		
	
		
			Some checks failed
		
		
	
	
		
			
				
	
				validate / windows (x64, Release) (push) Has been cancelled
				
			
		
			
				
	
				validate / ubuntu (arm64, Debug) (push) Has been cancelled
				
			
		
			
				
	
				validate / ubuntu (arm64, Release) (push) Has been cancelled
				
			
		
			
				
	
				validate / ubuntu (x64, Debug) (push) Has been cancelled
				
			
		
			
				
	
				validate / ubuntu (x64, Release) (push) Has been cancelled
				
			
		
			
				
	
				validate / windows (x64, Debug) (push) Has been cancelled
				
			
		
			
				
	
				validate / macos (arm64, Debug) (push) Has been cancelled
				
			
		
			
				
	
				validate / macos (arm64, Release) (push) Has been cancelled
				
			
		
			
				
	
				validate / macos (x64, Debug) (push) Has been cancelled
				
			
		
			
				
	
				validate / macos (x64, Release) (push) Has been cancelled
				
			
		
		
	
	
				
					
				
			
		
			Some checks failed
		
		
	
	validate / windows (x64, Release) (push) Has been cancelled
				
			validate / ubuntu (arm64, Debug) (push) Has been cancelled
				
			validate / ubuntu (arm64, Release) (push) Has been cancelled
				
			validate / ubuntu (x64, Debug) (push) Has been cancelled
				
			validate / ubuntu (x64, Release) (push) Has been cancelled
				
			validate / windows (x64, Debug) (push) Has been cancelled
				
			validate / macos (arm64, Debug) (push) Has been cancelled
				
			validate / macos (arm64, Release) (push) Has been cancelled
				
			validate / macos (x64, Debug) (push) Has been cancelled
				
			validate / macos (x64, Release) (push) Has been cancelled
				
			This commit is contained in:
		
							parent
							
								
									8506c1b588
								
							
						
					
					
						commit
						af075623dc
					
				
					 3 changed files with 77 additions and 9 deletions
				
			
		|  | @ -260,9 +260,6 @@ namespace recomp { | ||||||
|                 mod_id(mod_id_), error(error_), error_param(error_param_) {} |                 mod_id(mod_id_), error(error_), error_param(error_param_) {} | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         std::string get_mod_id_from_filename(const std::filesystem::path& mod_filename); |  | ||||||
|         std::optional<ModDetails> get_details_for_mod(const std::string& mod_id); |  | ||||||
|         std::vector<ModDetails> get_all_mod_details(const std::string& mod_game_id); |  | ||||||
|         void set_mod_index(const std::string &mod_game_id, const std::string &mod_id, size_t index); |         void set_mod_index(const std::string &mod_game_id, const std::string &mod_id, size_t index); | ||||||
| 
 | 
 | ||||||
|         // Internal functions, TODO move to an internal header.
 |         // Internal functions, TODO move to an internal header.
 | ||||||
|  | @ -277,6 +274,7 @@ namespace recomp { | ||||||
|         class ModHandle; |         class ModHandle; | ||||||
|         using content_enabled_callback = void(ModContext&, const ModHandle&); |         using content_enabled_callback = void(ModContext&, const ModHandle&); | ||||||
|         using content_disabled_callback = void(ModContext&, const ModHandle&); |         using content_disabled_callback = void(ModContext&, const ModHandle&); | ||||||
|  |         using content_reordered_callback = void(ModContext&); | ||||||
| 
 | 
 | ||||||
|         struct ModContentType { |         struct ModContentType { | ||||||
|             // The file that's used to indicate that a mod contains this content type.
 |             // The file that's used to indicate that a mod contains this content type.
 | ||||||
|  | @ -288,6 +286,11 @@ namespace recomp { | ||||||
|             content_enabled_callback* on_enabled; |             content_enabled_callback* on_enabled; | ||||||
|             // Function to call when an instance of this content type is disabled.
 |             // Function to call when an instance of this content type is disabled.
 | ||||||
|             content_disabled_callback* on_disabled; |             content_disabled_callback* on_disabled; | ||||||
|  |             // Function to call when an instance of this content type has been reordered.
 | ||||||
|  |             // No mod handle is provided as multiple instances may have been reordered at the same time.
 | ||||||
|  |             // Will not be called if an instance of this content type was incidentally reordered due
 | ||||||
|  |             // to the reordering of another mod, as the ordering of just instances of this content type will not have changed.
 | ||||||
|  |             content_reordered_callback* on_reordered; | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         // Holds IDs for mod content types, which get assigned as they're registered.
 |         // Holds IDs for mod content types, which get assigned as they're registered.
 | ||||||
|  | @ -336,6 +339,8 @@ namespace recomp { | ||||||
|             std::vector<ModLoadErrorDetails> load_mods(const GameEntry& game_entry, uint8_t* rdram, int32_t load_address, uint32_t& ram_used); |             std::vector<ModLoadErrorDetails> load_mods(const GameEntry& game_entry, uint8_t* rdram, int32_t load_address, uint32_t& ram_used); | ||||||
|             void unload_mods(); |             void unload_mods(); | ||||||
|             std::string get_mod_id_from_filename(const std::filesystem::path& mod_filename) const; |             std::string get_mod_id_from_filename(const std::filesystem::path& mod_filename) const; | ||||||
|  |             std::filesystem::path get_mod_filename(const std::string& mod_id) const; | ||||||
|  |             size_t get_mod_order_index(const std::string& mod_id) const; | ||||||
|             std::optional<ModDetails> get_details_for_mod(const std::string& mod_id) const; |             std::optional<ModDetails> get_details_for_mod(const std::string& mod_id) const; | ||||||
|             std::vector<ModDetails> get_all_mod_details(const std::string& mod_game_id); |             std::vector<ModDetails> get_all_mod_details(const std::string& mod_game_id); | ||||||
|             void set_mod_index(const std::string &mod_game_id, const std::string &mod_id, size_t index); |             void set_mod_index(const std::string &mod_game_id, const std::string &mod_id, size_t index); | ||||||
|  | @ -579,6 +584,8 @@ namespace recomp { | ||||||
|         void scan_mods(); |         void scan_mods(); | ||||||
|         void close_mods(); |         void close_mods(); | ||||||
|         std::filesystem::path get_mods_directory(); |         std::filesystem::path get_mods_directory(); | ||||||
|  |         std::optional<ModDetails> get_details_for_mod(const std::string& mod_id); | ||||||
|  |         std::vector<ModDetails> get_all_mod_details(const std::string& mod_game_id); | ||||||
|         void enable_mod(const std::string& mod_id, bool enabled); |         void enable_mod(const std::string& mod_id, bool enabled); | ||||||
|         bool is_mod_enabled(const std::string& mod_id); |         bool is_mod_enabled(const std::string& mod_id); | ||||||
|         bool is_mod_auto_enabled(const std::string& mod_id); |         bool is_mod_auto_enabled(const std::string& mod_id); | ||||||
|  | @ -588,6 +595,9 @@ namespace recomp { | ||||||
|         void set_mod_config_value(const std::string &mod_id, const std::string &option_id, const ConfigValueVariant &value); |         void set_mod_config_value(const std::string &mod_id, const std::string &option_id, const ConfigValueVariant &value); | ||||||
|         ConfigValueVariant get_mod_config_value(size_t mod_index, const std::string &option_id); |         ConfigValueVariant get_mod_config_value(size_t mod_index, const std::string &option_id); | ||||||
|         ConfigValueVariant get_mod_config_value(const std::string &mod_id, const std::string &option_id); |         ConfigValueVariant get_mod_config_value(const std::string &mod_id, const std::string &option_id); | ||||||
|  |         std::string get_mod_id_from_filename(const std::filesystem::path& mod_filename); | ||||||
|  |         std::filesystem::path get_mod_filename(const std::string& mod_id); | ||||||
|  |         size_t get_mod_order_index(const std::string& mod_id); | ||||||
|         ModContentTypeId register_mod_content_type(const ModContentType& type); |         ModContentTypeId register_mod_content_type(const ModContentType& type); | ||||||
|         bool register_mod_container_type(const std::string& extension, const std::vector<ModContentTypeId>& content_types, bool requires_manifest); |         bool register_mod_container_type(const std::string& extension, const std::vector<ModContentTypeId>& content_types, bool requires_manifest); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -614,7 +614,10 @@ recomp::mods::ModLoadError recomp::mods::ModContext::load_mod(recomp::mods::ModH | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     for (ModContentTypeId type_id : mod.content_types) { |     for (ModContentTypeId type_id : mod.content_types) { | ||||||
|         content_types[type_id.value].on_enabled(*this, mod); |         content_enabled_callback* callback = content_types[type_id.value].on_enabled; | ||||||
|  |         if (callback) { | ||||||
|  |             callback(*this, mod); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     return ModLoadError::Good; |     return ModLoadError::Good; | ||||||
|  | @ -872,7 +875,8 @@ recomp::mods::ModContext::ModContext() { | ||||||
|         .content_filename = std::string{modpaths::binary_syms_path}, |         .content_filename = std::string{modpaths::binary_syms_path}, | ||||||
|         .allow_runtime_toggle = false, |         .allow_runtime_toggle = false, | ||||||
|         .on_enabled = ModContext::on_code_mod_enabled, |         .on_enabled = ModContext::on_code_mod_enabled, | ||||||
|         .on_disabled = nullptr |         .on_disabled = nullptr, | ||||||
|  |         .on_reordered = nullptr | ||||||
|     }; |     }; | ||||||
|     code_content_type_id = register_content_type(code_content_type); |     code_content_type_id = register_content_type(code_content_type); | ||||||
|      |      | ||||||
|  | @ -969,7 +973,10 @@ void recomp::mods::ModContext::enable_mod(const std::string& mod_id, bool enable | ||||||
|         // If mods have been loaded and a mod was successfully enabled by this call, call the on_enabled handlers for its content types.
 |         // 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) { |         if (was_enabled && mods_loaded) { | ||||||
|             for (ModContentTypeId type_id : mod.content_types) { |             for (ModContentTypeId type_id : mod.content_types) { | ||||||
|                 content_types[type_id.value].on_enabled(*this, mod); |                 content_enabled_callback* callback = content_types[type_id.value].on_enabled; | ||||||
|  |                 if (callback) { | ||||||
|  |                     callback(*this, mod); | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -990,7 +997,10 @@ void recomp::mods::ModContext::enable_mod(const std::string& mod_id, bool enable | ||||||
| 
 | 
 | ||||||
|                             if (mods_loaded) { |                             if (mods_loaded) { | ||||||
|                                 for (ModContentTypeId type_id : mod_from_stack_handle.content_types) { |                                 for (ModContentTypeId type_id : mod_from_stack_handle.content_types) { | ||||||
|                                     content_types[type_id.value].on_enabled(*this, mod_from_stack_handle); |                                     content_enabled_callback* callback = content_types[type_id.value].on_enabled; | ||||||
|  |                                     if (callback) { | ||||||
|  |                                         callback(*this, mod_from_stack_handle); | ||||||
|  |                                     } | ||||||
|                                 } |                                 } | ||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
|  | @ -1005,7 +1015,10 @@ void recomp::mods::ModContext::enable_mod(const std::string& mod_id, bool enable | ||||||
|         // If mods have been loaded and a mod was successfully disabled by this call, call the on_disabled handlers for its content types.
 |         // 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) { |         if (was_disabled && mods_loaded) { | ||||||
|             for (ModContentTypeId type_id : mod.content_types) { |             for (ModContentTypeId type_id : mod.content_types) { | ||||||
|                 content_types[type_id.value].on_disabled(*this, mod); |                 content_disabled_callback* callback = content_types[type_id.value].on_disabled; | ||||||
|  |                 if (callback) { | ||||||
|  |                     callback(*this, mod); | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -1040,7 +1053,10 @@ void recomp::mods::ModContext::enable_mod(const std::string& mod_id, bool enable | ||||||
|                         if (enabled_mod_it != opened_mods_by_id.end()) { |                         if (enabled_mod_it != opened_mods_by_id.end()) { | ||||||
|                             const ModHandle &enabled_mod_handle = opened_mods[enabled_mod_it->second]; |                             const ModHandle &enabled_mod_handle = opened_mods[enabled_mod_it->second]; | ||||||
|                             for (ModContentTypeId type_id : enabled_mod_handle.content_types) { |                             for (ModContentTypeId type_id : enabled_mod_handle.content_types) { | ||||||
|                                 content_types[type_id.value].on_disabled(*this, enabled_mod_handle); |                                 content_disabled_callback* callback = content_types[type_id.value].on_disabled; | ||||||
|  |                                 if (callback) { | ||||||
|  |                                     callback(*this, enabled_mod_handle); | ||||||
|  |                                 } | ||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|  | @ -1077,6 +1093,31 @@ std::string recomp::mods::ModContext::get_mod_id_from_filename(const std::filesy | ||||||
|     return opened_mods[find_it->second].manifest.mod_id; |     return opened_mods[find_it->second].manifest.mod_id; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | std::filesystem::path recomp::mods::ModContext::get_mod_filename(const std::string& mod_id) const { | ||||||
|  |     auto find_it = opened_mods_by_id.find(mod_id); | ||||||
|  |     if (find_it == opened_mods_by_id.end()) { | ||||||
|  |         return {}; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return opened_mods[find_it->second].manifest.mod_root_path; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | size_t recomp::mods::ModContext::get_mod_order_index(const std::string& mod_id) const { | ||||||
|  |     auto find_it = opened_mods_by_id.find(mod_id); | ||||||
|  |     if (find_it == opened_mods_by_id.end()) { | ||||||
|  |         return static_cast<size_t>(-1); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // TODO keep a mapping of mod index to mod order index to prevent needing a lookup here.
 | ||||||
|  |     auto find_order_it = std::find(opened_mods_order.begin(), opened_mods_order.end(), find_it->second); | ||||||
|  |     if (find_order_it == opened_mods_order.end()) { | ||||||
|  |         assert(false); | ||||||
|  |         return static_cast<size_t>(-1); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return find_order_it - opened_mods_order.begin(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| std::optional<recomp::mods::ModDetails> recomp::mods::ModContext::get_details_for_mod(const std::string& mod_id) const { | std::optional<recomp::mods::ModDetails> recomp::mods::ModContext::get_details_for_mod(const std::string& mod_id) const { | ||||||
|     auto find_it = opened_mods_by_id.find(mod_id); |     auto find_it = opened_mods_by_id.find(mod_id); | ||||||
|     if (find_it == opened_mods_by_id.end()) { |     if (find_it == opened_mods_by_id.end()) { | ||||||
|  | @ -1272,6 +1313,13 @@ void recomp::mods::ModContext::set_mod_index(const std::string &mod_game_id, con | ||||||
|         opened_mods_order.push_back(mod_index); |         opened_mods_order.push_back(mod_index); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     for (ModContentTypeId type_id : opened_mods[mod_index].content_types) { | ||||||
|  |         content_reordered_callback* callback = content_types[type_id.value].on_reordered; | ||||||
|  |         if (callback) { | ||||||
|  |             callback(*this); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     mod_configuration_thread_queue.enqueue(ModConfigQueueSave()); |     mod_configuration_thread_queue.enqueue(ModConfigQueueSave()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -563,6 +563,16 @@ std::string recomp::mods::get_mod_id_from_filename(const std::filesystem::path& | ||||||
|     return mod_context->get_mod_id_from_filename(mod_filename); |     return mod_context->get_mod_id_from_filename(mod_filename); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | std::filesystem::path recomp::mods::get_mod_filename(const std::string& mod_id) { | ||||||
|  |     std::lock_guard lock { mod_context_mutex }; | ||||||
|  |     return mod_context->get_mod_filename(mod_id); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | size_t recomp::mods::get_mod_order_index(const std::string& mod_id) { | ||||||
|  |     std::lock_guard lock { mod_context_mutex }; | ||||||
|  |     return mod_context->get_mod_order_index(mod_id); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| std::optional<recomp::mods::ModDetails> recomp::mods::get_details_for_mod(const std::string& mod_id) { | std::optional<recomp::mods::ModDetails> recomp::mods::get_details_for_mod(const std::string& mod_id) { | ||||||
|     std::lock_guard lock { mod_context_mutex }; |     std::lock_guard lock { mod_context_mutex }; | ||||||
|     return mod_context->get_details_for_mod(mod_id); |     return mod_context->get_details_for_mod(mod_id); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Wiseguy
						Wiseguy