From 96aece36cffb1ca53018c57fa98da2f5d811e8b5 Mon Sep 17 00:00:00 2001 From: Joshua Goins Date: Wed, 25 Jun 2025 23:11:49 -0400 Subject: [PATCH] Implement more back and forth packets for events I figured out a few of these while figuring out the crystal bell event, although their purpose is still generally unknown. It doesn't really affect anything functionally as the event still works as well as it did before. I also fixed the crystal bell scenes so they don't finish the event prematurely, although it looks weird without the hairstyle menu. But that still isn't figured out yet. --- resources/opcodes.json | 15 +++++++ .../scripts/events/tosort/CrystalBell.lua | 2 + src/bin/kawari-world.rs | 44 ++++++++++++++++++- src/ipc/zone/actor_control.rs | 6 +++ src/ipc/zone/client_trigger.rs | 9 ++++ src/ipc/zone/mod.rs | 24 +++++++++- 6 files changed, 97 insertions(+), 3 deletions(-) diff --git a/resources/opcodes.json b/resources/opcodes.json index 07c34b9..22b02eb 100644 --- a/resources/opcodes.json +++ b/resources/opcodes.json @@ -179,6 +179,16 @@ "name": "Config", "opcode": 153, "size": 8 + }, + { + "name": "EventUnkReply", + "opcode": 337, + "size": 16 + }, + { + "name": "UnkCall", + "opcode": 886, + "size": 32 } ], "ClientZoneIpcType": [ @@ -306,6 +316,11 @@ "name": "Config", "opcode": 534, "size": 8 + }, + { + "name": "EventUnkRequest", + "opcode": 448, + "size": 16 } ], "ServerLobbyIpcType": [ diff --git a/resources/scripts/events/tosort/CrystalBell.lua b/resources/scripts/events/tosort/CrystalBell.lua index b808f3c..ec2f97c 100644 --- a/resources/scripts/events/tosort/CrystalBell.lua +++ b/resources/scripts/events/tosort/CrystalBell.lua @@ -28,8 +28,10 @@ function onReturn(scene, results, player) end elseif scene == 1 then player:play_scene(player.id, EVENT_ID, 00002, FADE_OUT + HIDE_UI + CONDITION_CUTSCENE, 0) + return elseif scene == 2 then player:play_scene(player.id, EVENT_ID, 00003, FADE_OUT + HIDE_UI + CONDITION_CUTSCENE, 0) + return end player:finish_event(EVENT_ID) end diff --git a/src/bin/kawari-world.rs b/src/bin/kawari-world.rs index ca64a1a..32dff12 100644 --- a/src/bin/kawari-world.rs +++ b/src/bin/kawari-world.rs @@ -774,8 +774,26 @@ async fn client_loop( ClientZoneIpcData::Unk16 { .. } => { // no-op } - ClientZoneIpcData::Unk17 { .. } => { - // no-op + ClientZoneIpcData::Unk17 { unk1, .. } => { + // this is *usually* sent in response, but not always + let ipc = ServerZoneIpcSegment { + op_code: ServerZoneIpcType::UnkCall, + timestamp: timestamp_secs(), + data: ServerZoneIpcData::UnkCall { + unk1: *unk1, // copied from here + unk2: 333, // always this for some reason + }, + ..Default::default() + }; + + connection + .send_segment(PacketSegment { + source_actor: connection.player_data.actor_id, + target_actor: connection.player_data.actor_id, + segment_type: SegmentType::Ipc, + data: SegmentData::Ipc { data: ipc }, + }) + .await; } ClientZoneIpcData::Unk18 { .. } => { // no-op @@ -874,6 +892,28 @@ async fn client_loop( )) .await; } + ClientZoneIpcData::EventUnkRequest { event_id, unk1, unk2, unk3 } => { + let ipc = ServerZoneIpcSegment { + op_code: ServerZoneIpcType::EventUnkReply, + timestamp: timestamp_secs(), + data: ServerZoneIpcData::EventUnkReply { + event_id: *event_id, + unk1: *unk1, + unk2: *unk2, + unk3: *unk3 + 1, + }, + ..Default::default() + }; + + connection + .send_segment(PacketSegment { + source_actor: connection.player_data.actor_id, + target_actor: connection.player_data.actor_id, + segment_type: SegmentType::Ipc, + data: SegmentData::Ipc { data: ipc }, + }) + .await; + } } } SegmentData::KeepAliveRequest { id, timestamp } => { diff --git a/src/ipc/zone/actor_control.rs b/src/ipc/zone/actor_control.rs index 41c51cb..e3ff0d5 100644 --- a/src/ipc/zone/actor_control.rs +++ b/src/ipc/zone/actor_control.rs @@ -109,6 +109,12 @@ pub enum ActorControlCategory { #[brw(pad_before = 2)] // padding emote: u32, }, + #[brw(magic = 0x207u16)] + TestActorControl { + #[brw(pad_before = 2)] // padding + actor_id: u32, + unk1: u32, + }, } #[binrw] diff --git a/src/ipc/zone/client_trigger.rs b/src/ipc/zone/client_trigger.rs index 10c72dc..9aae5a1 100644 --- a/src/ipc/zone/client_trigger.rs +++ b/src/ipc/zone/client_trigger.rs @@ -50,6 +50,15 @@ pub enum ClientTriggerCommand { aetheryte_id: u32, // TODO: fill out the rest }, + #[brw(magic = 0x033Eu16)] + EventRelatedUnk { + // seen in haircut event + #[brw(pad_before = 2)] // padding + unk1: u32, + unk2: u32, + unk3: u32, + unk4: u32, + }, } #[binrw] diff --git a/src/ipc/zone/mod.rs b/src/ipc/zone/mod.rs index 091b908..1f5ea8d 100644 --- a/src/ipc/zone/mod.rs +++ b/src/ipc/zone/mod.rs @@ -268,6 +268,19 @@ pub enum ServerZoneIpcData { CurrencyCrystalInfo(CurrencyInfo), /// Used to update an actor's equip display flags Config(Config), + /// Unknown, seen in haircut event + EventUnkReply { + event_id: u32, + unk1: u16, + unk2: u8, + #[brw(pad_after = 8)] + unk3: u8, + }, + UnkCall { + unk1: u32, + #[brw(pad_after = 26)] + unk2: u16, + }, } #[binrw] @@ -371,7 +384,8 @@ pub enum ClientZoneIpcData { }, #[br(pre_assert(*magic == ClientZoneIpcType::Unk17))] Unk17 { - unk: [u8; 32], // TODO: unknown + unk1: u32, + unk2: [u8; 28], // TODO: unknown }, #[br(pre_assert(*magic == ClientZoneIpcType::Unk18))] Unk18 { @@ -408,6 +422,14 @@ pub enum ClientZoneIpcData { }, #[br(pre_assert(*magic == ClientZoneIpcType::Config))] Config(Config), + #[br(pre_assert(*magic == ClientZoneIpcType::EventUnkRequest))] + EventUnkRequest { + event_id: u32, + unk1: u16, + unk2: u8, + #[brw(pad_after = 8)] + unk3: u8, + }, } #[cfg(test)]