From 74f7554aa8498695e75a08274fbb440948fb1cf2 Mon Sep 17 00:00:00 2001 From: Joshua Goins Date: Thu, 13 Mar 2025 00:41:16 -0400 Subject: [PATCH] Support the GM command for changing territories --- src/bin/kawari-world.rs | 41 ++++++++++++++++++++++++++++++++++++++++- src/ipc.rs | 19 +++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/src/bin/kawari-world.rs b/src/bin/kawari-world.rs index ba38443..68a1f8f 100644 --- a/src/bin/kawari-world.rs +++ b/src/bin/kawari-world.rs @@ -1,7 +1,7 @@ use std::time::{SystemTime, UNIX_EPOCH}; use kawari::client_select_data::ClientCustomizeData; -use kawari::ipc::{IPCOpCode, IPCSegment, IPCStructData}; +use kawari::ipc::{GameMasterCommandType, IPCOpCode, IPCSegment, IPCStructData}; use kawari::oodle::FFXIVOodle; use kawari::packet::{ CompressionType, PacketSegment, SegmentType, State, parse_packet, send_keep_alive, send_packet, @@ -375,6 +375,7 @@ async fn main() { model_type: 1, spawn_index: 1, state: 1, + gm_rank: 3, look: CustomizeData { race: 3, age: 0, @@ -483,6 +484,44 @@ async fn main() { IPCStructData::ChatMessage { message, .. } => { tracing::info!("Client sent chat message: {message}!"); } + IPCStructData::GameMasterCommand { command, arg, .. } => { + tracing::info!("Got a game master command!"); + + match &command { + GameMasterCommandType::ChangeTerritory => { + // Init Zone + { + let ipc = IPCSegment { + unk1: 0, + unk2: 0, + op_code: IPCOpCode::InitZone, + server_id: 0, + timestamp: timestamp_secs(), + data: IPCStructData::InitZone(InitZone { + server_id: WORLD_ID, + zone_id: *arg as u16, + ..Default::default() + }), + }; + + let response_packet = PacketSegment { + source_actor: state.player_id.unwrap(), + target_actor: state.player_id.unwrap(), + segment_type: SegmentType::Ipc { + data: ipc, + }, + }; + send_packet( + &mut write, + &[response_packet], + &mut state, + CompressionType::Oodle, + ) + .await; + } + } + } + } _ => panic!( "The server is recieving a IPC response or unknown packet!" ), diff --git a/src/ipc.rs b/src/ipc.rs index 14a1231..99e6b6f 100644 --- a/src/ipc.rs +++ b/src/ipc.rs @@ -79,6 +79,8 @@ pub enum IPCOpCode { Disconnected = 0x360, // Sent by the client when they send a chat message ChatMessage = 0xCA, + // 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. + GameMasterCommand = 0x3B3, } #[binrw] @@ -162,6 +164,13 @@ pub enum LobbyCharacterAction { Request = 0x15, } +#[binrw] +#[brw(repr = u8)] +#[derive(Clone, PartialEq, Debug)] +pub enum GameMasterCommandType { + ChangeTerritory = 0x58, +} + #[binrw] #[br(import(magic: &IPCOpCode))] #[derive(Debug, Clone)] @@ -296,6 +305,15 @@ pub enum IPCStructData { #[bw(map = write_string)] message: String, }, + #[br(pre_assert(*magic == IPCOpCode::GameMasterCommand))] + GameMasterCommand { + // TODO: incomplete + command: GameMasterCommandType, + #[br(pad_before = 3)] // idk, not empty though + arg: u32, + #[br(dbg)] + unk: [u8; 24], + }, // Server->Client IPC #[br(pre_assert(false))] @@ -455,6 +473,7 @@ impl IPCSegment { IPCStructData::LogOutComplete { .. } => 8, IPCStructData::Disconnected { .. } => todo!(), IPCStructData::ChatMessage { .. } => 1056, + IPCStructData::GameMasterCommand { .. } => todo!(), } } }