2019-11-10 21:43:02 -08:00
|
|
|
use std::io::{Seek, SeekFrom};
|
|
|
|
|
|
|
|
use psopacket::pso_message;
|
|
|
|
use crate::{PSOPacketData, PacketParseError};
|
|
|
|
|
|
|
|
|
|
|
|
pub trait PSOMessage {
|
|
|
|
const CMD: u8;
|
|
|
|
fn from_bytes<R: std::io::Read + std::io::Seek>(cur: &mut R) -> Result<Self, PacketParseError> where Self: Sized;
|
|
|
|
fn as_bytes(&self) -> Vec<u8>;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[pso_message(0x40)]
|
|
|
|
pub struct PlayerWalking {
|
|
|
|
x: f32,
|
|
|
|
y: f32,
|
|
|
|
z: f32,
|
|
|
|
}
|
|
|
|
|
2019-12-11 23:32:11 -08:00
|
|
|
#[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,
|
|
|
|
}
|
|
|
|
|
2019-12-15 23:14:17 -08:00
|
|
|
#[pso_message(0x20)]
|
|
|
|
pub struct TellOtherPlayerMyLocation {
|
|
|
|
unknown1: u32,
|
|
|
|
unknown2: u32,
|
|
|
|
x: f32,
|
|
|
|
y: f32,
|
|
|
|
z: f32,
|
|
|
|
}
|
2019-12-11 23:32:11 -08:00
|
|
|
|
|
|
|
#[pso_message(0x3F)]
|
|
|
|
pub struct PlayerLoadedIn {
|
|
|
|
unknown1: u32,
|
|
|
|
unknown2: u32,
|
|
|
|
x: f32,
|
|
|
|
y: f32,
|
|
|
|
z: f32,
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[pso_message(0x23)]
|
|
|
|
pub struct PlayerDoneChangingMap {
|
2020-02-14 23:31:43 -04:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#[pso_message(0x75)]
|
|
|
|
pub struct PlayerChangedFloor {
|
|
|
|
map: u32,
|
2019-12-11 23:32:11 -08:00
|
|
|
}
|
|
|
|
|
2020-02-14 23:31:43 -04:00
|
|
|
|
2019-12-18 21:52:21 -08:00
|
|
|
#[pso_message(0x52)]
|
|
|
|
pub struct TalkToNpc {
|
|
|
|
unknown1: u32,
|
|
|
|
unknown2: u32,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[pso_message(0x58)]
|
|
|
|
pub struct LobbyEmote {
|
|
|
|
emote: u32,
|
|
|
|
}
|
2019-11-10 21:43:02 -08:00
|
|
|
|
2019-12-15 23:14:17 -08:00
|
|
|
#[pso_message(0xAE)]
|
|
|
|
pub struct UnknownAE {
|
|
|
|
unknown1: u32,
|
|
|
|
unknown2: u32,
|
|
|
|
unknown3: u32,
|
|
|
|
}
|
|
|
|
|
2020-01-09 23:21:15 -04:00
|
|
|
#[pso_message(0xAB)]
|
|
|
|
pub struct PhotonChairSit {
|
|
|
|
unknown1: u32,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[pso_message(0xAF)]
|
|
|
|
pub struct PhotonChairTurn {
|
|
|
|
unknown1: u32,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[pso_message(0xB0)]
|
|
|
|
pub struct PhotonChairMove {
|
|
|
|
unknown1: u32,
|
|
|
|
}
|
|
|
|
|
2020-01-15 01:05:03 -04:00
|
|
|
#[pso_message(0x3B)]
|
2020-02-14 23:31:43 -04:00
|
|
|
pub struct PlayerSpawnedIntoArea {
|
2020-01-15 01:05:03 -04:00
|
|
|
|
|
|
|
}
|
2019-12-15 23:14:17 -08:00
|
|
|
|
2020-01-29 20:13:27 -08:00
|
|
|
#[pso_message(0xC8)]
|
|
|
|
pub struct RequestExp {
|
|
|
|
enemy_id: u16,
|
|
|
|
client_id: u8,
|
|
|
|
unused: u8,
|
|
|
|
last_hitter: u32,
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[pso_message(0x60)]
|
|
|
|
pub struct RequestItem {
|
|
|
|
area: u8,
|
|
|
|
pt_index: u8,
|
|
|
|
enemy_id: u16,
|
|
|
|
x: f32,
|
|
|
|
z: f32,
|
|
|
|
y: f32,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[pso_message(0x76)]
|
|
|
|
pub struct KillMonster {
|
|
|
|
_unknown: [u8; 4],
|
|
|
|
}
|
|
|
|
|
2020-02-14 23:31:43 -04:00
|
|
|
#[pso_message(0x43)]
|
|
|
|
pub struct ComboStep1 {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#[pso_message(0x44)]
|
|
|
|
pub struct ComboStep2 {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#[pso_message(0x45)]
|
|
|
|
pub struct ComboStep3 {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#[pso_message(0x46)]
|
|
|
|
pub struct ComboStepDone {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#[pso_message(0x8D)]
|
|
|
|
pub struct PlayerTechStart {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#[pso_message(0x47)]
|
|
|
|
pub struct PlayerTechCast {
|
|
|
|
technique: u8,
|
|
|
|
unknown1: u8,
|
|
|
|
unknown2: u8,
|
|
|
|
num_of_targets: u8,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[pso_message(0x48)]
|
|
|
|
pub struct PlayerTechDone {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#[pso_message(0x0A)]
|
|
|
|
pub struct MobAttack {
|
|
|
|
|
|
|
|
}
|
2020-01-29 20:13:27 -08:00
|
|
|
|
2020-02-14 23:31:43 -04:00
|
|
|
#[pso_message(0x4A)]
|
|
|
|
pub struct PlayerBlockedDamage {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[pso_message(0x83)]
|
|
|
|
pub struct PlayerTrapSet {
|
|
|
|
trap_type: u16,
|
|
|
|
trap_count: u16,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[pso_message(0x80)]
|
|
|
|
pub struct PlayerTrapActivate {
|
|
|
|
|
|
|
|
}
|
2020-01-29 20:13:27 -08:00
|
|
|
|
2020-03-22 22:17:52 -03:00
|
|
|
#[pso_message(0x06)]
|
|
|
|
pub struct GuildcardSend {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#[pso_message(0x06)]
|
|
|
|
pub struct GuildcardRecv {
|
|
|
|
guildcard: u32,
|
|
|
|
name: [u16; 0x18],
|
|
|
|
team: [u16; 0x10],
|
|
|
|
desc: [u16; 0x58],
|
|
|
|
one: u8,
|
|
|
|
language: u8,
|
|
|
|
section_id: u8,
|
|
|
|
class: u8,
|
|
|
|
}
|
|
|
|
|
2019-12-15 23:14:17 -08:00
|
|
|
|
2019-11-16 23:13:36 -08:00
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
|
|
pub enum GameMessage {
|
2019-11-10 21:43:02 -08:00
|
|
|
PlayerWalking(PlayerWalking),
|
2019-12-11 23:32:11 -08:00
|
|
|
PlayerRunning(PlayerRunning),
|
|
|
|
PlayerStopped(PlayerStopped),
|
|
|
|
PlayerLoadedIn(PlayerLoadedIn),
|
|
|
|
PlayerChangedMap(PlayerChangedMap),
|
|
|
|
PlayerChangedMap2(PlayerChangedMap2),
|
|
|
|
PlayerDoneChangingMap(PlayerDoneChangingMap),
|
2020-02-14 23:31:43 -04:00
|
|
|
PlayerChangedFloor(PlayerChangedFloor),
|
2019-12-15 23:14:17 -08:00
|
|
|
TellOtherPlayerMyLocation(TellOtherPlayerMyLocation),
|
2019-12-18 21:52:21 -08:00
|
|
|
LobbyEmote(LobbyEmote),
|
|
|
|
TalkToNpc(TalkToNpc),
|
2019-12-15 23:14:17 -08:00
|
|
|
UnknownAE(UnknownAE),
|
2020-01-09 23:21:15 -04:00
|
|
|
PhotonChairSit(PhotonChairSit),
|
|
|
|
PhotonChairTurn(PhotonChairTurn),
|
|
|
|
PhotonChairMove(PhotonChairMove),
|
2020-02-14 23:31:43 -04:00
|
|
|
PlayerSpawnedIntoArea(PlayerSpawnedIntoArea),
|
2020-01-31 11:58:24 -08:00
|
|
|
RequestExp(RequestExp),
|
|
|
|
RequestItem(RequestItem),
|
|
|
|
KillMonster(KillMonster),
|
2020-02-14 23:31:43 -04:00
|
|
|
ComboStep1(ComboStep1),
|
|
|
|
ComboStep2(ComboStep2),
|
|
|
|
ComboStep3(ComboStep3),
|
|
|
|
ComboStepDone(ComboStepDone),
|
|
|
|
PlayerTechStart(PlayerTechStart),
|
|
|
|
PlayerTechCast(PlayerTechCast),
|
|
|
|
PlayerTechDone(PlayerTechDone),
|
|
|
|
MobAttack(MobAttack),
|
|
|
|
PlayerBlockedDamage(PlayerBlockedDamage),
|
|
|
|
PlayerTrapSet(PlayerTrapSet),
|
|
|
|
PlayerTrapActivate(PlayerTrapActivate),
|
2020-03-22 22:17:52 -03:00
|
|
|
GuildcardSend(GuildcardSend),
|
|
|
|
GuildcardRecv(GuildcardRecv),
|
2019-11-10 21:43:02 -08:00
|
|
|
}
|
|
|
|
|
2019-11-16 23:13:36 -08:00
|
|
|
impl PSOPacketData for GameMessage {
|
2019-11-10 21:43:02 -08:00
|
|
|
fn from_bytes<R: std::io::Read + std::io::Seek>(mut cur: &mut R) -> Result<Self, PacketParseError> {
|
|
|
|
let mut byte = [0u8; 1];
|
2019-12-11 23:32:11 -08:00
|
|
|
let mut len = [0u8; 1];
|
2019-11-10 21:43:02 -08:00
|
|
|
cur.read(&mut byte);
|
2019-12-11 23:32:11 -08:00
|
|
|
cur.read(&mut len);
|
|
|
|
cur.seek(SeekFrom::Current(-2)); // Cursor doesn't implement Peek?
|
2019-11-10 21:43:02 -08:00
|
|
|
match byte[0] {
|
2019-11-16 23:13:36 -08:00
|
|
|
PlayerWalking::CMD => Ok(GameMessage::PlayerWalking(PlayerWalking::from_bytes(&mut cur)?)),
|
2019-12-11 23:32:11 -08:00
|
|
|
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)?)),
|
2020-02-14 23:31:43 -04:00
|
|
|
PlayerChangedFloor::CMD => Ok(GameMessage::PlayerChangedFloor(PlayerChangedFloor::from_bytes(&mut cur)?)),
|
2019-12-15 23:14:17 -08:00
|
|
|
TellOtherPlayerMyLocation::CMD => Ok(GameMessage::TellOtherPlayerMyLocation(TellOtherPlayerMyLocation::from_bytes(&mut cur)?)),
|
2019-12-18 21:52:21 -08:00
|
|
|
LobbyEmote::CMD => Ok(GameMessage::LobbyEmote(LobbyEmote::from_bytes(&mut cur)?)),
|
|
|
|
TalkToNpc::CMD => Ok(GameMessage::TalkToNpc(TalkToNpc::from_bytes(&mut cur)?)),
|
2019-12-15 23:14:17 -08:00
|
|
|
UnknownAE::CMD => Ok(GameMessage::UnknownAE(UnknownAE::from_bytes(&mut cur)?)),
|
2020-01-09 23:21:15 -04:00
|
|
|
PhotonChairSit::CMD => Ok(GameMessage::PhotonChairSit(PhotonChairSit::from_bytes(&mut cur)?)),
|
|
|
|
PhotonChairTurn::CMD => Ok(GameMessage::PhotonChairTurn(PhotonChairTurn::from_bytes(&mut cur)?)),
|
|
|
|
PhotonChairMove::CMD => Ok(GameMessage::PhotonChairMove(PhotonChairMove::from_bytes(&mut cur)?)),
|
2020-02-14 23:31:43 -04:00
|
|
|
PlayerSpawnedIntoArea::CMD => Ok(GameMessage::PlayerSpawnedIntoArea(PlayerSpawnedIntoArea::from_bytes(&mut cur)?)),
|
2020-01-31 11:58:24 -08:00
|
|
|
RequestExp::CMD => Ok(GameMessage::RequestExp(RequestExp::from_bytes(&mut cur)?)),
|
|
|
|
RequestItem::CMD => Ok(GameMessage::RequestItem(RequestItem::from_bytes(&mut cur)?)),
|
|
|
|
KillMonster::CMD => Ok(GameMessage::KillMonster(KillMonster::from_bytes(&mut cur)?)),
|
2020-02-14 23:31:43 -04:00
|
|
|
ComboStep1::CMD => Ok(GameMessage::ComboStep1(ComboStep1::from_bytes(&mut cur)?)),
|
|
|
|
ComboStep2::CMD => Ok(GameMessage::ComboStep2(ComboStep2::from_bytes(&mut cur)?)),
|
|
|
|
ComboStep3::CMD => Ok(GameMessage::ComboStep3(ComboStep3::from_bytes(&mut cur)?)),
|
|
|
|
ComboStepDone::CMD => Ok(GameMessage::ComboStepDone(ComboStepDone::from_bytes(&mut cur)?)),
|
|
|
|
PlayerTechStart::CMD => Ok(GameMessage::PlayerTechStart(PlayerTechStart::from_bytes(&mut cur)?)),
|
|
|
|
PlayerTechCast::CMD => Ok(GameMessage::PlayerTechCast(PlayerTechCast::from_bytes(&mut cur)?)),
|
|
|
|
PlayerTechDone::CMD => Ok(GameMessage::PlayerTechDone(PlayerTechDone::from_bytes(&mut cur)?)),
|
|
|
|
MobAttack::CMD => Ok(GameMessage::MobAttack(MobAttack::from_bytes(&mut cur)?)),
|
|
|
|
PlayerBlockedDamage::CMD => Ok(GameMessage::PlayerBlockedDamage(PlayerBlockedDamage::from_bytes(&mut cur)?)),
|
|
|
|
PlayerTrapSet::CMD => Ok(GameMessage::PlayerTrapSet(PlayerTrapSet::from_bytes(&mut cur)?)),
|
|
|
|
PlayerTrapActivate::CMD => Ok(GameMessage::PlayerTrapActivate(PlayerTrapActivate::from_bytes(&mut cur)?)),
|
2020-03-22 22:17:52 -03:00
|
|
|
GuildcardSend::CMD => Ok(GameMessage::GuildcardSend(GuildcardSend::from_bytes(&mut cur)?)),
|
|
|
|
GuildcardRecv::CMD => Ok(GameMessage::GuildcardRecv(GuildcardRecv::from_bytes(&mut cur)?)),
|
2019-12-18 21:05:58 -08:00
|
|
|
_ => Err(PacketParseError::UnknownMessage(byte[0],
|
|
|
|
{
|
|
|
|
let mut b = vec![0; len[0] as usize * 4];
|
|
|
|
cur.read(&mut b).unwrap();
|
|
|
|
b.to_vec()
|
|
|
|
}
|
|
|
|
)),
|
2019-11-10 21:43:02 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
fn as_bytes(&self) -> Vec<u8> {
|
2019-11-16 23:13:36 -08:00
|
|
|
match self {
|
|
|
|
GameMessage::PlayerWalking(data) => data.as_bytes(),
|
2019-12-11 23:32:11 -08:00
|
|
|
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(),
|
2019-12-15 23:14:17 -08:00
|
|
|
GameMessage::TellOtherPlayerMyLocation(data) => data.as_bytes(),
|
2019-12-18 21:52:21 -08:00
|
|
|
GameMessage::LobbyEmote(data) => data.as_bytes(),
|
|
|
|
GameMessage::TalkToNpc(data) => data.as_bytes(),
|
2019-12-15 23:14:17 -08:00
|
|
|
GameMessage::UnknownAE(data) => data.as_bytes(),
|
2020-01-09 23:21:15 -04:00
|
|
|
GameMessage::PhotonChairSit(data) => data.as_bytes(),
|
|
|
|
GameMessage::PhotonChairTurn(data) => data.as_bytes(),
|
|
|
|
GameMessage::PhotonChairMove(data) => data.as_bytes(),
|
2020-02-14 23:31:43 -04:00
|
|
|
GameMessage::PlayerSpawnedIntoArea(data) => data.as_bytes(),
|
2020-01-31 11:58:24 -08:00
|
|
|
GameMessage::RequestExp(data) => data.as_bytes(),
|
|
|
|
GameMessage::RequestItem(data) => data.as_bytes(),
|
|
|
|
GameMessage::KillMonster(data) => data.as_bytes(),
|
2020-02-14 23:31:43 -04:00
|
|
|
GameMessage::ComboStep1(data) => data.as_bytes(),
|
|
|
|
GameMessage::ComboStep2(data) => data.as_bytes(),
|
|
|
|
GameMessage::ComboStep3(data) => data.as_bytes(),
|
|
|
|
GameMessage::ComboStepDone(data) => data.as_bytes(),
|
|
|
|
GameMessage::PlayerTechStart(data) => data.as_bytes(),
|
|
|
|
GameMessage::PlayerTechCast(data) => data.as_bytes(),
|
|
|
|
GameMessage::PlayerTechDone(data) => data.as_bytes(),
|
|
|
|
GameMessage::MobAttack(data) => data.as_bytes(),
|
|
|
|
GameMessage::PlayerBlockedDamage(data) => data.as_bytes(),
|
|
|
|
GameMessage::PlayerTrapSet(data) => data.as_bytes(),
|
|
|
|
GameMessage::PlayerTrapActivate(data) => data.as_bytes(),
|
|
|
|
GameMessage::PlayerChangedFloor(data) => data.as_bytes(),
|
2020-03-22 22:17:52 -03:00
|
|
|
GameMessage::GuildcardSend(data) => data.as_bytes(),
|
|
|
|
GameMessage::GuildcardRecv(data) => data.as_bytes(),
|
2019-11-16 23:13:36 -08:00
|
|
|
}
|
2019-11-10 21:43:02 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|