diff --git a/build.rs b/build.rs index a3ec500..b7ad54b 100644 --- a/build.rs +++ b/build.rs @@ -21,84 +21,82 @@ fn main() { let key = element.0; let opcodes = element.1.as_array().unwrap(); - if !opcodes.is_empty() { - // beginning - output_str.push_str("#[binrw]\n"); - output_str.push_str("#[derive(Clone, PartialEq, Debug)]\n"); - output_str.push_str(&format!("pub enum {key} {{\n")); + // beginning + output_str.push_str("#[binrw]\n"); + output_str.push_str("#[derive(Clone, PartialEq, Debug)]\n"); + output_str.push_str(&format!("pub enum {key} {{\n")); - for opcode in opcodes { - let opcode = opcode.as_object().unwrap(); - let name = opcode.get("name").unwrap().as_str().unwrap(); - let opcode = opcode.get("opcode").unwrap().as_number().unwrap(); + for opcode in opcodes { + let opcode = opcode.as_object().unwrap(); + let name = opcode.get("name").unwrap().as_str().unwrap(); + let opcode = opcode.get("opcode").unwrap().as_number().unwrap(); - output_str.push_str(&format!("#[brw(magic = {opcode}u16)]\n")); - output_str.push_str(&format!("{name},\n")); - } - - output_str.push_str("Unknown(u16),\n"); - - // end - output_str.push_str("}\n\n"); - - output_str.push_str(&format!("impl {key} {{\n")); - - // sizes - output_str.push_str("/// Returns the expected size of the data segment of this IPC opcode, _without_ any headers.\n"); - output_str.push_str("pub fn calc_size(&self) -> u32 {\n"); - output_str.push_str("match self {\n"); - - for opcode in opcodes { - let opcode = opcode.as_object().unwrap(); - let name = opcode.get("name").unwrap().as_str().unwrap(); - let size = opcode.get("size").unwrap().as_number().unwrap(); - - output_str.push_str(&format!("{key}::{name} => {size},\n")); - } - - output_str.push_str(&format!("{key}::Unknown(_) => 0,\n")); - - output_str.push_str("}\n\n"); - output_str.push_str("}\n\n"); - - // names - output_str.push_str("/// Returns a human-readable name of the opcode.\n"); - output_str.push_str("pub fn get_name(&self) -> &'static str {\n"); - output_str.push_str("match self {\n"); - - for opcode in opcodes { - let opcode = opcode.as_object().unwrap(); - let name = opcode.get("name").unwrap().as_str().unwrap(); - - output_str.push_str(&format!("{key}::{name} => \"{name}\",\n")); - } - - output_str.push_str(&format!("{key}::Unknown(_) => \"Unknown\",\n")); - - output_str.push_str("}\n\n"); - output_str.push_str("}\n\n"); - - // opcodes - output_str.push_str("/// Returns the integer opcode.\n"); - output_str.push_str("pub fn get_opcode(&self) -> u16 {\n"); - output_str.push_str("match self {\n"); - - for opcode in opcodes { - let opcode = opcode.as_object().unwrap(); - let name = opcode.get("name").unwrap().as_str().unwrap(); - let opcode = opcode.get("opcode").unwrap().as_number().unwrap(); - - output_str.push_str(&format!("{key}::{name} => {opcode},\n")); - } - - output_str.push_str(&format!("{key}::Unknown(opcode) => *opcode,\n")); - - output_str.push_str("}\n\n"); - output_str.push_str("}\n\n"); - - // end impl - output_str.push_str("}\n\n"); + output_str.push_str(&format!("#[brw(magic = {opcode}u16)]\n")); + output_str.push_str(&format!("{name},\n")); } + + output_str.push_str("Unknown(u16),\n"); + + // end + output_str.push_str("}\n\n"); + + output_str.push_str(&format!("impl {key} {{\n")); + + // sizes + output_str.push_str("/// Returns the expected size of the data segment of this IPC opcode, _without_ any headers.\n"); + output_str.push_str("pub fn calc_size(&self) -> u32 {\n"); + output_str.push_str("match self {\n"); + + for opcode in opcodes { + let opcode = opcode.as_object().unwrap(); + let name = opcode.get("name").unwrap().as_str().unwrap(); + let size = opcode.get("size").unwrap().as_number().unwrap(); + + output_str.push_str(&format!("{key}::{name} => {size},\n")); + } + + output_str.push_str(&format!("{key}::Unknown(_) => 0,\n")); + + output_str.push_str("}\n\n"); + output_str.push_str("}\n\n"); + + // names + output_str.push_str("/// Returns a human-readable name of the opcode.\n"); + output_str.push_str("pub fn get_name(&self) -> &'static str {\n"); + output_str.push_str("match self {\n"); + + for opcode in opcodes { + let opcode = opcode.as_object().unwrap(); + let name = opcode.get("name").unwrap().as_str().unwrap(); + + output_str.push_str(&format!("{key}::{name} => \"{name}\",\n")); + } + + output_str.push_str(&format!("{key}::Unknown(_) => \"Unknown\",\n")); + + output_str.push_str("}\n\n"); + output_str.push_str("}\n\n"); + + // opcodes + output_str.push_str("/// Returns the integer opcode.\n"); + output_str.push_str("pub fn get_opcode(&self) -> u16 {\n"); + output_str.push_str("match self {\n"); + + for opcode in opcodes { + let opcode = opcode.as_object().unwrap(); + let name = opcode.get("name").unwrap().as_str().unwrap(); + let opcode = opcode.get("opcode").unwrap().as_number().unwrap(); + + output_str.push_str(&format!("{key}::{name} => {opcode},\n")); + } + + output_str.push_str(&format!("{key}::Unknown(opcode) => *opcode,\n")); + + output_str.push_str("}\n\n"); + output_str.push_str("}\n\n"); + + // end impl + output_str.push_str("}\n\n"); } std::fs::write("src/opcodes.rs", output_str).expect("Failed to write opcodes file!"); diff --git a/src/ipc/chat/mod.rs b/src/ipc/chat/mod.rs index f4e4f3c..d0c266f 100644 --- a/src/ipc/chat/mod.rs +++ b/src/ipc/chat/mod.rs @@ -1,7 +1,7 @@ use binrw::binrw; use crate::{ - opcodes::ServerChatIpcType, + opcodes::{ClientChatIpcType, ServerChatIpcType}, packet::{IPC_HEADER_SIZE, IpcSegment, ReadWriteIpcSegment}, }; @@ -38,6 +38,36 @@ impl Default for ServerChatIpcSegment { } } +pub type ClientChatIpcSegment = IpcSegment; + +impl ReadWriteIpcSegment for ClientChatIpcSegment { + fn calc_size(&self) -> u32 { + IPC_HEADER_SIZE + self.op_code.calc_size() + } + + fn get_name(&self) -> &'static str { + self.op_code.get_name() + } + + fn get_opcode(&self) -> u16 { + self.op_code.get_opcode() + } +} + +// TODO: make generic +impl Default for ClientChatIpcSegment { + fn default() -> Self { + Self { + unk1: 0x14, + unk2: 0, + op_code: ClientChatIpcType::Unknown(0), + option: 0, + timestamp: 0, + data: ClientChatIpcData::Unknown { unk: Vec::new() }, + } + } +} + #[binrw] #[br(import(magic: &ServerChatIpcType, size: &u32))] #[derive(Debug, Clone)] @@ -50,3 +80,13 @@ pub enum ServerChatIpcData { unk: Vec, }, } + +#[binrw] +#[br(import(_magic: &ClientChatIpcType, size: &u32))] +#[derive(Debug, Clone)] +pub enum ClientChatIpcData { + Unknown { + #[br(count = size - 32)] + unk: Vec, + }, +}