use psopacket::{pso_packet, PSOPacketData}; use crate::{PSOPacket, PacketParseError, PSOPacketData}; use crate::utf8_to_utf16_array; use crate::packet::messages::GameMessage; //use character::character::FullCharacter; use crate::character::character as character; use std::io::Read; const BLOCK_MENU_ID: u32 = 1; #[pso_packet(0x03)] pub struct ShipWelcome { #[utf8] copyright: [u8; 0x60], server_key: [u8; 48], client_key: [u8; 48], } impl ShipWelcome { pub fn new(server_key: [u8; 48], client_key: [u8; 48]) -> ShipWelcome { let mut copyright = [0u8; 0x60]; copyright[..0x4B].clone_from_slice(b"Phantasy Star Online Blue Burst Game Server. Copyright 1999-2004 SONICTEAM."); ShipWelcome { copyright: copyright, server_key: server_key, client_key: client_key, } } } #[derive(Debug, PartialEq, Clone)] pub struct BlockEntry { menu: u32, item: u32, flags: u16, name: [u16; 0x11], } impl PSOPacketData for BlockEntry { fn from_bytes(_cursor: &mut R) -> Result { unimplemented!(); } 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 } } #[pso_packet(0xA1)] pub struct ShipBlockList { shipblock: BlockEntry, blocks: Vec } impl ShipBlockList { pub fn new(shipname: &str, num_blocks: usize) -> ShipBlockList { ShipBlockList { shipblock: BlockEntry { menu: BLOCK_MENU_ID, item: 0, flags: 0, name: utf8_to_utf16_array!(shipname, 0x11) }, blocks: (0..num_blocks).map(|i| BlockEntry { menu: BLOCK_MENU_ID, item: i as u32 + 1, flags: 0, name: utf8_to_utf16_array!(format!("Block {}", i+1), 0x11) }).collect() } } } // TODO: menu should be an enum // TODO: or perhaps MenuSelect should be broken up into different structs based on menu // TODO: i.e. ShipMenuSelect, BlockMenuSelect, etc #[pso_packet(0x10)] pub struct MenuSelect { pub menu: u32, pub item: u32, } #[pso_packet(0xE7)] pub struct FullCharacter { #[no_debug] character: character::FullCharacter, } #[pso_packet(0x95)] pub struct CharDataRequest { } // TODO: what does this even do? #[pso_packet(0x61)] pub struct CharData { _unknown: [u8; 0x828] } #[pso_packet(0x60)] pub struct Message { msg: GameMessage, } impl Message { pub fn new(msg: GameMessage) -> Message { Message { msg: msg, } } } #[pso_packet(0x62, manual_flag)] pub struct DirectMessage { flag: u32, msg: GameMessage } impl DirectMessage { pub fn new(target: u32, msg: GameMessage) -> DirectMessage { DirectMessage { flag: target, msg: msg, } } } #[derive(PSOPacketData, Clone, Copy, Default)] pub struct PlayerHeader { pub tag: u32, pub guildcard: u32, pub _unknown1: [u32; 5], pub client_id: u32, pub name: [u16; 16], pub _unknown2: u32, } #[derive(PSOPacketData, Clone)] pub struct PlayerInfo { pub header: PlayerHeader, pub inventory: character::Inventory, pub character: character::Character, } #[pso_packet(0x67)] pub struct JoinLobby { pub client: u8, pub leader: u8, pub one: u8, pub lobby: u8, pub block: u16, pub event: u16, pub padding: u32, pub playerinfo: Vec, } #[pso_packet(0x68, manual_flag)] pub struct AddToLobby { flag: u32, pub client: u8, pub leader: u8, pub one: u8, pub lobby: u8, pub block: u16, pub event: u16, pub padding: u32, pub playerinfo: PlayerInfo, } #[pso_packet(0xC1)] pub struct CreateRoom { unknown: [u32; 2], name: [u16; 16], password: [u16; 16], difficulty: u8, battle: u8, challenge: u8, episode: u8, single_player: u8, padding: [u8; 3], } #[pso_packet(0x01)] pub struct SmallDialog { msg: String, } impl SmallDialog { pub fn new(msg: String) -> SmallDialog { SmallDialog { msg: msg, } } } #[pso_packet(0x64, manual_flag)] pub struct JoinRoom { flag: u32, // # of elements in players maps: [u32; 0x20], players: [PlayerHeader; 4], client_id: u8, leader_id: u8, one: u8, difficulty: u8, // TODO: enum battle: u8, event: u8, section: u8, challenge: u8, random_seed: u32, episode: u8, one2: u8, single_player: u8, unknown: u8, } impl JoinRoom { /*fn new() -> JoinRoom { JoinRoom { } }*/ } #[pso_packet(0x65, manual_flag)] pub struct AddToRoom { flag: u32, pub client: u8, pub leader: u8, pub one: u8, pub lobby: u8, pub block: u16, pub event: u16, pub padding: u32, pub playerinfo: PlayerInfo, }