diff --git a/src/ship/packet/builder/quest.rs b/src/ship/packet/builder/quest.rs index 9a33696..089fe56 100644 --- a/src/ship/packet/builder/quest.rs +++ b/src/ship/packet/builder/quest.rs @@ -1,7 +1,7 @@ use crate::ship::quests::{Quest, QuestList}; use crate::ship::ship::{QUEST_CATEGORY_MENU_ID, QUEST_SELECT_MENU_ID}; use libpso::packet::ship::*; -use libpso::utf8_to_utf16_array; +use libpso::{utf8_to_array, utf8_to_utf16_array}; pub fn quest_category_list(quests: &QuestList) -> QuestCategoryList { @@ -45,3 +45,24 @@ pub fn quest_detail(quest: &Quest) -> QuestDetail { description: utf8_to_utf16_array!(quest.full_description, 288), } } + +pub fn quest_header(quest_menu_select: &QuestMenuSelect, data_blob: &[u8], suffix: &str) -> QuestHeader { + let path = format!("{}-{}.{}", quest_menu_select.category, quest_menu_select.quest, suffix); + QuestHeader { + unknown1: [0; 0x24], + filename: utf8_to_array!(path, 16), + length: data_blob.len() as u32, + name: utf8_to_array!(path, 16), + unknown2: [0; 8], + } +} + +pub fn quest_chunk(chunk_num: u32, filename: [u8; 16], blob: [u8; 0x400], blob_length: usize) -> QuestChunk { + QuestChunk { + chunk_num: chunk_num, + filename: filename, + blob: blob, + blob_length: blob_length as u32, + unknown: 0, + } +} diff --git a/src/ship/packet/handler/quest.rs b/src/ship/packet/handler/quest.rs index ca5cdf9..bf1b49f 100644 --- a/src/ship/packet/handler/quest.rs +++ b/src/ship/packet/handler/quest.rs @@ -11,11 +11,12 @@ use libpso::utf8_to_array; use libpso::util::array_to_utf8; // TOOD: enum -const DATATYPE_BIN: u16 = 1; -const DATATYPE_DAT: u16 = 2; - +enum QuestFileType { + Bin, + Dat +} -fn parse_filename(filename_bytes: &[u8; 16]) -> Result<(u16, u16, u16), ShipError> { +fn parse_filename(filename_bytes: &[u8; 16]) -> Result<(u16, u16, QuestFileType), ShipError> { let filename = array_to_utf8(*filename_bytes).map_err(|_| ShipError::InvalidQuestFilename("NOT UTF8".to_string()))?; let (filename, suffix) = { let mut s = filename.splitn(2, '.'); @@ -24,8 +25,8 @@ fn parse_filename(filename_bytes: &[u8; 16]) -> Result<(u16, u16, u16), ShipErro }; let datatype = match suffix { - "bin" => DATATYPE_BIN, - "dat" => DATATYPE_DAT, + "bin" => QuestFileType::Bin, + "dat" => QuestFileType::Dat, _ => return Err(ShipError::InvalidQuestFilename(filename.to_owned())) }; @@ -87,23 +88,8 @@ pub fn load_quest(id: ClientId, questmenuselect: &QuestMenuSelect, quests: &Ques .ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))?; room.maps.set_quest_data(quest.enemies.clone(), quest.objects.clone()); - let bin_path = format!("{}-{}.bin", questmenuselect.category, questmenuselect.quest); - let bin = QuestHeader { - unknown1: [0; 0x24], - filename: utf8_to_array!(bin_path, 16), - length: quest.bin_blob.len() as u32, - name: utf8_to_array!("quest.bin", 16), - unknown2: [0; 8], - }; - - let dat_path = format!("{}-{}.dat", questmenuselect.category, questmenuselect.quest); - let dat = QuestHeader { - unknown1: [0; 0x24], - filename: utf8_to_array!(dat_path, 16), - length: quest.dat_blob.len() as u32, - name: utf8_to_array!("quest.dat", 16), - unknown2: [0; 8], - }; + let bin = quest::quest_header(questmenuselect, &quest.bin_blob, "bin"); + let dat = quest::quest_header(questmenuselect, &quest.dat_blob, "dat"); let area_clients = client_location.get_all_clients_by_client(id).map_err(|err| -> ClientLocationError { err.into() })?; area_clients.iter().for_each(|c| { @@ -114,8 +100,6 @@ pub fn load_quest(id: ClientId, questmenuselect: &QuestMenuSelect, quests: &Ques Ok(Box::new(area_clients.into_iter().map(move |c| { vec![(c.client, SendShipPacket::QuestHeader(bin.clone())), (c.client, SendShipPacket::QuestHeader(dat.clone()))] }).flatten())) - - //Ok(Box::new(vec![(id, SendShipPacket::QuestHeader(bin)), (id, SendShipPacket::QuestHeader(dat))].into_iter())) } pub fn quest_file_request(id: ClientId, quest_file_request: &QuestFileRequest, quests: &QuestList) -> Result + Send>, ShipError> { @@ -129,23 +113,15 @@ pub fn quest_file_request(id: ClientId, quest_file_request: &QuestFileRequest, q q.id == quest_id as u16 }).ok_or(ShipError::InvalidQuest(quest_id as u32))?; - // quest.Bin quest.Dat let blob = match datatype { - DATATYPE_BIN => &quest.bin_blob, - DATATYPE_DAT => &quest.dat_blob, - _ => panic!() + QuestFileType::Bin => &quest.bin_blob, + QuestFileType::Dat => &quest.dat_blob, }; let mut blob_cursor = Cursor::new(blob); let mut subblob = [0u8; 0x400]; let blob_length = blob_cursor.read(&mut subblob)?; - let qc = QuestChunk { - chunk_num: 0, - filename: quest_file_request.filename, - blob: subblob, - blob_length: blob_length as u32, - unknown: 0, - }; + let qc = quest::quest_chunk(0, quest_file_request.filename, subblob, blob_length); Ok(Box::new(vec![(id, SendShipPacket::QuestChunk(qc))].into_iter())) } @@ -162,9 +138,8 @@ pub fn quest_chunk_ack(id: ClientId, quest_chunk_ack: &QuestChunkAck, quests: &Q }).ok_or(ShipError::InvalidQuest(quest_id as u32))?; let blob = match datatype { - DATATYPE_BIN => &quest.bin_blob, - DATATYPE_DAT => &quest.dat_blob, - _ => panic!() + QuestFileType::Bin => &quest.bin_blob, + QuestFileType::Dat => &quest.dat_blob, }; let mut blob_cursor = Cursor::new(blob); @@ -174,13 +149,7 @@ pub fn quest_chunk_ack(id: ClientId, quest_chunk_ack: &QuestChunkAck, quests: &Q if blob_length == 0 { return Ok(Box::new(None.into_iter())); } - let qc = QuestChunk { - chunk_num: quest_chunk_ack.chunk_num + 1, - filename: quest_chunk_ack.filename, - blob: subblob, - blob_length: blob_length as u32, - unknown: 0, - }; + let qc = quest::quest_chunk(quest_chunk_ack.chunk_num + 1, quest_chunk_ack.filename, subblob, blob_length); Ok(Box::new(vec![(id, SendShipPacket::QuestChunk(qc))].into_iter())) } diff --git a/src/ship/quests.rs b/src/ship/quests.rs index da94e0e..02c0a8a 100644 --- a/src/ship/quests.rs +++ b/src/ship/quests.rs @@ -133,7 +133,7 @@ fn parse_dat(dat: &[u8], episode: &Episode) -> Result<(Vec>, Ve #[derive(Error, Debug)] #[error("")] -enum QuestLoadError { +pub enum QuestLoadError { ParseDatError(#[from] ParseDatError), CouldNotReadMetadata, CouldNotLoadConfigFile,