use builder::quest
This commit is contained in:
parent
1954225d34
commit
fd221ab6a2
@ -1,7 +1,7 @@
|
|||||||
use crate::ship::quests::{Quest, QuestList};
|
use crate::ship::quests::{Quest, QuestList};
|
||||||
use crate::ship::ship::{QUEST_CATEGORY_MENU_ID, QUEST_SELECT_MENU_ID};
|
use crate::ship::ship::{QUEST_CATEGORY_MENU_ID, QUEST_SELECT_MENU_ID};
|
||||||
use libpso::packet::ship::*;
|
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 {
|
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),
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -11,11 +11,12 @@ use libpso::utf8_to_array;
|
|||||||
use libpso::util::array_to_utf8;
|
use libpso::util::array_to_utf8;
|
||||||
|
|
||||||
// TOOD: enum
|
// TOOD: enum
|
||||||
const DATATYPE_BIN: u16 = 1;
|
enum QuestFileType {
|
||||||
const DATATYPE_DAT: u16 = 2;
|
Bin,
|
||||||
|
Dat
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_filename(filename_bytes: &[u8; 16]) -> Result<(u16, u16, QuestFileType), ShipError> {
|
||||||
fn parse_filename(filename_bytes: &[u8; 16]) -> Result<(u16, u16, u16), ShipError> {
|
|
||||||
let filename = array_to_utf8(*filename_bytes).map_err(|_| ShipError::InvalidQuestFilename("NOT UTF8".to_string()))?;
|
let filename = array_to_utf8(*filename_bytes).map_err(|_| ShipError::InvalidQuestFilename("NOT UTF8".to_string()))?;
|
||||||
let (filename, suffix) = {
|
let (filename, suffix) = {
|
||||||
let mut s = filename.splitn(2, '.');
|
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 {
|
let datatype = match suffix {
|
||||||
"bin" => DATATYPE_BIN,
|
"bin" => QuestFileType::Bin,
|
||||||
"dat" => DATATYPE_DAT,
|
"dat" => QuestFileType::Dat,
|
||||||
_ => return Err(ShipError::InvalidQuestFilename(filename.to_owned()))
|
_ => 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))?;
|
.ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))?;
|
||||||
room.maps.set_quest_data(quest.enemies.clone(), quest.objects.clone());
|
room.maps.set_quest_data(quest.enemies.clone(), quest.objects.clone());
|
||||||
|
|
||||||
let bin_path = format!("{}-{}.bin", questmenuselect.category, questmenuselect.quest);
|
let bin = quest::quest_header(questmenuselect, &quest.bin_blob, "bin");
|
||||||
let bin = QuestHeader {
|
let dat = quest::quest_header(questmenuselect, &quest.dat_blob, "dat");
|
||||||
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 area_clients = client_location.get_all_clients_by_client(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let area_clients = client_location.get_all_clients_by_client(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
area_clients.iter().for_each(|c| {
|
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| {
|
Ok(Box::new(area_clients.into_iter().map(move |c| {
|
||||||
vec![(c.client, SendShipPacket::QuestHeader(bin.clone())), (c.client, SendShipPacket::QuestHeader(dat.clone()))]
|
vec![(c.client, SendShipPacket::QuestHeader(bin.clone())), (c.client, SendShipPacket::QuestHeader(dat.clone()))]
|
||||||
}).flatten()))
|
}).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<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError> {
|
pub fn quest_file_request(id: ClientId, quest_file_request: &QuestFileRequest, quests: &QuestList) -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError> {
|
||||||
@ -129,23 +113,15 @@ pub fn quest_file_request(id: ClientId, quest_file_request: &QuestFileRequest, q
|
|||||||
q.id == quest_id as u16
|
q.id == quest_id as u16
|
||||||
}).ok_or(ShipError::InvalidQuest(quest_id as u32))?;
|
}).ok_or(ShipError::InvalidQuest(quest_id as u32))?;
|
||||||
|
|
||||||
// quest.Bin quest.Dat
|
|
||||||
let blob = match datatype {
|
let blob = match datatype {
|
||||||
DATATYPE_BIN => &quest.bin_blob,
|
QuestFileType::Bin => &quest.bin_blob,
|
||||||
DATATYPE_DAT => &quest.dat_blob,
|
QuestFileType::Dat => &quest.dat_blob,
|
||||||
_ => panic!()
|
|
||||||
};
|
};
|
||||||
let mut blob_cursor = Cursor::new(blob);
|
let mut blob_cursor = Cursor::new(blob);
|
||||||
|
|
||||||
let mut subblob = [0u8; 0x400];
|
let mut subblob = [0u8; 0x400];
|
||||||
let blob_length = blob_cursor.read(&mut subblob)?;
|
let blob_length = blob_cursor.read(&mut subblob)?;
|
||||||
let qc = QuestChunk {
|
let qc = quest::quest_chunk(0, quest_file_request.filename, subblob, blob_length);
|
||||||
chunk_num: 0,
|
|
||||||
filename: quest_file_request.filename,
|
|
||||||
blob: subblob,
|
|
||||||
blob_length: blob_length as u32,
|
|
||||||
unknown: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Box::new(vec![(id, SendShipPacket::QuestChunk(qc))].into_iter()))
|
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))?;
|
}).ok_or(ShipError::InvalidQuest(quest_id as u32))?;
|
||||||
|
|
||||||
let blob = match datatype {
|
let blob = match datatype {
|
||||||
DATATYPE_BIN => &quest.bin_blob,
|
QuestFileType::Bin => &quest.bin_blob,
|
||||||
DATATYPE_DAT => &quest.dat_blob,
|
QuestFileType::Dat => &quest.dat_blob,
|
||||||
_ => panic!()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut blob_cursor = Cursor::new(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 {
|
if blob_length == 0 {
|
||||||
return Ok(Box::new(None.into_iter()));
|
return Ok(Box::new(None.into_iter()));
|
||||||
}
|
}
|
||||||
let qc = QuestChunk {
|
let qc = quest::quest_chunk(quest_chunk_ack.chunk_num + 1, quest_chunk_ack.filename, subblob, blob_length);
|
||||||
chunk_num: quest_chunk_ack.chunk_num + 1,
|
|
||||||
filename: quest_chunk_ack.filename,
|
|
||||||
blob: subblob,
|
|
||||||
blob_length: blob_length as u32,
|
|
||||||
unknown: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Box::new(vec![(id, SendShipPacket::QuestChunk(qc))].into_iter()))
|
Ok(Box::new(vec![(id, SendShipPacket::QuestChunk(qc))].into_iter()))
|
||||||
}
|
}
|
||||||
|
@ -133,7 +133,7 @@ fn parse_dat(dat: &[u8], episode: &Episode) -> Result<(Vec<Option<MapEnemy>>, Ve
|
|||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
#[error("")]
|
#[error("")]
|
||||||
enum QuestLoadError {
|
pub enum QuestLoadError {
|
||||||
ParseDatError(#[from] ParseDatError),
|
ParseDatError(#[from] ParseDatError),
|
||||||
CouldNotReadMetadata,
|
CouldNotReadMetadata,
|
||||||
CouldNotLoadConfigFile,
|
CouldNotLoadConfigFile,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user