mirror of
https://github.com/N64Recomp/N64ModernRuntime.git
synced 2026-04-26 03:51:54 +00:00
Add custom gamemode option to mod manifest and implement gamemode mechanism
This commit is contained in:
parent
a857af008d
commit
5db1c639bc
6 changed files with 63 additions and 18 deletions
|
|
@ -1 +1 @@
|
|||
Subproject commit 98bf104b1b5ed83126af8bcab0cc964782617dbf
|
||||
Subproject commit 2b6f05688de2abc7d86da5b4a89b84c2c6acbabe
|
||||
|
|
@ -108,7 +108,7 @@ namespace recomp {
|
|||
bool sram_allowed();
|
||||
bool flashram_allowed();
|
||||
|
||||
void start_game(const std::u8string& game_id);
|
||||
void start_game(const std::u8string& game_id, const std::string& game_mode_id);
|
||||
std::u8string current_game_id();
|
||||
std::string current_mod_game_id();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -204,6 +204,7 @@ namespace recomp {
|
|||
std::vector<Dependency> dependencies;
|
||||
bool runtime_toggleable;
|
||||
bool enabled_by_default;
|
||||
bool custom_gamemode;
|
||||
};
|
||||
|
||||
struct ModManifest {
|
||||
|
|
@ -221,6 +222,7 @@ namespace recomp {
|
|||
Version version;
|
||||
bool runtime_toggleable;
|
||||
bool enabled_by_default;
|
||||
bool custom_gamemode;
|
||||
|
||||
std::vector<NativeLibraryManifest> native_libraries;
|
||||
std::unique_ptr<ModFileHandle> file_handle;
|
||||
|
|
@ -319,10 +321,10 @@ namespace recomp {
|
|||
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);
|
||||
bool is_mod_auto_enabled(const std::string& mod_id);
|
||||
bool is_mod_enabled(const std::string& mod_id) const;
|
||||
bool is_mod_auto_enabled(const std::string& mod_id) const;
|
||||
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);
|
||||
std::vector<ModLoadErrorDetails> 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();
|
||||
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;
|
||||
|
|
@ -330,6 +332,7 @@ namespace recomp {
|
|||
size_t get_mod_order_index(size_t mod_index) 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);
|
||||
size_t game_mode_count(const std::string& mod_game_id, bool include_disabled) const;
|
||||
recomp::Version get_mod_version(size_t mod_index);
|
||||
std::string get_mod_id(size_t mod_index);
|
||||
void set_mod_index(const std::string &mod_game_id, const std::string &mod_id, size_t index);
|
||||
|
|
@ -475,7 +478,8 @@ namespace recomp {
|
|||
.authors = manifest.authors,
|
||||
.dependencies = manifest.dependencies,
|
||||
.runtime_toggleable = is_runtime_toggleable(),
|
||||
.enabled_by_default = manifest.enabled_by_default
|
||||
.enabled_by_default = manifest.enabled_by_default,
|
||||
.custom_gamemode = manifest.custom_gamemode
|
||||
};
|
||||
}
|
||||
private:
|
||||
|
|
@ -592,6 +596,7 @@ namespace recomp {
|
|||
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);
|
||||
size_t game_mode_count(const std::string& mod_game_id, bool include_disabled);
|
||||
recomp::Version get_mod_version(size_t mod_index);
|
||||
std::string get_mod_id(size_t mod_index);
|
||||
void enable_mod(const std::string& mod_id, bool enabled);
|
||||
|
|
|
|||
|
|
@ -151,6 +151,7 @@ const std::string version_key = "version";
|
|||
const std::string authors_key = "authors";
|
||||
const std::string minimum_recomp_version_key = "minimum_recomp_version";
|
||||
const std::string enabled_by_default_key = "enabled_by_default";
|
||||
const std::string custom_gamemode_key = "custom_gamemode";
|
||||
const std::string dependencies_key = "dependencies";
|
||||
const std::string optional_dependencies_key = "optional_dependencies";
|
||||
const std::string native_libraries_key = "native_libraries";
|
||||
|
|
@ -706,6 +707,12 @@ recomp::mods::ModOpenError recomp::mods::parse_manifest(ModManifest& ret, const
|
|||
return current_error;
|
||||
}
|
||||
|
||||
// Custom gamemode (optional, false if not present)
|
||||
current_error = try_get<json::boolean_t>(ret.custom_gamemode, manifest_json, custom_gamemode_key, false, error_param, false);
|
||||
if (current_error != ModOpenError::Good) {
|
||||
return current_error;
|
||||
}
|
||||
|
||||
// Dependencies (optional)
|
||||
std::vector<std::string> dep_strings{};
|
||||
current_error = try_get_vec<json::string_t>(dep_strings, manifest_json, dependencies_key, false, error_param);
|
||||
|
|
|
|||
|
|
@ -1127,11 +1127,11 @@ void recomp::mods::ModContext::enable_mod(const std::string& mod_id, bool enable
|
|||
}
|
||||
}
|
||||
|
||||
bool recomp::mods::ModContext::is_mod_enabled(const std::string& mod_id) {
|
||||
bool recomp::mods::ModContext::is_mod_enabled(const std::string& mod_id) const {
|
||||
return enabled_mods.contains(mod_id);
|
||||
}
|
||||
|
||||
bool recomp::mods::ModContext::is_mod_auto_enabled(const std::string& mod_id) {
|
||||
bool recomp::mods::ModContext::is_mod_auto_enabled(const std::string& mod_id) const {
|
||||
return auto_enabled_mods.contains(mod_id);
|
||||
}
|
||||
|
||||
|
|
@ -1210,6 +1210,29 @@ std::vector<recomp::mods::ModDetails> recomp::mods::ModContext::get_all_mod_deta
|
|||
return ret;
|
||||
}
|
||||
|
||||
size_t recomp::mods::ModContext::game_mode_count(const std::string& mod_game_id, bool include_disabled) const {
|
||||
size_t ret = 0;
|
||||
bool all_games = mod_game_id.empty();
|
||||
size_t game_index = (size_t)-1;
|
||||
|
||||
auto find_game_it = mod_game_ids.find(mod_game_id);
|
||||
if (find_game_it != mod_game_ids.end()) {
|
||||
game_index = find_game_it->second;
|
||||
}
|
||||
|
||||
for (const ModHandle &mod : opened_mods) {
|
||||
if (all_games || mod.is_for_game(game_index)) {
|
||||
if (include_disabled || is_mod_enabled(mod.manifest.mod_id) || is_mod_auto_enabled(mod.manifest.mod_id)) {
|
||||
if (mod.manifest.custom_gamemode) {
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
recomp::Version recomp::mods::ModContext::get_mod_version(size_t mod_index) {
|
||||
return opened_mods[mod_index].manifest.version;
|
||||
}
|
||||
|
|
@ -1484,7 +1507,7 @@ void recomp::mods::ModContext::set_mod_config_directory(const std::filesystem::p
|
|||
mod_config_directory = path;
|
||||
}
|
||||
|
||||
std::vector<recomp::mods::ModLoadErrorDetails> recomp::mods::ModContext::load_mods(const GameEntry& game_entry, uint8_t* rdram, int32_t load_address, uint32_t& ram_used) {
|
||||
std::vector<recomp::mods::ModLoadErrorDetails> recomp::mods::ModContext::load_mods(const GameEntry& game_entry, const std::string& game_mode_id, uint8_t* rdram, int32_t load_address, uint32_t& ram_used) {
|
||||
std::vector<recomp::mods::ModLoadErrorDetails> ret{};
|
||||
ram_used = 0;
|
||||
num_events = recomp::overlays::num_base_events();
|
||||
|
|
@ -1529,15 +1552,18 @@ std::vector<recomp::mods::ModLoadErrorDetails> recomp::mods::ModContext::load_mo
|
|||
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) || 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);
|
||||
// Only load gamemode mods if the current gamemode matches the mod id.
|
||||
if (!mod.manifest.custom_gamemode || game_mode_id == mod.manifest.mod_id) {
|
||||
active_mods.push_back(mod_index);
|
||||
loaded_mods_by_id.emplace(mod.manifest.mod_id, mod_index);
|
||||
|
||||
printf("Loading mod %s\n", mod.manifest.mod_id.c_str());
|
||||
std::string load_error_param;
|
||||
ModLoadError load_error = load_mod(mod, load_error_param);
|
||||
printf("Loading mod %s\n", mod.manifest.mod_id.c_str());
|
||||
std::string load_error_param;
|
||||
ModLoadError load_error = load_mod(mod, load_error_param);
|
||||
|
||||
if (load_error != ModLoadError::Good) {
|
||||
ret.emplace_back(mod.manifest.mod_id, load_error, load_error_param);
|
||||
if (load_error != ModLoadError::Good) {
|
||||
ret.emplace_back(mod.manifest.mod_id, load_error, load_error_param);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -461,6 +461,7 @@ extern "C" void do_break(uint32_t vram) {
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
std::string current_game_mode_id;
|
||||
std::optional<std::u8string> current_game = std::nullopt;
|
||||
std::atomic<GameStatus> game_status = GameStatus::None;
|
||||
|
||||
|
|
@ -526,8 +527,9 @@ std::string recomp::current_mod_game_id() {
|
|||
return game_entry.mod_game_id;
|
||||
}
|
||||
|
||||
void recomp::start_game(const std::u8string& game_id) {
|
||||
void recomp::start_game(const std::u8string& game_id, const std::string& game_mode_id) {
|
||||
std::lock_guard<std::mutex> lock(current_game_mutex);
|
||||
current_game_mode_id = game_mode_id;
|
||||
current_game = game_id;
|
||||
game_status.store(GameStatus::Running);
|
||||
game_status.notify_all();
|
||||
|
|
@ -629,6 +631,11 @@ std::vector<recomp::mods::ModDetails> recomp::mods::get_all_mod_details(const st
|
|||
return mod_context->get_all_mod_details(mod_game_id);
|
||||
}
|
||||
|
||||
size_t recomp::mods::game_mode_count(const std::string& mod_game_id, bool include_disabled) {
|
||||
std::lock_guard lock { mod_context_mutex };
|
||||
return mod_context->game_mode_count(mod_game_id, include_disabled);
|
||||
}
|
||||
|
||||
recomp::Version recomp::mods::get_mod_version(size_t mod_index) {
|
||||
std::lock_guard lock { mod_context_mutex };
|
||||
return mod_context->get_mod_version(mod_index);
|
||||
|
|
@ -668,7 +675,7 @@ bool wait_for_game_started(uint8_t* rdram, recomp_context* context) {
|
|||
std::vector<recomp::mods::ModLoadErrorDetails> mod_load_errors;
|
||||
{
|
||||
std::lock_guard lock { mod_context_mutex };
|
||||
mod_load_errors = mod_context->load_mods(game_entry, rdram, recomp::mod_rdram_start, mod_ram_used);
|
||||
mod_load_errors = mod_context->load_mods(game_entry, current_game_mode_id, rdram, recomp::mod_rdram_start, mod_ram_used);
|
||||
}
|
||||
|
||||
if (!mod_load_errors.empty()) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue