diff --git a/src/data/builtin/builtin_data/locale/en.json b/src/data/builtin/builtin_data/locale/en.json index d7554c7..d5064fd 100644 --- a/src/data/builtin/builtin_data/locale/en.json +++ b/src/data/builtin/builtin_data/locale/en.json @@ -60,6 +60,10 @@ "replay_last": "Replay Last", "delete_replay": "Delete Best Replay" }, + "challenges_menu": { + "empty_mod_name": "No Mod Name", + "empty_mod_description": "No Description" + }, "options_menu": { "graphics": "Graphics...", "graphics_menu": { diff --git a/src/data/builtin/builtin_data/locale/jp.json b/src/data/builtin/builtin_data/locale/jp.json index 811d478..d65bef7 100644 --- a/src/data/builtin/builtin_data/locale/jp.json +++ b/src/data/builtin/builtin_data/locale/jp.json @@ -60,6 +60,10 @@ "replay_last": "最後のプレイを再生", "delete_replay": "ベストリプレイを削除" }, + "challenges_menu": { + "empty_mod_name": "モッド名なし", + "empty_mod_description": "描写なし" + }, "options_menu": { "graphics": "グラフィック", "graphics_menu": { diff --git a/src/game/shared_game_state.rs b/src/game/shared_game_state.rs index 609caff..7aeae1d 100644 --- a/src/game/shared_game_state.rs +++ b/src/game/shared_game_state.rs @@ -512,10 +512,7 @@ impl SharedGameState { } pub fn reload_stage_table(&mut self, ctx: &mut Context) -> GameResult { - let stages = StageData::load_stage_table( - self, - ctx, - )?; + let stages = StageData::load_stage_table(self, ctx)?; self.stages = stages; Ok(()) } @@ -860,12 +857,14 @@ impl SharedGameState { } pub fn get_rec_filename(&self) -> String { - if let Some(mod_path) = &self.mod_path { - let name = self.mod_list.get_name_from_path(mod_path.to_string()); - return format!("/{}", name); - } else { - return "/290".to_string(); - } + let name = &self + .mod_path + .clone() + .and_then(|mod_path| self.mod_list.get_info_from_path(mod_path)) + .and_then(|mod_info| mod_info.name.clone().or(Some(mod_info.id.clone()))) + .unwrap_or("290".to_owned()); + + format!("/{name}") } pub fn has_replay_data(&self, ctx: &mut Context, replay_kind: ReplayKind) -> bool { diff --git a/src/mod_list.rs b/src/mod_list.rs index 7a5ddba..25c0791 100644 --- a/src/mod_list.rs +++ b/src/mod_list.rs @@ -15,8 +15,8 @@ pub struct ModInfo { pub priority: u32, pub save_slot: i32, pub path: String, - pub name: String, - pub description: String, + pub name: Option, + pub description: Option, pub valid: bool, } @@ -81,7 +81,7 @@ impl ModList { } consume_spaces(&mut chars); - id.push_str("csmod_"); + id.push_str("cspmod_"); for c in &mut chars { if c == ' ' { break; @@ -150,8 +150,8 @@ impl ModList { } let mut valid = false; - let mut name = String::new(); - let mut description = String::new(); + let mut name: Option = None; + let mut description: Option = None; let mut save_slot = -1; if let Ok(file) = filesystem::open(ctx, [&path, "/mod.txt"].join("")) { @@ -162,15 +162,14 @@ impl ModList { save_slot = line.unwrap_or("-1".to_string()).parse::().unwrap_or(-1); } if let Some(line) = lines.next() { - let read_name = line.unwrap_or("No Mod Name".to_string()).to_string(); - name = string_table.get(&read_name).unwrap_or(&read_name).to_string(); + name = line.ok().and_then(|read_name| { + let name = string_table.get(&read_name).or(Some(&read_name)).cloned(); + name.filter(|s| !s.is_empty()) + }); } if let Some(line) = lines.next() { - description = line.unwrap_or("No Description".to_string()).to_string(); + description = line.ok().filter(|s| !s.is_empty()); } - } else { - name = path.clone(); - description = "mod.txt not found".to_string(); } mods.push(ModInfo { id, requirement, priority, save_slot, path, name, description, valid }) @@ -182,19 +181,15 @@ impl ModList { Ok(ModList { mods }) } - pub fn get_save_from_path(&self, mod_path: String) -> i32 { - if let Some(mod_sel) = self.mods.iter().find(|x| x.path == mod_path) { - mod_sel.save_slot - } else { - -1 - } + pub fn get_info_from_path(&self, mod_path: String) -> Option<&ModInfo> { + self.mods.iter().find(|x| x.path == mod_path) } - pub fn get_name_from_path(&self, mod_path: String) -> &str { - if let Some(mod_sel) = self.mods.iter().find(|x| x.path == mod_path) { - &mod_sel.name - } else { - "NoName" - } + pub fn get_save_from_path(&self, mod_path: String) -> i32 { + self.get_info_from_path(mod_path).and_then(|mod_info| Some(mod_info.save_slot)).unwrap_or(-1) + } + + pub fn get_name_from_path(&self, mod_path: String) -> Option<&str> { + self.get_info_from_path(mod_path).and_then(|mod_info| mod_info.name.as_deref()) } } diff --git a/src/scene/title_scene.rs b/src/scene/title_scene.rs index e378847..5b50c59 100644 --- a/src/scene/title_scene.rs +++ b/src/scene/title_scene.rs @@ -254,8 +254,15 @@ impl Scene for TitleScene { continue; } if mod_info.satisfies_requirement(&state.mod_requirements) { - self.challenges_menu - .push_entry(ChallengesMenuEntry::Challenge(idx), MenuEntry::Active(mod_info.name.clone())); + self.challenges_menu.push_entry( + ChallengesMenuEntry::Challenge(idx), + MenuEntry::Active( + mod_info + .name + .clone() + .unwrap_or(state.loc.t("menus.challenges_menu.empty_mod_name").to_string()), + ), + ); if mutate_selection { selected = ChallengesMenuEntry::Challenge(idx); @@ -387,6 +394,7 @@ impl Scene for TitleScene { } CurrentMenu::ChallengesMenu => match self.challenges_menu.tick(&mut self.controller, state) { MenuSelectionResult::Selected(ChallengesMenuEntry::Challenge(idx), _) => { + let fallback_mod_name = state.loc.t("menus.challenges_menu.empty_mod_name").to_owned(); if let Some(mod_info) = state.mod_list.mods.get(idx) { state.mod_path = Some(mod_info.path.clone()); if mod_info.save_slot >= 0 { @@ -395,7 +403,7 @@ impl Scene for TitleScene { self.nikumaru_rec.load_counter(state, ctx)?; self.current_menu = CurrentMenu::SaveSelectMenu; } else { - let mod_name = mod_info.name.clone(); + let mod_name = mod_info.name.clone().unwrap_or(fallback_mod_name.clone()); self.confirm_menu.width = (state.font.builder().compute_width(&mod_name).max(50.0) + 32.0) as u16;