diff --git a/src/packet/login.rs b/src/packet/login.rs index edb2339..7e0cb39 100644 --- a/src/packet/login.rs +++ b/src/packet/login.rs @@ -1,7 +1,8 @@ use chrono::{DateTime, Utc}; -use psopacket::pso_packet; -use crate::{PSOPacket, PacketParseError}; +//use psopacket::pso_packet; +use psopacket::pso_packet2 as pso_packet; +use crate::{PSOPacket, PacketParseError, PSOPacketData}; use crate::character::character::SelectScreenCharacter; @@ -11,13 +12,10 @@ pub const PATCH_FILE_CHUNK_SIZE: u16 = 0x8000; // 32kb pub const GUILD_CARD_CHUNK_SIZE: usize = 0x6800; pub const PARAM_DATA_CHUNK_SIZE: usize = 0x6800; -#[allow(non_camel_case_types)] -type u8_str = u8; - #[pso_packet(0x03)] pub struct LoginWelcome { - flag: u32, - copyright: [u8_str; 0x60], + #[utf8] + copyright: [u8; 0x60], server_key: [u8; 48], client_key: [u8; 48], } @@ -27,7 +25,6 @@ impl LoginWelcome { let mut copyright = [0u8; 0x60]; copyright[..0x4B].clone_from_slice(b"Phantasy Star Online Blue Burst Game Server. Copyright 1999-2004 SONICTEAM."); LoginWelcome { - flag: 0, copyright: copyright, server_key: server_key, client_key: client_key, @@ -37,15 +34,16 @@ impl LoginWelcome { #[pso_packet(0x93)] pub struct Login { - pub flag: u32, pub tag: u32, pub guildcard: u32, pub version: u16, pub unknown1: [u8; 6], pub team: u32, - pub username: [u8_str; 16], + #[utf8] + pub username: [u8; 16], pub unknown2: [u8; 32], - pub password: [u8_str; 16], + #[utf8] + pub password: [u8; 16], pub unknown3: [u8; 40], pub hwinfo: [u8; 8], pub security_data: [u8; 40], @@ -67,27 +65,10 @@ pub enum AccountStatus { BadVersion, } -impl AccountStatus { - const SIZE: usize = 4; - - fn to_le_bytes(&self) -> [u8; 4] { - [match self { - AccountStatus::Ok => 0, - AccountStatus::Error => 1, - AccountStatus::InvalidPassword => 2, - AccountStatus::InvalidPassword2 => 3, - AccountStatus::Maintenance => 4, - AccountStatus::AlreadyOnline => 5, - AccountStatus::Banned => 6, - AccountStatus::Banned2 => 7, - AccountStatus::InvalidUser => 8, - AccountStatus::PayUp => 9, - AccountStatus::Locked => 10, - AccountStatus::BadVersion => 11, - },0,0,0] - } - - fn from_le_bytes(bytes: [u8; 4]) -> Result { +impl PSOPacketData for AccountStatus { + fn from_bytes(cursor: &mut R) -> Result { + let mut bytes = [0u8; 4]; + cursor.read(&mut bytes).map_err(|_| PacketParseError::ReadError)?; match bytes[0] { 0 => Ok(AccountStatus::Ok), 1 => Ok(AccountStatus::Error), @@ -104,12 +85,28 @@ impl AccountStatus { _ => Err(PacketParseError::InvalidValue), } } - + + fn as_bytes(&self) -> Vec { + vec![match self { + AccountStatus::Ok => 0, + AccountStatus::Error => 1, + AccountStatus::InvalidPassword => 2, + AccountStatus::InvalidPassword2 => 3, + AccountStatus::Maintenance => 4, + AccountStatus::AlreadyOnline => 5, + AccountStatus::Banned => 6, + AccountStatus::Banned2 => 7, + AccountStatus::InvalidUser => 8, + AccountStatus::PayUp => 9, + AccountStatus::Locked => 10, + AccountStatus::BadVersion => 11, + },0,0,0] + } } + #[pso_packet(0xE6)] pub struct LoginResponse { - pub flag: u32, pub status: AccountStatus, pub tag: u32, pub guildcard: u32, @@ -121,7 +118,6 @@ pub struct LoginResponse { impl LoginResponse { pub fn by_status(status: AccountStatus, security_data: [u8; 40]) -> LoginResponse { LoginResponse { - flag: 0, status: status, tag: 0x00010000, //tag: 0x00000100, @@ -133,7 +129,6 @@ impl LoginResponse { } pub fn by_char_select(guildcard: u32, team_id: u32, security_data: [u8; 40]) -> LoginResponse { LoginResponse { - flag: 0, status: AccountStatus::Ok, tag: 0x00010000, //tag: 0x00000100, @@ -148,12 +143,10 @@ impl LoginResponse { #[pso_packet(0xE0)] pub struct RequestSettings { - pub flag: u32 } #[pso_packet(0xE2)] pub struct SendKeyAndTeamSettings { - flag: u32, unknown: [u8; 0x114], key_config: [u8; 0x16C], joystick_config: [u8; 0x38], @@ -165,6 +158,7 @@ pub struct SendKeyAndTeamSettings { unknown2: u16, //team_name: [u16; 16], team_name: [u8; 32], + #[nodebug] team_flag: [u8; 2048], team_rewards: [u8; 8], } @@ -172,7 +166,6 @@ pub struct SendKeyAndTeamSettings { impl SendKeyAndTeamSettings { pub fn new(key_config: [u8; 0x16C], joystick_config: [u8; 0x38], guildcard: u32, team_id: u32) -> SendKeyAndTeamSettings { SendKeyAndTeamSettings { - flag: 0, unknown: [0; 0x114], key_config: key_config, joystick_config: joystick_config, @@ -192,7 +185,6 @@ impl SendKeyAndTeamSettings { #[pso_packet(0x19)] pub struct RedirectClient { - pub flag: u32, pub ip: u32, pub port: u16, pub padding: u16, @@ -201,7 +193,6 @@ pub struct RedirectClient { impl RedirectClient { pub fn new(ip: u32, port: u16) -> RedirectClient { RedirectClient { - flag: 0, ip: ip, port: port, padding: 0, @@ -211,21 +202,18 @@ impl RedirectClient { #[pso_packet(0x1E8)] pub struct Checksum { - pub flag: u32, pub checksum: u32, pub padding: u32, } #[pso_packet(0x2E8)] pub struct ChecksumAck { - pub flag: u32, pub ack: u32, } impl ChecksumAck { pub fn new(ack: u32) -> ChecksumAck { ChecksumAck { - flag: 0, ack: ack, } } @@ -233,34 +221,40 @@ impl ChecksumAck { #[pso_packet(0xE3)] pub struct CharSelect { - pub flag: u32, pub slot: u32, pub reason: u32, // TODO: enum? } #[pso_packet(0xE4)] pub struct CharAck { - pub flag: u32, pub slot: u32, pub code: u32, // TODO: enum? } +impl PSOPacketData for SelectScreenCharacter { + fn from_bytes(cursor: &mut R) -> Result { + let mut buf = [0u8; SelectScreenCharacter::SIZE]; + cursor.read(&mut buf).map_err(|_| PacketParseError::ReadError)?; + SelectScreenCharacter::from_le_bytes(buf) + } + + fn as_bytes(&self) -> Vec { + self.to_le_bytes().to_vec() + } +} #[pso_packet(0xE5)] pub struct CharacterPreview { - pub flag: u32, pub slot: u32, pub character: SelectScreenCharacter, } #[pso_packet(0x3E8)] pub struct GuildcardDataRequest { - flag: u32, } #[pso_packet(0x1DC)] pub struct GuildcardDataHeader { - flag: u32, one: u32, len: u32, checksum: u32, @@ -269,7 +263,6 @@ pub struct GuildcardDataHeader { impl GuildcardDataHeader { pub fn new(len: usize, checksum: u32) -> GuildcardDataHeader { GuildcardDataHeader { - flag: 0, one: 1, len: len as u32, checksum: checksum @@ -279,14 +272,12 @@ impl GuildcardDataHeader { #[pso_packet(0x3DC)] pub struct GuildcardDataChunkRequest { - flag: u32, _unknown: u32, pub chunk: u32, pub again: u32, } pub struct GuildcardDataChunk { - flag: u32, _unknown: u32, chunk: u32, pub buffer: [u8; GUILD_CARD_CHUNK_SIZE], @@ -297,7 +288,6 @@ pub struct GuildcardDataChunk { impl GuildcardDataChunk { pub fn new(chunk: u32, buffer: [u8; GUILD_CARD_CHUNK_SIZE], len: usize) -> GuildcardDataChunk { GuildcardDataChunk { - flag: 0, _unknown: 0, chunk: chunk as u32, buffer: buffer, @@ -313,7 +303,7 @@ impl PSOPacket for GuildcardDataChunk { fn as_bytes(&self) -> Vec { let mut buf: Vec = Vec::new(); - buf.extend_from_slice(&u32::to_le_bytes(self.flag)); + buf.extend_from_slice(&u32::to_le_bytes(0)); buf.extend_from_slice(&u32::to_le_bytes(self._unknown)); buf.extend_from_slice(&u32::to_le_bytes(self.chunk)); buf.extend_from_slice(&self.buffer[0..self.len]); @@ -333,7 +323,7 @@ impl PSOPacket for GuildcardDataChunk { impl std::fmt::Debug for GuildcardDataChunk { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "packet GuildcardDataChunk {{\n").unwrap(); - write!(f, " flag: {:?}\n", self.flag).unwrap(); + write!(f, " flag: {:?}\n", 0).unwrap(); write!(f, " _unknown: {:X?}\n", self._unknown).unwrap(); write!(f, " chunk: {:X?}\n", self.chunk).unwrap(); write!(f, " buffer: [0..{:X}]\n", self.len).unwrap(); @@ -344,7 +334,6 @@ impl std::fmt::Debug for GuildcardDataChunk { #[pso_packet(0x4EB)] pub struct ParamDataRequest { - flag: u32, } #[derive(Clone)] @@ -398,27 +387,25 @@ impl std::fmt::Debug for ParamDataHeader { #[pso_packet(0x3EB)] pub struct ParamDataChunkRequest { - flag: u32, } #[pso_packet(0x2EB)] pub struct ParamDataChunk { - pub flag: u32, pub chunk: u32, + #[nodebug] pub data: [u8; 0x6800], // TODO: why wont the const work here? (blame macros?) } #[pso_packet(0xEC)] pub struct SetFlag { - flag: u32, pub flags: u32, } #[pso_packet(0xB1)] pub struct Timestamp { - flag: u32, + #[utf8] timestamp: [u8; 28], } @@ -429,7 +416,6 @@ impl Timestamp { let mut timebuf = [0u8; 28]; timebuf[..timebytes.len()].clone_from_slice(timebytes); Timestamp { - flag: 0, timestamp: timebuf } } @@ -444,8 +430,41 @@ pub struct ShipListEntry { pub name: [u16; 0x11], } +impl PSOPacketData for ShipListEntry { + fn from_bytes(cursor: &mut R) -> Result { + let mut buf4 = [0u8; 4]; + cursor.read(&mut buf4).map_err(|_| PacketParseError::ReadError)?; + let menu = u32::from_le_bytes(buf4); + cursor.read(&mut buf4).map_err(|_| PacketParseError::ReadError)?; + let item = u32::from_le_bytes(buf4); + + let mut buf2 = [0u8; 2]; + cursor.read(&mut buf2).map_err(|_| PacketParseError::ReadError)?; + let flags = u16::from_le_bytes(buf2); + + let mut name = [0u8; 0x11 * 2]; + cursor.read(&mut name).map_err(|_| PacketParseError::ReadError)?; + Ok(ShipListEntry { + menu: menu, + item: item, + flags: flags, + name: unsafe { std::mem::transmute(name)} + }) + } + + fn as_bytes(&self) -> Vec { + let mut bytes = Vec::new(); + bytes.extend_from_slice(&u32::to_le_bytes(self.menu)); + bytes.extend_from_slice(&u32::to_le_bytes(self.item)); + bytes.extend_from_slice(&u16::to_le_bytes(self.flags)); + bytes.extend_from_slice(&unsafe { std::mem::transmute::<[u16; 0x11], [u8; 0x11*2]>(self.name) }); + bytes + //self.to_le_bytes().to_vec() + } +} + + pub struct ShipList { - pub flag: u32, pub ships: Vec, } @@ -490,7 +509,7 @@ impl PSOPacket for ShipList { impl std::fmt::Debug for ShipList { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "packet ShipList {{\n").unwrap(); - write!(f, " flag: {:?}\n", self.flag).unwrap(); + write!(f, " flag: {:?}\n", 0).unwrap(); write!(f, " ships: {:?}]\n", self.ships).unwrap(); write!(f, "}}") } @@ -499,7 +518,6 @@ impl std::fmt::Debug for ShipList { #[pso_packet(0x10)] pub struct MenuSelect { - pub flag: u32, pub menu: u32, pub item: u32, } @@ -511,7 +529,6 @@ mod tests { fn test_account_status_enum() { use super::PSOPacket; let pkt = super::LoginResponse { - flag: 0, status: super::AccountStatus::InvalidPassword, tag: 0, guildcard: 0,