From 5420225c74eeceeb609d0c2f23a273416d9560bd Mon Sep 17 00:00:00 2001 From: Joshua Goins Date: Thu, 1 May 2025 23:20:56 -0400 Subject: [PATCH] Update world IPC packets with better fitting names, fields --- resources/opcodes.json | 20 +++++++------- src/bin/kawari-world.rs | 30 ++++++++++----------- src/world/connection.rs | 31 ++++++++++----------- src/world/inventory.rs | 2 +- src/world/ipc/action_request.rs | 4 +-- src/world/ipc/actor_move.rs | 2 +- src/world/ipc/actor_set_pos.rs | 8 +++--- src/world/ipc/init_zone.rs | 4 +-- src/world/ipc/inventory_modify.rs | 6 ++--- src/world/ipc/mod.rs | 45 +++++++++++++++++-------------- src/world/lua.rs | 9 +++---- 11 files changed, 82 insertions(+), 79 deletions(-) diff --git a/resources/opcodes.json b/resources/opcodes.json index 43222f6..e5e4821 100644 --- a/resources/opcodes.json +++ b/resources/opcodes.json @@ -21,7 +21,7 @@ "size": 144 }, { - "name": "PlayerSetup", + "name": "PlayerStatus", "opcode": 311, "size": 2808 }, @@ -46,7 +46,7 @@ "size": 8 }, { - "name": "ActorSetPos", + "name": "Warp", "opcode": 121, "size": 24 }, @@ -91,7 +91,7 @@ "size": 24 }, { - "name": "ActorMove", + "name": "Move", "opcode": 487, "size": 16 }, @@ -116,12 +116,12 @@ "size": 384 }, { - "name": "WeatherChange", + "name": "WeatherId", "opcode": 580, "size": 8 }, { - "name": "ItemInfo", + "name": "UpdateItem", "opcode": 404, "size": 64 }, @@ -131,7 +131,7 @@ "size": 16 }, { - "name": "EventPlay", + "name": "EventScene", "opcode": 269, "size": 40 }, @@ -156,7 +156,7 @@ "size": 72 }, { - "name": "ActorFreeSpawn", + "name": "Delete", "opcode": 149, "size": 8 } @@ -228,12 +228,12 @@ "size": 58 }, { - "name": "GameMasterCommand", + "name": "GMCommand", "opcode": 266, "size": 32 }, { - "name": "EnterZoneLine", + "name": "ZoneJump", "opcode": 609, "size": 24 }, @@ -268,7 +268,7 @@ "size": 16 }, { - "name": "InventoryModify", + "name": "ItemOperation", "opcode": 583, "size": 48 } diff --git a/src/bin/kawari-world.rs b/src/bin/kawari-world.rs index 781161c..d20d62d 100644 --- a/src/bin/kawari-world.rs +++ b/src/bin/kawari-world.rs @@ -344,9 +344,9 @@ async fn client_loop( // Player Setup { let ipc = ServerZoneIpcSegment { - op_code: ServerZoneIpcType::PlayerSetup, + op_code: ServerZoneIpcType::PlayerStatus, timestamp: timestamp_secs(), - data: ServerZoneIpcData::PlayerSetup(PlayerSetup { + data: ServerZoneIpcData::PlayerStatus(PlayerSetup { content_id: connection.player_data.content_id, exp: [10000; 32], levels: [100; 32], @@ -584,19 +584,19 @@ async fn client_loop( ) .await } - ClientZoneIpcData::GameMasterCommand { command, arg, .. } => { + ClientZoneIpcData::GameMasterCommand { command, arg0, .. } => { tracing::info!("Got a game master command!"); match &command { GameMasterCommandType::SetLevel => { - connection.player_data.level = *arg as u8; + connection.player_data.level = *arg0 as u8; connection.update_class_info().await; } GameMasterCommandType::ChangeWeather => { - connection.change_weather(*arg as u16).await + connection.change_weather(*arg0 as u16).await } GameMasterCommandType::ChangeTerritory => { - connection.change_zone(*arg as u16).await + connection.change_zone(*arg0 as u16).await } GameMasterCommandType::ToggleInvisibility => { connection @@ -615,18 +615,18 @@ async fn client_loop( }) .await, GameMasterCommandType::GiveItem => { - connection.player_data.inventory.add_in_next_free_slot(Item { id: *arg, quantity: 1 }); + connection.player_data.inventory.add_in_next_free_slot(Item { id: *arg0, quantity: 1 }); connection.send_inventory(false).await; } } } - ClientZoneIpcData::EnterZoneLine { - exit_box_id, + ClientZoneIpcData::ZoneJump { + exit_box, position, .. } => { tracing::info!( - "Character entered {exit_box_id} with a position of {position:#?}!" + "Character entered {exit_box} with a position of {position:#?}!" ); // find the exit box id @@ -636,7 +636,7 @@ async fn client_loop( .zone .as_ref() .unwrap() - .find_exit_box(*exit_box_id) + .find_exit_box(*exit_box) .unwrap(); // find the pop range on the other side @@ -666,7 +666,7 @@ async fn client_loop( let state = lua.app_data_ref::().unwrap(); if let Some(action_script) = - state.action_scripts.get(&request.action_id) + state.action_scripts.get(&request.action_key) { lua.scope(|scope| { let connection_data = scope @@ -729,10 +729,10 @@ async fn client_loop( data: ServerZoneIpcData::ActionResult(ActionResult { main_target: request.target, target_id_again: request.target, - action_id: request.action_id, + action_id: request.action_key, animation_lock_time: 0.6, rotation: connection.player_data.rotation, - action_animation_id: request.action_id as u16, // assuming action id == animation id + action_animation_id: request.action_key as u16, // assuming action id == animation id flag: 1, effect_count: effects_builder.effects.len() as u8, effects, @@ -791,7 +791,7 @@ async fn client_loop( ClientZoneIpcData::Unk19 { .. } => { tracing::info!("Recieved Unk19!"); } - ClientZoneIpcData::InventoryModify(action) => { + ClientZoneIpcData::ItemOperation(action) => { tracing::info!("Client is modifying inventory! {action:#?}"); connection.player_data.inventory.process_action(action); diff --git a/src/world/connection.rs b/src/world/connection.rs index 1883153..9155b93 100644 --- a/src/world/connection.rs +++ b/src/world/connection.rs @@ -271,10 +271,9 @@ impl ZoneConnection { // set pos { let ipc = ServerZoneIpcSegment { - op_code: ServerZoneIpcType::ActorSetPos, + op_code: ServerZoneIpcType::Warp, timestamp: timestamp_secs(), - data: ServerZoneIpcData::ActorSetPos(ActorSetPos { - unk: 0x020fa3b8, + data: ServerZoneIpcData::Warp(ActorSetPos { position, ..Default::default() }), @@ -292,15 +291,14 @@ impl ZoneConnection { pub async fn set_actor_position(&mut self, actor_id: u32, position: Position, rotation: f32) { let ipc = ServerZoneIpcSegment { - op_code: ServerZoneIpcType::ActorMove, + op_code: ServerZoneIpcType::Move, timestamp: timestamp_secs(), - data: ServerZoneIpcData::ActorMove(ActorMove { + data: ServerZoneIpcData::Move(ActorMove { rotation, dir_before_slip: 0x7F, flag1: 0, flag2: 0, speed: 0x3C, - unk1: 0xEA, position, }), ..Default::default() @@ -350,11 +348,11 @@ impl ZoneConnection { let ipc = ServerZoneIpcSegment { unk1: 20, unk2: 0, - op_code: ServerZoneIpcType::ActorFreeSpawn, + op_code: ServerZoneIpcType::Delete, server_id: 0, timestamp: timestamp_secs(), - data: ServerZoneIpcData::ActorFreeSpawn { - spawn_index: actor.spawn_index, + data: ServerZoneIpcData::Delete { + spawn_index: actor.spawn_index as u8, actor_id, }, }; @@ -441,8 +439,7 @@ impl ZoneConnection { op_code: ServerZoneIpcType::InitZone, timestamp: timestamp_secs(), data: ServerZoneIpcData::InitZone(InitZone { - server_id: 0, - zone_id: self.zone.as_ref().unwrap().id, + territory_type: self.zone.as_ref().unwrap().id, weather_id: 1, obsfucation_mode: if config.world.enable_packet_obsfucation { OBFUSCATION_ENABLED_MODE @@ -465,9 +462,9 @@ impl ZoneConnection { pub async fn change_weather(&mut self, new_weather_id: u16) { let ipc = ServerZoneIpcSegment { - op_code: ServerZoneIpcType::WeatherChange, + op_code: ServerZoneIpcType::WeatherId, timestamp: timestamp_secs(), - data: ServerZoneIpcData::WeatherChange(WeatherChange { + data: ServerZoneIpcData::WeatherId(WeatherChange { weather_id: new_weather_id, transistion_time: 1.0, }), @@ -502,9 +499,9 @@ impl ZoneConnection { let mut send_slot = async |slot_index: u16, item: &Item| { let ipc = ServerZoneIpcSegment { - op_code: ServerZoneIpcType::ItemInfo, + op_code: ServerZoneIpcType::UpdateItem, timestamp: timestamp_secs(), - data: ServerZoneIpcData::ItemInfo(ItemInfo { + data: ServerZoneIpcData::UpdateItem(ItemInfo { sequence, container: kind, slot: slot_index, @@ -559,9 +556,9 @@ impl ZoneConnection { let mut send_slot = async |slot_index: u16, item: &Item| { let ipc = ServerZoneIpcSegment { - op_code: ServerZoneIpcType::ItemInfo, + op_code: ServerZoneIpcType::UpdateItem, timestamp: timestamp_secs(), - data: ServerZoneIpcData::ItemInfo(ItemInfo { + data: ServerZoneIpcData::UpdateItem(ItemInfo { sequence, container: ContainerType::Equipped, slot: slot_index, diff --git a/src/world/inventory.rs b/src/world/inventory.rs index 233fe1d..aa4587e 100644 --- a/src/world/inventory.rs +++ b/src/world/inventory.rs @@ -215,7 +215,7 @@ impl Inventory { } pub fn process_action(&mut self, action: &InventoryModify) { - if action.operation_type == 571 { + if action.operation_type == 78 { // discard let src_container = self.get_container(&action.src_storage_id); let src_slot = src_container.get_slot_mut(action.src_container_index); diff --git a/src/world/ipc/action_request.rs b/src/world/ipc/action_request.rs index 9a44519..cf8c50d 100644 --- a/src/world/ipc/action_request.rs +++ b/src/world/ipc/action_request.rs @@ -16,8 +16,8 @@ pub enum ActionKind { pub struct ActionRequest { pub exec_proc: u8, // what? pub action_kind: ActionKind, - #[brw(pad_before = 2)] // this ISNT empty - pub action_id: u32, // See Action Excel sheet + #[brw(pad_before = 2)] // padding, i think it's filled with GARBAGE + pub action_key: u32, // See Action Excel sheet pub request_id: u16, #[br(map = read_quantized_rotation)] #[bw(map = write_quantized_rotation)] diff --git a/src/world/ipc/actor_move.rs b/src/world/ipc/actor_move.rs index 150f277..1fcdf6c 100644 --- a/src/world/ipc/actor_move.rs +++ b/src/world/ipc/actor_move.rs @@ -15,7 +15,7 @@ pub struct ActorMove { pub flag1: u8, pub flag2: u8, pub speed: u8, - pub unk1: u8, + #[brw(pad_before = 1)] // padding #[brw(pad_after = 4)] // empty #[br(map = read_packed_position)] #[bw(map = write_packed_position)] diff --git a/src/world/ipc/actor_set_pos.rs b/src/world/ipc/actor_set_pos.rs index cb0514d..156848e 100644 --- a/src/world/ipc/actor_set_pos.rs +++ b/src/world/ipc/actor_set_pos.rs @@ -5,8 +5,10 @@ use crate::common::Position; #[binrw] #[derive(Debug, Clone, Default)] pub struct ActorSetPos { - pub unk: u32, - pub layer_id: u32, + pub dir: u16, + pub warp_type: u8, + pub warp_type_arg: u8, + pub layer_set: u32, + #[brw(pad_after = 4)] // padding pub position: Position, - pub unk3: u32, } diff --git a/src/world/ipc/init_zone.rs b/src/world/ipc/init_zone.rs index f79e9d0..b897687 100644 --- a/src/world/ipc/init_zone.rs +++ b/src/world/ipc/init_zone.rs @@ -5,9 +5,9 @@ use super::Position; #[binrw] #[derive(Debug, Clone, Default)] pub struct InitZone { - pub server_id: u16, pub zone_id: u16, - pub zone_index: u16, + pub territory_type: u16, + pub territory_index: u16, pub content_finder_condition_id: u16, pub layer_set_id: u32, pub layout_id: u32, diff --git a/src/world/ipc/inventory_modify.rs b/src/world/ipc/inventory_modify.rs index 71c249e..1e08595 100644 --- a/src/world/ipc/inventory_modify.rs +++ b/src/world/ipc/inventory_modify.rs @@ -6,9 +6,9 @@ use super::ContainerType; #[derive(Debug, Clone, Default)] pub struct InventoryModify { pub context_id: u32, - pub operation_type: u16, + pub operation_type: u8, - #[brw(pad_before = 2)] + #[brw(pad_before = 3)] pub src_actor_id: u32, #[brw(pad_size_to = 4)] pub src_storage_id: ContainerType, @@ -44,7 +44,7 @@ mod tests { let modify_inventory = InventoryModify::read_le(&mut buffer).unwrap(); assert_eq!(modify_inventory.context_id, 0x10000000); - assert_eq!(modify_inventory.operation_type, 572); + assert_eq!(modify_inventory.operation_type, 128); assert_eq!(modify_inventory.src_actor_id, 0); assert_eq!(modify_inventory.src_storage_id, ContainerType::Equipped); assert_eq!(modify_inventory.src_container_index, 3); diff --git a/src/world/ipc/mod.rs b/src/world/ipc/mod.rs index f8e0dc8..3527df3 100644 --- a/src/world/ipc/mod.rs +++ b/src/world/ipc/mod.rs @@ -131,7 +131,7 @@ impl Default for ServerZoneIpcSegment { } #[binrw] -#[brw(repr = u8)] +#[brw(repr = u32)] #[derive(Clone, PartialEq, Debug)] pub enum GameMasterCommandType { SetLevel = 0x1, @@ -161,7 +161,7 @@ pub enum ServerZoneIpcData { /// Sent by the server containing character stats PlayerStats(PlayerStats), /// Sent by the server to setup the player on the client - PlayerSetup(PlayerSetup), + PlayerStatus(PlayerSetup), /// Sent by the server to setup class info UpdateClassInfo(UpdateClassInfo), /// Sent by the server to spawn the player in @@ -172,7 +172,7 @@ pub enum ServerZoneIpcData { unk: [u8; 8], }, /// Sent by the server to modify the client's position - ActorSetPos(ActorSetPos), + Warp(ActorSetPos), /// Sent by the server when they send a chat message ServerChatMessage { unk: u8, // channel? @@ -189,7 +189,7 @@ pub enum ServerZoneIpcData { /// Sent by the server ActorControl(ActorControl), /// Sent by the server - ActorMove(ActorMove), + Move(ActorMove), /// Sent by the server in response to SocialListRequest SocialList(SocialList), /// Sent by the server to spawn an NPC @@ -197,13 +197,13 @@ pub enum ServerZoneIpcData { /// Sent by the server to update an actor's status effect list StatusEffectList(StatusEffectList), /// Sent by the server when it's time to change the weather - WeatherChange(WeatherChange), + WeatherId(WeatherChange), /// Sent to inform the client of an inventory item - ItemInfo(ItemInfo), + UpdateItem(ItemInfo), /// Sent to inform the client of container status ContainerInfo(ContainerInfo), /// Sent to tell the client to play a scene - EventPlay(EventPlay), + EventScene(EventPlay), /// Sent to tell the client to load a scene, but not play it EventStart(EventStart), /// Sent to update an actor's hp & mp values @@ -217,7 +217,11 @@ pub enum ServerZoneIpcData { /// Sent to to the client to update their appearance Equip(Equip), /// Sent to the client to free up a spawn index - ActorFreeSpawn { spawn_index: u32, actor_id: u32 }, + Delete { + spawn_index: u8, + #[brw(pad_before = 3)] // padding + actor_id: u32, + }, } #[binrw] @@ -305,20 +309,21 @@ pub enum ClientZoneIpcData { #[br(pre_assert(*magic == ClientZoneIpcType::ChatMessage))] ChatMessage(ChatMessage), /// Sent by the client when they send a GM command. This can only be sent by the client if they are sent a GM rank. - #[br(pre_assert(*magic == ClientZoneIpcType::GameMasterCommand))] + #[br(pre_assert(*magic == ClientZoneIpcType::GMCommand))] GameMasterCommand { - // TODO: incomplete command: GameMasterCommandType, - #[br(pad_before = 3)] // idk, not empty though - arg: u32, - unk: [u8; 24], + arg0: u32, + arg1: u32, + arg2: u32, + arg3: u32, + target: u64, }, /// Sent by the client when the character walks into a zone transistion - #[br(pre_assert(*magic == ClientZoneIpcType::EnterZoneLine))] - EnterZoneLine { - exit_box_id: u32, + #[br(pre_assert(*magic == ClientZoneIpcType::ZoneJump))] + ZoneJump { + exit_box: u32, position: Position, - #[brw(pad_after = 4)] // empty + #[brw(pad_after = 4)] // padding landset_index: i32, }, /// Sent by the client when a character performs an action @@ -348,8 +353,8 @@ pub enum ClientZoneIpcData { Unk19 { unk: [u8; 16], // TODO: unknown }, - #[br(pre_assert(*magic == ClientZoneIpcType::InventoryModify))] - InventoryModify(InventoryModify), + #[br(pre_assert(*magic == ClientZoneIpcType::ItemOperation))] + ItemOperation(InventoryModify), } #[cfg(test)] @@ -426,7 +431,7 @@ mod tests { ServerZoneIpcData::ActorControl(ActorControl::default()), ), ( - ServerZoneIpcType::ActorMove, + ServerZoneIpcType::Move, ServerZoneIpcData::ActorMove(ActorMove::default()), ), ( diff --git a/src/world/lua.rs b/src/world/lua.rs index 6185ff1..ce79548 100644 --- a/src/world/lua.rs +++ b/src/world/lua.rs @@ -57,10 +57,10 @@ impl LuaPlayer { let ipc = ServerZoneIpcSegment { unk1: 20, unk2: 0, - op_code: ServerZoneIpcType::EventPlay, + op_code: ServerZoneIpcType::EventScene, server_id: 0, timestamp: timestamp_secs(), - data: ServerZoneIpcData::EventPlay(EventPlay { + data: ServerZoneIpcData::EventScene(EventPlay { actor_id: ObjectTypeId { object_id: ObjectId(self.player_data.actor_id), object_type: 0, @@ -82,10 +82,9 @@ impl LuaPlayer { fn set_position(&mut self, position: Position) { let ipc = ServerZoneIpcSegment { - op_code: ServerZoneIpcType::ActorSetPos, + op_code: ServerZoneIpcType::Warp, timestamp: timestamp_secs(), - data: ServerZoneIpcData::ActorSetPos(ActorSetPos { - unk: 0x020fa3b8, + data: ServerZoneIpcData::Warp(ActorSetPos { position, ..Default::default() }),