use std::io::{Seek, SeekFrom}; use psopacket::pso_message; use crate::{PSOPacketData, PacketParseError}; pub trait PSOMessage { const CMD: u8; fn from_bytes(cur: &mut R) -> Result where Self: Sized; fn as_bytes(&self) -> Vec; } #[pso_message(0x40)] pub struct PlayerWalking { x: f32, y: f32, z: f32, } #[pso_message(0x42)] pub struct PlayerRunning { x: f32, z: f32, } #[pso_message(0x3E)] pub struct PlayerStopped { unknown1: u32, unknown2: u32, x: f32, y: f32, z: f32, } #[pso_message(0x1F)] pub struct PlayerChangedMap { unknown1: u32, unknown2: u32, x: f32, y: f32, z: f32, } #[pso_message(0x1F)] pub struct PlayerChangedMap2 { unknown1: u32, } #[pso_message(0x3F)] pub struct PlayerLoadedIn { unknown1: u32, unknown2: u32, x: f32, y: f32, z: f32, } #[pso_message(0x23)] pub struct PlayerDoneChangingMap { } #[derive(Debug, Clone, PartialEq)] pub enum GameMessage { PlayerWalking(PlayerWalking), PlayerRunning(PlayerRunning), PlayerStopped(PlayerStopped), PlayerLoadedIn(PlayerLoadedIn), PlayerChangedMap(PlayerChangedMap), PlayerChangedMap2(PlayerChangedMap2), PlayerDoneChangingMap(PlayerDoneChangingMap), } impl PSOPacketData for GameMessage { fn from_bytes(mut cur: &mut R) -> Result { let mut byte = [0u8; 1]; let mut len = [0u8; 1]; cur.read(&mut byte); cur.read(&mut len); cur.seek(SeekFrom::Current(-2)); // Cursor doesn't implement Peek? match byte[0] { PlayerWalking::CMD => Ok(GameMessage::PlayerWalking(PlayerWalking::from_bytes(&mut cur)?)), PlayerRunning::CMD => Ok(GameMessage::PlayerRunning(PlayerRunning::from_bytes(&mut cur)?)), PlayerStopped::CMD => Ok(GameMessage::PlayerStopped(PlayerStopped::from_bytes(&mut cur)?)), PlayerLoadedIn::CMD => Ok(GameMessage::PlayerLoadedIn(PlayerLoadedIn::from_bytes(&mut cur)?)), PlayerChangedMap::CMD if len[0] == 6 => Ok(GameMessage::PlayerChangedMap(PlayerChangedMap::from_bytes(&mut cur)?)), PlayerChangedMap2::CMD if len[0] == 2 => Ok(GameMessage::PlayerChangedMap2(PlayerChangedMap2::from_bytes(&mut cur)?)), PlayerDoneChangingMap::CMD => Ok(GameMessage::PlayerDoneChangingMap(PlayerDoneChangingMap::from_bytes(&mut cur)?)), _ => Err(PacketParseError::WrongPacketCommand), } } fn as_bytes(&self) -> Vec { match self { GameMessage::PlayerWalking(data) => data.as_bytes(), GameMessage::PlayerRunning(data) => data.as_bytes(), GameMessage::PlayerStopped(data) => data.as_bytes(), GameMessage::PlayerLoadedIn(data) => data.as_bytes(), GameMessage::PlayerChangedMap(data) => data.as_bytes(), GameMessage::PlayerChangedMap2(data) => data.as_bytes(), GameMessage::PlayerDoneChangingMap(data) => data.as_bytes(), } } }