mirror of
https://github.com/redstrate/Kawari.git
synced 2025-04-24 08:07:45 +00:00
Add the remaining IPC opcodes to allow you to join a world
This commit is contained in:
parent
7b0c41a478
commit
68d87c3a42
2 changed files with 300 additions and 20 deletions
|
@ -1,6 +1,6 @@
|
|||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
use kawari::ipc::{ActorControlType, IPCOpCode, IPCSegment, IPCStructData, Position};
|
||||
use kawari::ipc::{ActorControlType, IPCOpCode, IPCSegment, IPCStructData, Position, StatusEffect};
|
||||
use kawari::oodle::FFXIVOodle;
|
||||
use kawari::packet::{
|
||||
CompressionType, PacketSegment, SegmentType, State, parse_packet, send_keep_alive, send_packet,
|
||||
|
@ -38,6 +38,15 @@ async fn main() {
|
|||
println!("recieved {n} bytes...");
|
||||
let (segments, connection_type) = parse_packet(&buf[..n], &mut state).await;
|
||||
for segment in &segments {
|
||||
let timestamp_secs = || {
|
||||
SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.expect("Failed to get UNIX timestamp!")
|
||||
.as_secs()
|
||||
.try_into()
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
match &segment.segment_type {
|
||||
SegmentType::InitializeSession { player_id } => {
|
||||
state.player_id = Some(*player_id);
|
||||
|
@ -147,15 +156,6 @@ async fn main() {
|
|||
"Client is now requesting zone information. Sending!"
|
||||
);
|
||||
|
||||
let timestamp_secs = || {
|
||||
SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.expect("Failed to get UNIX timestamp!")
|
||||
.as_secs()
|
||||
.try_into()
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
// IPC Init(?)
|
||||
{
|
||||
let ipc = IPCSegment {
|
||||
|
@ -502,19 +502,97 @@ async fn main() {
|
|||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
IPCStructData::FinishLoading { .. } => {
|
||||
tracing::info!(
|
||||
"Client has finished loading... spawning in!"
|
||||
);
|
||||
|
||||
// ?????
|
||||
/*{
|
||||
// send player spawn
|
||||
{
|
||||
let ipc = IPCSegment {
|
||||
unk1: 0,
|
||||
unk2: 0,
|
||||
op_code: IPCOpCode::InitRequest,
|
||||
op_code: IPCOpCode::PlayerSpawn,
|
||||
server_id: 0,
|
||||
timestamp: timestamp_secs(),
|
||||
data: IPCStructData::InitResponse {
|
||||
unk1: 0,
|
||||
character_id: state.player_id.unwrap(),
|
||||
unk2: 0,
|
||||
data: IPCStructData::PlayerSpawn {
|
||||
title: 0,
|
||||
u1b: 0,
|
||||
current_world_id: 0,
|
||||
home_world_id: 0,
|
||||
gm_rank: 0,
|
||||
u3c: 0,
|
||||
u4: 0,
|
||||
online_status: 0,
|
||||
pose: 0,
|
||||
u5a: 0,
|
||||
u5b: 0,
|
||||
u5c: 0,
|
||||
target_id: 0,
|
||||
u6: 0,
|
||||
u7: 0,
|
||||
main_weapon_model: 0,
|
||||
sec_weapon_model: 0,
|
||||
craft_tool_model: 0,
|
||||
u14: 0,
|
||||
u15: 0,
|
||||
b_npc_base: 0,
|
||||
b_npc_name: 0,
|
||||
u18: 0,
|
||||
u19: 0,
|
||||
director_id: 0,
|
||||
owner_id: 0,
|
||||
u22: 0,
|
||||
padding4: [0; 16],
|
||||
hp_max: 0,
|
||||
hp_curr: 0,
|
||||
display_flags: 0,
|
||||
fate_id: 0,
|
||||
mp_curr: 0,
|
||||
mp_max: 0,
|
||||
unk: 0,
|
||||
model_chara: 0,
|
||||
rotation: 0,
|
||||
current_mount: 0,
|
||||
active_minion: 0,
|
||||
u23: 0,
|
||||
u24: 0,
|
||||
u25: 0,
|
||||
u26: 0,
|
||||
spawn_index: 0,
|
||||
state: 0,
|
||||
persistent_emote: 0,
|
||||
model_type: 0,
|
||||
subtype: 0,
|
||||
voice: 0,
|
||||
enemy_type: 0,
|
||||
unk27: 0,
|
||||
level: 0,
|
||||
class_job: 0,
|
||||
unk28: 0,
|
||||
unk29: 0,
|
||||
unk30: 0,
|
||||
mount_head: 0,
|
||||
mount_body: 0,
|
||||
mount_feet: 0,
|
||||
mount_color: 0,
|
||||
scale: 0,
|
||||
element_data: [0; 6],
|
||||
padding2: [0; 12],
|
||||
effect: [StatusEffect::default(); 30],
|
||||
pos: Position {
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
z: 0.0,
|
||||
},
|
||||
models: [0; 10],
|
||||
unknown6_58: [0; 10],
|
||||
padding3: [0; 7],
|
||||
name: [0; 32],
|
||||
look: [0; 26],
|
||||
fc_tag: [0; 6],
|
||||
padding: [0; 26],
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -523,9 +601,41 @@ async fn main() {
|
|||
target_actor: state.player_id.unwrap(),
|
||||
segment_type: SegmentType::Ipc { data: ipc },
|
||||
};
|
||||
send_packet(&mut write, &[response_packet], &mut state, CompressionType::Oodle)
|
||||
send_packet(
|
||||
&mut write,
|
||||
&[response_packet],
|
||||
&mut state,
|
||||
CompressionType::Oodle,
|
||||
)
|
||||
.await;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
IPCStructData::Unk1 { .. } => {
|
||||
tracing::info!("Recieved Unk1!");
|
||||
}
|
||||
IPCStructData::Unk2 { .. } => {
|
||||
tracing::info!("Recieved Unk2!");
|
||||
}
|
||||
IPCStructData::Unk3 { .. } => {
|
||||
tracing::info!("Recieved Unk3!");
|
||||
}
|
||||
IPCStructData::Unk4 { .. } => {
|
||||
tracing::info!("Recieved Unk4!");
|
||||
}
|
||||
IPCStructData::SetSearchInfoHandler { .. } => {
|
||||
tracing::info!("Recieved SetSearchInfoHandler!");
|
||||
}
|
||||
IPCStructData::Unk5 { .. } => {
|
||||
tracing::info!("Recieved Unk5!");
|
||||
}
|
||||
IPCStructData::Unk6 { .. } => {
|
||||
tracing::info!("Recieved Unk6!");
|
||||
}
|
||||
IPCStructData::Unk7 { .. } => {
|
||||
tracing::info!("Recieved Unk7!");
|
||||
}
|
||||
IPCStructData::UpdatePositionHandler { .. } => {
|
||||
tracing::info!("Recieved UpdatePositionHandler!");
|
||||
}
|
||||
_ => panic!(
|
||||
"The server is recieving a IPC response or unknown packet!"
|
||||
|
|
170
src/ipc.rs
170
src/ipc.rs
|
@ -43,6 +43,27 @@ pub enum IPCOpCode {
|
|||
PlayerSetup = 0x006B,
|
||||
// Sent by the server to setup class info
|
||||
UpdateClassInfo = 0x006A,
|
||||
// Sent by the client when they're done loading and they need to be spawned in
|
||||
FinishLoading = 0x397, // TODO: assumed
|
||||
// Sent by the server to spawn the player in
|
||||
PlayerSpawn = 0x1AB,
|
||||
|
||||
// FIXME: 32 bytes of something from the client, not sure what yet
|
||||
Unk1 = 0x37C,
|
||||
// FIXME: 16 bytes of something from the client, not sure what yet
|
||||
Unk2 = 0x1A1,
|
||||
// FIXME: 8 bytes of something from the client, not sure what yet
|
||||
Unk3 = 0x326,
|
||||
// FIXME: 8 bytes of something from the client, not sure what yet
|
||||
Unk4 = 0x143,
|
||||
SetSearchInfoHandler = 0x3B2, // TODO: assumed,
|
||||
// FIXME: 8 bytes of something from the client, not sure what yet
|
||||
Unk5 = 0x2D0,
|
||||
// FIXME: 8 bytes of something from the client, not sure what yet
|
||||
Unk6 = 0x2E5,
|
||||
// FIXME: 32 bytes of something from the client, not sure what yet
|
||||
Unk7 = 0x2B5,
|
||||
UpdatePositionHandler = 0x249, // TODO: assumed
|
||||
}
|
||||
|
||||
#[binrw]
|
||||
|
@ -141,6 +162,15 @@ pub enum ActorControlType {
|
|||
SetCharaGearParamUI = 0x260,
|
||||
}
|
||||
|
||||
#[binrw]
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
pub struct StatusEffect {
|
||||
effect_id: u16,
|
||||
param: u16,
|
||||
duration: f32,
|
||||
source_actor_id: u32,
|
||||
}
|
||||
|
||||
#[binrw]
|
||||
#[br(import(magic: &IPCOpCode))]
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -197,6 +227,56 @@ pub enum IPCStructData {
|
|||
#[br(dbg)]
|
||||
unk: [u8; 105],
|
||||
},
|
||||
#[br(pre_assert(*magic == IPCOpCode::FinishLoading))]
|
||||
FinishLoading {
|
||||
// TODO: full of possibly interesting information
|
||||
unk: [u8; 72],
|
||||
},
|
||||
#[br(pre_assert(*magic == IPCOpCode::Unk1))]
|
||||
Unk1 {
|
||||
// TODO: full of possibly interesting information
|
||||
unk: [u8; 32],
|
||||
},
|
||||
#[br(pre_assert(*magic == IPCOpCode::Unk2))]
|
||||
Unk2 {
|
||||
// TODO: full of possibly interesting information
|
||||
unk: [u8; 16],
|
||||
},
|
||||
#[br(pre_assert(*magic == IPCOpCode::Unk3))]
|
||||
Unk3 {
|
||||
// TODO: full of possibly interesting information
|
||||
unk: [u8; 8],
|
||||
},
|
||||
#[br(pre_assert(*magic == IPCOpCode::Unk4))]
|
||||
Unk4 {
|
||||
// TODO: full of possibly interesting information
|
||||
unk: [u8; 8],
|
||||
},
|
||||
#[br(pre_assert(*magic == IPCOpCode::SetSearchInfoHandler))]
|
||||
SetSearchInfoHandler {
|
||||
// TODO: full of possibly interesting information
|
||||
unk: [u8; 8],
|
||||
},
|
||||
#[br(pre_assert(*magic == IPCOpCode::Unk5))]
|
||||
Unk5 {
|
||||
// TODO: full of possibly interesting information
|
||||
unk: [u8; 8],
|
||||
},
|
||||
#[br(pre_assert(*magic == IPCOpCode::Unk6))]
|
||||
Unk6 {
|
||||
// TODO: full of possibly interesting information
|
||||
unk: [u8; 8],
|
||||
},
|
||||
#[br(pre_assert(*magic == IPCOpCode::Unk7))]
|
||||
Unk7 {
|
||||
// TODO: full of possibly interesting information
|
||||
unk: [u8; 32],
|
||||
},
|
||||
#[br(pre_assert(*magic == IPCOpCode::UpdatePositionHandler))]
|
||||
UpdatePositionHandler {
|
||||
// TODO: full of possibly interesting information
|
||||
unk: [u8; 24],
|
||||
},
|
||||
|
||||
// Server->Client IPC
|
||||
#[br(pre_assert(false))]
|
||||
|
@ -488,6 +568,85 @@ pub enum IPCStructData {
|
|||
class_level: u16,
|
||||
role_actions: [u32; 10],
|
||||
},
|
||||
#[br(pre_assert(false))]
|
||||
PlayerSpawn {
|
||||
title: u16,
|
||||
u1b: u16,
|
||||
current_world_id: u16,
|
||||
home_world_id: u16,
|
||||
|
||||
gm_rank: u8,
|
||||
u3c: u8,
|
||||
u4: u8,
|
||||
online_status: u8,
|
||||
|
||||
pose: u8,
|
||||
u5a: u8,
|
||||
u5b: u8,
|
||||
u5c: u8,
|
||||
|
||||
target_id: u64,
|
||||
u6: u32,
|
||||
u7: u32,
|
||||
main_weapon_model: u64,
|
||||
sec_weapon_model: u64,
|
||||
craft_tool_model: u64,
|
||||
|
||||
u14: u32,
|
||||
u15: u32,
|
||||
b_npc_base: u32,
|
||||
b_npc_name: u32,
|
||||
u18: u32,
|
||||
u19: u32,
|
||||
director_id: u32,
|
||||
owner_id: u32,
|
||||
u22: u32,
|
||||
padding4: [u8; 16],
|
||||
hp_max: u32,
|
||||
hp_curr: u32,
|
||||
display_flags: u32,
|
||||
fate_id: u16,
|
||||
mp_curr: u16,
|
||||
mp_max: u16,
|
||||
unk: u16,
|
||||
model_chara: u16,
|
||||
rotation: u16,
|
||||
current_mount: u16,
|
||||
active_minion: u16,
|
||||
u23: u8,
|
||||
u24: u8,
|
||||
u25: u8,
|
||||
u26: u8,
|
||||
spawn_index: u8,
|
||||
state: u8,
|
||||
persistent_emote: u8,
|
||||
model_type: u8,
|
||||
subtype: u8,
|
||||
voice: u8,
|
||||
enemy_type: u8,
|
||||
unk27: u8,
|
||||
level: u8,
|
||||
class_job: u8,
|
||||
unk28: u8,
|
||||
unk29: u8,
|
||||
unk30: u8,
|
||||
mount_head: u8,
|
||||
mount_body: u8,
|
||||
mount_feet: u8,
|
||||
mount_color: u8,
|
||||
scale: u8,
|
||||
element_data: [u8; 6],
|
||||
padding2: [u8; 12],
|
||||
effect: [StatusEffect; 30],
|
||||
pos: Position,
|
||||
models: [u32; 10],
|
||||
unknown6_58: [u8; 10],
|
||||
padding3: [u8; 7],
|
||||
name: [u8; 32],
|
||||
look: [u8; 26],
|
||||
fc_tag: [u8; 6],
|
||||
padding: [u8; 26],
|
||||
},
|
||||
}
|
||||
|
||||
#[binrw]
|
||||
|
@ -529,6 +688,17 @@ impl IPCSegment {
|
|||
IPCStructData::PlayerStats { .. } => 228,
|
||||
IPCStructData::PlayerSetup { .. } => 2544,
|
||||
IPCStructData::UpdateClassInfo { .. } => 48,
|
||||
IPCStructData::FinishLoading { .. } => todo!(),
|
||||
IPCStructData::PlayerSpawn { .. } => 656,
|
||||
IPCStructData::Unk1 { .. } => todo!(),
|
||||
IPCStructData::Unk2 { .. } => todo!(),
|
||||
IPCStructData::Unk3 { .. } => todo!(),
|
||||
IPCStructData::Unk4 { .. } => todo!(),
|
||||
IPCStructData::SetSearchInfoHandler { .. } => todo!(),
|
||||
IPCStructData::Unk5 { .. } => todo!(),
|
||||
IPCStructData::Unk6 { .. } => todo!(),
|
||||
IPCStructData::Unk7 { .. } => todo!(),
|
||||
IPCStructData::UpdatePositionHandler { .. } => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue