diff --git a/src/ship/quests.rs b/src/ship/quests.rs index 6d10735..da94e0e 100644 --- a/src/ship/quests.rs +++ b/src/ship/quests.rs @@ -97,7 +97,6 @@ fn read_dat_section_header(cursor: &mut T, episode: &Episode) -> fn quest_episode(bin: &[u8]) -> Option { for bytes in bin.windows(3) { if bytes[0] == 0xF8 && bytes[1] == 0xBC { - warn!("ep? {:?}", bytes[2]); return Some(Episode::from_quest(bytes[2]).ok()?) } } @@ -136,6 +135,10 @@ fn parse_dat(dat: &[u8], episode: &Episode) -> Result<(Vec>, Ve #[error("")] enum QuestLoadError { ParseDatError(#[from] ParseDatError), + CouldNotReadMetadata, + CouldNotLoadConfigFile, + QuestFileNotFound(String), + CouldNotLoadFile(String), } #[derive(Debug)] @@ -153,8 +156,8 @@ pub struct Quest { impl Quest { fn from_bin_dat(bin: Vec, dat: Vec) -> Result { - let id = u16::from_le_bytes(bin[16..18].try_into().unwrap()); - let language = u16::from_le_bytes(bin[18..20].try_into().unwrap()); + let id = u16::from_le_bytes(bin[16..18].try_into().map_err(|_| QuestLoadError::CouldNotReadMetadata)?); + let language = u16::from_le_bytes(bin[18..20].try_into().map_err(|_| QuestLoadError::CouldNotReadMetadata)?); let name = array_to_utf16(&bin[24..88]); let description = array_to_utf16(&bin[88..334]); let full_description = array_to_utf16(&bin[334..920]); @@ -173,8 +176,8 @@ impl Quest { full_description: full_description, id: id, language: language, - bin_blob: prs_bin.into_inner().unwrap(), - dat_blob: prs_dat.into_inner().unwrap(), + bin_blob: prs_bin.into_inner().map_err(|_| QuestLoadError::CouldNotReadMetadata)?, + dat_blob: prs_dat.into_inner().map_err(|_| QuestLoadError::CouldNotReadMetadata)?, enemies: enemies, objects: objects, }) @@ -184,31 +187,39 @@ impl Quest { // QuestCollection pub type QuestList = BTreeMap>; -pub fn load_quests(quest_path: PathBuf) -> QuestList { - let mut f = File::open(quest_path).unwrap(); +pub fn load_quests(quest_path: PathBuf) -> Result { + let mut f = File::open(quest_path).map_err(|_| QuestLoadError::CouldNotLoadConfigFile)?; let mut s = String::new(); f.read_to_string(&mut s); let mut used_quest_ids = BTreeSet::new(); - let ql: BTreeMap = toml::from_str(s.as_str()).unwrap(); + let ql: BTreeMap = toml::from_str(s.as_str()).map_err(|_| QuestLoadError::CouldNotLoadConfigFile)?; - ql.into_iter().map(|(category, category_details)| { + Ok(ql.into_iter().map(|(category, category_details)| { let quests = category_details.quests .into_iter() .filter_map(|quest| { - warn!("{:?}", quest.bin); - let dat_file = File::open(format!("data/quests/{}", quest.dat)).unwrap(); - let bin_file = File::open(format!("data/quests/{}", quest.bin)).unwrap(); + let dat_file = File::open(format!("data/quests/{}", quest.dat)) + .map_err(|err| { + warn!("could not load quest file {}: {:?}", quest.dat, err) + }).ok()?; + let bin_file = File::open(format!("data/quests/{}", quest.bin)) + .map_err(|err| { + warn!("could not load quest file {}: {:?}", quest.bin, err) + }).ok()?; let mut dat_prs = LegacyPrsDecoder::new(dat_file); let mut bin_prs = LegacyPrsDecoder::new(bin_file); let mut dat = Vec::new(); let mut bin = Vec::new(); - dat_prs.read_to_end(&mut dat).unwrap(); - bin_prs.read_to_end(&mut bin).unwrap(); + dat_prs.read_to_end(&mut dat).ok()?; + bin_prs.read_to_end(&mut bin).ok()?; - let quest = Quest::from_bin_dat(bin, dat).unwrap(); + let quest = Quest::from_bin_dat(bin, dat).map_err(|err| { + warn!("could not parse quest file {}/{}: {:?}", quest.bin, quest.dat, err) + }).ok()?; if used_quest_ids.contains(&quest.id) { + warn!("quest id already exists: {}", quest.id); return None; } used_quest_ids.insert(quest.id); @@ -219,6 +230,5 @@ pub fn load_quests(quest_path: PathBuf) -> QuestList { name: category, description: category_details.description, }, quests.collect()) - }).collect() - + }).collect()) } diff --git a/src/ship/ship.rs b/src/ship/ship.rs index 4e91f6c..b6874c1 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -257,7 +257,7 @@ impl ShipServerState { name: "Sona-Nyl".into(), rooms: [None; MAX_ROOMS], item_manager: items::ItemManager::new(), - quests: quests::load_quests("data/quests.toml".into()), + quests: quests::load_quests("data/quests.toml".into()).unwrap(), } }