diff --git a/.gitignore b/.gitignore index ea8c4bf..bc170b8 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ /target +/purple_cello_mc_protocol_derive/target +/.vscode diff --git a/Cargo.lock b/Cargo.lock index 46380ae..987b558 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -49,12 +49,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "base64" -version = "0.21.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" - [[package]] name = "bitflags" version = "1.3.2" @@ -82,17 +76,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "getrandom" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - [[package]] name = "gimli" version = "0.28.1" @@ -201,12 +184,6 @@ version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - [[package]] name = "proc-macro2" version = "1.0.71" @@ -221,8 +198,6 @@ name = "purple_cello_mc_protocol" version = "0.1.0" dependencies = [ "async-trait", - "base64", - "rand", "serde", "serde_json", "tokio", @@ -237,36 +212,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - [[package]] name = "redox_syscall" version = "0.4.1" diff --git a/Cargo.toml b/Cargo.toml index 1149db5..80b7900 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,12 +5,8 @@ edition = "2021" description = "Purple Cello implementation of the Minecraft multiplayer protocol" license = "MIT" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] tokio = { version = "1", features = ["full"] } serde = { version = "1", features = ["derive"] } serde_json = "1" -base64 = "0.21.5" -rand = "0.8.5" async-trait = "0.1.75" diff --git a/purple_cello_mc_protocol_derive/Cargo.lock b/purple_cello_mc_protocol_derive/Cargo.lock new file mode 100644 index 0000000..b94c915 --- /dev/null +++ b/purple_cello_mc_protocol_derive/Cargo.lock @@ -0,0 +1,46 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "proc-macro2" +version = "1.0.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75cb1540fadbd5b8fbccc4dddad2734eba435053f725621c070711a14bb5f4b8" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "purple_cello_mc_protocol_derive" +version = "0.1.0" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" diff --git a/purple_cello_mc_protocol_derive/Cargo.toml b/purple_cello_mc_protocol_derive/Cargo.toml new file mode 100644 index 0000000..392c26f --- /dev/null +++ b/purple_cello_mc_protocol_derive/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "purple_cello_mc_protocol_derive" +version = "0.1.0" +edition = "2021" +description = "Macros for Purple Cello implementation of the Minecraft multiplayer protocol" +license = "MIT" + +[lib] +proc-macro = true + +[dependencies] +syn = "1.0" +quote = "1.0" diff --git a/purple_cello_mc_protocol_derive/src/lib.rs b/purple_cello_mc_protocol_derive/src/lib.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/lib.rs b/src/lib.rs index b64644a..53d2ac1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ // Yeahbut December 2023 pub mod mc_types; -pub mod handshake; -pub mod status; -pub mod login; +// pub mod handshake; +// pub mod status; +// pub mod login; diff --git a/src/mc_types.rs b/src/mc_types.rs index f9d6b2a..c8139d8 100644 --- a/src/mc_types.rs +++ b/src/mc_types.rs @@ -16,6 +16,8 @@ pub const VERSION_PROTOCOL: i32 = 762; const SEGMENT_BITS: u8 = 0x7F; const CONTINUE_BIT: u8 = 0x80; +// enum PacketError + #[derive(Debug)] pub enum PacketError { ValueTooLarge, @@ -43,6 +45,10 @@ pub struct Chat { pub text: String, } +// trait PacketType + +// trait Packet + #[async_trait] pub trait Packet: Sized { fn packet_id() -> i32; @@ -101,187 +107,214 @@ async fn read_var_int_stream(stream: &mut OwnedReadHalf) -> Result { Ok(varint) } -pub trait PacketArray: Sized { - fn get(data: &mut Vec) -> Result; - fn convert(&self) -> Vec; +// enum MCTypes - fn get_array(data: &mut Vec) -> Result> { - let length = get_var_int(data)?; - let mut out_data: Vec = vec![]; - for _ in 0..length { - out_data.push(Self::get(data)?); - } - Ok(out_data) +pub enum MCTypes { + Boolean, + Byte, + UnsignedByte, + Short, + UnsignedShort, + Int, + Long, + Float, + Double, + String, + // Chat, + Json, + Identifier, + VarInt, + VarLong, + // EntityMetadata, + // Slot, + // NBTTag, + Position, + Angle, + Uuid, + Optional, + Array, + // Enum, + ByteArray, +} + +// fn get_boolean +pub fn get_boolean(data: &mut Vec) -> Result { + if data.len() < std::mem::size_of::() { + return Err(Box::new(PacketError::RanOutOfBytes)) } + Ok(u8::from_be_bytes( + data.drain(0..std::mem::size_of::()).as_slice().try_into()?) != 0) +} +// fn convert_boolean +pub fn convert_boolean(value: bool) -> Vec { + (value as u8).to_be_bytes().to_vec() +} - fn convert_array(array: &mut Vec) -> Vec { - let length = array.len() as i32; - let mut data: Vec = convert_var_int(length); - for element in array { - data.append(&mut Self::convert(element)); - } - data +// fn get_byte +pub fn get_byte(data: &mut Vec) -> Result { + if data.len() < std::mem::size_of::() { + return Err(Box::new(PacketError::RanOutOfBytes)) } + Ok(i8::from_be_bytes( + data.drain(0..std::mem::size_of::()).as_slice().try_into()?)) +} +// fn convert_byte +pub fn convert_byte(value: i8) -> Vec { + value.to_be_bytes().to_vec() } -pub fn get_bool(data: &mut Vec) -> bool { - data.remove(0) != 0 +// fn get_unsigned_byte +pub fn get_unsigned_byte(data: &mut Vec) -> Result { + if data.len() < std::mem::size_of::() { + return Err(Box::new(PacketError::RanOutOfBytes)) + } + Ok(u8::from_be_bytes( + data.drain(0..std::mem::size_of::()).as_slice().try_into()?)) } -pub fn convert_bool(value: bool) -> Vec { - vec![value as u8] +// fn convert_unsigned_byte +pub fn convert_unsigned_byte(value: u8) -> Vec { + value.to_be_bytes().to_vec() } -pub fn get_u8(data: &mut Vec) -> u8 { - data.remove(0) +// fn get_short +pub fn get_short(data: &mut Vec) -> Result { + if data.len() < std::mem::size_of::() { + return Err(Box::new(PacketError::RanOutOfBytes)) + } + Ok(i16::from_be_bytes( + data.drain(0..std::mem::size_of::()).as_slice().try_into()?)) } -pub fn convert_u8(value: u8) -> Vec { - vec![value] +// fn convert_short +pub fn convert_short(value: i16) -> Vec { + value.to_be_bytes().to_vec() } -pub fn get_i8(data: &mut Vec) -> i8 { - get_u8(data) as i8 +// fn get_unsigned_short +pub fn get_unsigned_short(data: &mut Vec) -> Result { + if data.len() < std::mem::size_of::() { + return Err(Box::new(PacketError::RanOutOfBytes)) + } + Ok(u16::from_be_bytes( + data.drain(0..std::mem::size_of::()).as_slice().try_into()?)) } -pub fn convert_i8(value: i8) -> Vec { - convert_u8(value as u8) +// fn convert_unsigned_short +pub fn convert_unsigned_short(value: u16) -> Vec { + value.to_be_bytes().to_vec() } -pub fn get_u16(data: &mut Vec) -> u16 { - ((data.remove(0) as u16) << 8) | - (data.remove(0) as u16) +// fn get_int +pub fn get_int(data: &mut Vec) -> Result { + if data.len() < std::mem::size_of::() { + return Err(Box::new(PacketError::RanOutOfBytes)) + } + Ok(i32::from_be_bytes( + data.drain(0..std::mem::size_of::()).as_slice().try_into()?)) } -pub fn convert_u16(value: u16) -> Vec { - vec![ - ((value & 0xFF00) >> 8) as u8, - (value & 0xFF) as u8, - ] +// fn convert_int +pub fn convert_int(value: i32) -> Vec { + value.to_be_bytes().to_vec() } -pub fn get_i16(data: &mut Vec) -> i16 { - get_u16(data) as i16 +// fn get_long +pub fn get_long(data: &mut Vec) -> Result { + if data.len() < std::mem::size_of::() { + return Err(Box::new(PacketError::RanOutOfBytes)) + } + Ok(i64::from_be_bytes( + data.drain(0..std::mem::size_of::()).as_slice().try_into()?)) } -pub fn convert_i16(value: i16) -> Vec { - convert_u16(value as u16) +// fn convert_long +pub fn convert_long(value: i64) -> Vec { + value.to_be_bytes().to_vec() } -pub fn get_u32(data: &mut Vec) -> u32 { - ((data.remove(0) as u32) << 24) | - ((data.remove(0) as u32) << 16) | - ((data.remove(0) as u32) << 8) | - (data.remove(0) as u32) +// fn get_float +pub fn get_float(data: &mut Vec) -> Result { + if data.len() < std::mem::size_of::() { + return Err(Box::new(PacketError::RanOutOfBytes)); + } + Ok(f32::from_be_bytes( + data.drain(0..std::mem::size_of::()).as_slice().try_into()?)) } -pub fn convert_u32(value: u32) -> Vec { - vec![ - ((value & 0xFF0000) >> 24) as u8, - ((value & 0xFF0000) >> 16) as u8, - ((value & 0xFF00) >> 8) as u8, - (value & 0xFF) as u8, - ] +// fn convert_float +pub fn convert_float(value: f32) -> Vec { + value.to_be_bytes().to_vec() } -pub fn get_i32(data: &mut Vec) -> i32 { - get_u32(data) as i32 +// fn get_double +pub fn get_double(data: &mut Vec) -> Result { + if data.len() < std::mem::size_of::() { + return Err(Box::new(PacketError::RanOutOfBytes)); + } + Ok(f64::from_be_bytes( + data.drain(0..std::mem::size_of::()).as_slice().try_into()?)) } -pub fn convert_i32(value: i32) -> Vec { - convert_u32(value as u32) +// fn convert_double +pub fn convert_double(value: f64) -> Vec { + value.to_be_bytes().to_vec() } -pub fn get_f32(data: &mut Vec) -> f32 { - get_u32(data) as f32 +// fn get_string +pub fn get_string(data: &mut Vec) -> Result { + let length = get_var_int(data)? as usize; + let buffer = data[..length].to_vec(); + for _ in 0..length { data.remove(0); } + Ok(String::from_utf8_lossy(&buffer).to_string()) } -pub fn convert_f32(value: f32) -> Vec { - convert_u32(value as u32) +// fn convert_string +pub fn convert_string(s: &str) -> Vec { + let length = s.len() as i32; + let mut data = convert_var_int(length); + data.append(&mut s.as_bytes().to_vec()); + data } -pub fn get_u64(data: &mut Vec) -> u64 { - ((data.remove(0) as u64) << 56) | - ((data.remove(0) as u64) << 48) | - ((data.remove(0) as u64) << 40) | - ((data.remove(0) as u64) << 32) | - ((data.remove(0) as u64) << 24) | - ((data.remove(0) as u64) << 16) | - ((data.remove(0) as u64) << 8) | - (data.remove(0) as u64) +// // fn get_chat <- nbt +// pub fn get_chat(data: &mut Vec) -> Result { +// get_nbt_tag(data) +// } +// // fn convert_chat <- nbt +// pub fn convert_chat(value: String) -> Vec { +// convert_nbt_tag(value) +// } + +// fn get_json_chat <- string +pub fn get_json_chat(data: &mut Vec) -> Result { + get_string(data) } -pub fn convert_u64(value: u64) -> Vec { - vec![ - ((value & 0xFF00000000000000) >> 56) as u8, - ((value & 0xFF000000000000) >> 48) as u8, - ((value & 0xFF0000000000) >> 40) as u8, - ((value & 0xFF00000000) >> 32) as u8, - ((value & 0xFF000000) >> 24) as u8, - ((value & 0xFF0000) >> 16) as u8, - ((value & 0xFF00) >> 8) as u8, - (value & 0xFF) as u8, - ] +// fn convert_json_chat <- string +pub fn convert_json_chat(value: String) -> Vec { + convert_string(value) } -pub fn get_i64(data: &mut Vec) -> i64 { - get_u64(data) as i64 +// fn get_identifier <- string +pub fn get_identifier(data: &mut Vec) -> Result { + get_string(data) } -pub fn convert_i64(value: i64) -> Vec { - convert_u64(value as u64) -} - -pub fn get_f64(data: &mut Vec) -> f64 { - get_u64(data) as f64 -} -pub fn convert_f64(value: f64) -> Vec { - convert_u64(value as u64) -} - -pub fn get_uuid(data: &mut Vec) -> u128 { - ((data.remove(0) as u128) << 120) | - ((data.remove(0) as u128) << 112) | - ((data.remove(0) as u128) << 104) | - ((data.remove(0) as u128) << 96) | - ((data.remove(0) as u128) << 88) | - ((data.remove(0) as u128) << 80) | - ((data.remove(0) as u128) << 72) | - ((data.remove(0) as u128) << 64) | - ((data.remove(0) as u128) << 56) | - ((data.remove(0) as u128) << 48) | - ((data.remove(0) as u128) << 40) | - ((data.remove(0) as u128) << 32) | - ((data.remove(0) as u128) << 24) | - ((data.remove(0) as u128) << 16) | - ((data.remove(0) as u128) << 8) | - (data.remove(0) as u128) -} -pub fn convert_uuid(value: u128) -> Vec { - vec![ - ((value & 0xFF000000000000000000000000000000) >> 120) as u8, - ((value & 0xFF0000000000000000000000000000) >> 112) as u8, - ((value & 0xFF00000000000000000000000000) >> 104) as u8, - ((value & 0xFF000000000000000000000000) >> 96) as u8, - ((value & 0xFF0000000000000000000000) >> 88) as u8, - ((value & 0xFF00000000000000000000) >> 80) as u8, - ((value & 0xFF000000000000000000) >> 72) as u8, - ((value & 0xFF0000000000000000) >> 64) as u8, - ((value & 0xFF00000000000000) >> 56) as u8, - ((value & 0xFF000000000000) >> 48) as u8, - ((value & 0xFF0000000000) >> 40) as u8, - ((value & 0xFF00000000) >> 32) as u8, - ((value & 0xFF000000) >> 24) as u8, - ((value & 0xFF0000) >> 16) as u8, - ((value & 0xFF00) >> 8) as u8, - (value & 0xFF) as u8, - ] +// fn convert_identifier <- string +pub fn convert_identifier(value: String) -> Vec { + convert_string(value) } +// fn get_var_int pub fn get_var_int(data: &mut Vec) -> Result { Ok(get_var(data, 32)? as i32) } +// fn convert_var_int pub fn convert_var_int(value: i32) -> Vec { convert_var(value as i64) } +// fn get_var_long pub fn get_var_long(data: &mut Vec) -> Result { get_var(data, 64) } +// fn convert_var_long pub fn convert_var_long(value: i64) -> Vec { convert_var(value) } +// fn get_var fn get_var(data: &mut Vec, size: u8) -> Result { let mut value: i64 = 0; let mut position: u8 = 0; @@ -307,6 +340,7 @@ fn get_var(data: &mut Vec, size: u8) -> Result { Ok(value) } +// fn convert_var fn convert_var(mut value: i64) -> Vec { let mut data: Vec = vec![]; loop { @@ -320,25 +354,108 @@ fn convert_var(mut value: i64) -> Vec { } } -pub fn get_string(data: &mut Vec) -> Result { - let length = get_var_int(data)? as usize; - let buffer = data[..length].to_vec(); - for _ in 0..length { data.remove(0); } - Ok(String::from_utf8_lossy(&buffer).to_string()) -} -pub fn convert_string(s: &str) -> Vec { - let length = s.len() as i32; - let mut data = convert_var_int(length); - data.append(&mut s.as_bytes().to_vec()); - data +// fn get_entity_metadata + +// fn convert_entity_metadata + +// struct MCSlot + +// fn get_slot + +// fn convert_slot + +// fn get_nbt_tag + +// fn convert_nbt_tag + +// struct MCPosition +pub struct MCPosition { + x: i32, + z: i32, + y: i16, } +impl MCPosition { + + // fn get_position + pub fn get(data: &mut Vec) -> Result { + let pos = get_long(data)?; + Ok(MCPosition { + x: (pos >> 38) as i32, + z: (pos << 26 >> 38) as i32, + y: (pos << 52 >> 52) as i16, + }) + } + // fn convert_position + pub fn convert(&self) -> Vec { + let pos: u64 = + ((self.x as u64 & 0x3FFFFFF) << 38) | + ((self.z as u64 & 0x3FFFFFF) << 12) | + (self.y as u64 & 0xFFF); + convert_long(pos as i64) + } + +} + +// fn get_angle <- u8 +pub fn get_angle(data: &mut Vec) -> Result { + get_unsigned_byte(data) +} +// fn convert_angle <- u8 +pub fn convert_angle(value: u8) -> Vec { + convert_unsigned_byte(value) +} + +// fn get_uuid +pub fn get_uuid(data: &mut Vec) -> Result { + if data.len() < std::mem::size_of::() { + return Err(Box::new(PacketError::RanOutOfBytes)) + } + Ok(i128::from_be_bytes( + data.drain(0..std::mem::size_of::()).as_slice().try_into()?)) +} +// fn convert_uuid +pub fn convert_uuid(value: i128) -> Vec { + value.to_be_bytes().to_vec() +} + +// trait MCTypeOptional + +// trait MCTypeArray + +pub trait MCTypeArray: Sized { + fn get(data: &mut Vec) -> Result; + fn convert(&self) -> Vec; + + fn get_array(data: &mut Vec) -> Result> { + let length = get_var_int(data)?; + let mut out_data: Vec = vec![]; + for _ in 0..length { + out_data.push(Self::get(data)?); + } + Ok(out_data) + } + + fn convert_array(array: &mut Vec) -> Vec { + let length = array.len() as i32; + let mut data: Vec = convert_var_int(length); + for element in array { + data.append(&mut Self::convert(element)); + } + data + } +} + +// trait MCTypeEnum + +// fn get_byte_array pub fn get_byte_array(data: &mut Vec) -> Result> { let length = get_var_int(data)? as usize; let buffer = data[..length].to_vec(); for _ in 0..length { data.remove(0); } Ok(buffer) } +// fn convert_byte_array pub fn convert_byte_array(mut s: &mut Vec) -> Vec { let length = s.len() as i32; let mut data = convert_var_int(length);