diff options
author | Joey Sacchini <joey@sacchini.net> | 2020-10-20 18:20:45 -0400 |
---|---|---|
committer | Joey Sacchini <joey@sacchini.net> | 2020-10-20 18:20:45 -0400 |
commit | 9facbf7d8a9c00b2413be325b23aeed786d7a7c1 (patch) | |
tree | f5260368a63f4202523ef4ab54c69eab55814220 | |
parent | fc08a93b6109373652d6775fe1bfb7d18cdb7575 (diff) | |
download | mcproto-rs-9facbf7d8a9c00b2413be325b23aeed786d7a7c1.tar.gz mcproto-rs-9facbf7d8a9c00b2413be325b23aeed786d7a7c1.tar.bz2 mcproto-rs-9facbf7d8a9c00b2413be325b23aeed786d7a7c1.zip |
lots of macro and type refactoring to simplify common patterns such as: position/location/rotation, counted array types (macro -> generics), rename some macros, and use macros to implement primitives (and other things in types.rs inc: VarInt/VarNum)
-rw-r--r-- | Cargo.lock | 19 | ||||
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | src/byte_order.rs | 8 | ||||
-rw-r--r-- | src/protocol.rs | 245 | ||||
-rw-r--r-- | src/serialize.rs | 4 | ||||
-rw-r--r-- | src/test_macros.rs | 2 | ||||
-rw-r--r-- | src/types.rs | 716 | ||||
-rw-r--r-- | src/v1_15_2.rs | 578 |
8 files changed, 710 insertions, 863 deletions
@@ -74,7 +74,6 @@ version = "0.2.0" dependencies = [ "base64", "flate2", - "paste", "rand", "serde", "serde_json", @@ -91,12 +90,6 @@ dependencies = [ ] [[package]] -name = "paste" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0520af26d4cf99643dbbe093a61507922b57232d9978d8491fdc8f7b44573c8c" - -[[package]] name = "ppv-lite86" version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -169,18 +162,18 @@ checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" [[package]] name = "serde" -version = "1.0.116" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96fe57af81d28386a513cbc6858332abc6117cfdb5999647c6444b8f43a370a5" +checksum = "b88fa983de7720629c9387e9f517353ed404164b1e482c970a90c1a4aaf7dc1a" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.116" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f630a6370fd8e457873b4bd2ffdae75408bc291ba72be773772a4c2a065d9ae8" +checksum = "cbd1ae72adb44aab48f325a02444a5fc079349a8d804c1fc922aed3f7454c74e" dependencies = [ "proc-macro2", "quote", @@ -200,9 +193,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.44" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e03e57e4fcbfe7749842d53e24ccb9aa12b7252dbe5e91d2acad31834c8b8fdd" +checksum = "ea9c5432ff16d6152371f808fb5a871cd67368171b09bb21b43df8e4a47a3556" dependencies = [ "proc-macro2", "quote", @@ -10,7 +10,6 @@ keywords = ["minecraft", "games", "protocol", "serialziers", "deserializers", "p serde_json = { version = "1.0", default-features = false, features = ["alloc"] } base64 = { version = "0.12.3", default-features = false, features = ["alloc"] } rand = { version = "0.7", optional = true } -paste = "1.0.1" [dependencies.serde] version = "1.0.116" diff --git a/src/byte_order.rs b/src/byte_order.rs index f1c40e3..2f65ca8 100644 --- a/src/byte_order.rs +++ b/src/byte_order.rs @@ -53,6 +53,10 @@ pub trait ByteOrder { Ok(Self::read_ushort(data)?.map(move |data| data as i16)) } + fn write_ubyte(v: u8) -> [u8; 1] { + [v] + } + fn read_ubyte(data: &[u8]) -> DeserializeResult<u8> { match data.split_first() { Some((byte, rest)) => Deserialized::ok(*byte, rest), @@ -60,6 +64,10 @@ pub trait ByteOrder { } } + fn write_byte(v: i8) -> [u8; 1] { + [v as u8] + } + fn read_byte(data: &[u8]) -> DeserializeResult<i8> { Ok(Self::read_ubyte(data)?.map(move |b| b as i8)) } diff --git a/src/protocol.rs b/src/protocol.rs index fb2c1fb..9781bb2 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -87,19 +87,7 @@ macro_rules! as_item { } #[macro_export] -macro_rules! __protocol_body_serialize_def_helper { - ($to: ident, $slf: ident, $fieldn: ident, $($field_rest: ident),+) => { - $to.serialize_other(&$slf.$fieldn)?; - $crate::__protocol_body_serialize_def_helper!($to, $slf, $($field_rest),+); - }; - - ( $to: ident, $slf: ident, $fieldn: ident ) => { - $to.serialize_other(&$slf.$fieldn) - }; -} - -#[macro_export] -macro_rules! __protocol_body_def_helper { +macro_rules! proto_struct { ($bodyt: ident { }) => { #[derive(Debug, Clone, PartialEq, Default)] pub struct $bodyt; @@ -123,15 +111,17 @@ macro_rules! __protocol_body_def_helper { } } }; - ($bodyt: ident { $($fname: ident: $ftyp: ty ),+ }) => { + ($bodyt: ident $(<$($g: ident),*>)? { + $($fname: ident: $ftyp: ty ),+ + }) => { $crate::as_item! { #[derive(Debug, Clone, PartialEq)] - pub struct $bodyt { + pub struct $bodyt$(<$($g),*> where $($g: alloc::fmt::Debug + Clone + PartialEq),*)? { $(pub $fname: $ftyp),+ } } - impl Serialize for $bodyt { + impl$(<$($g),*>)? Serialize for $bodyt$(<$($g),*> where $($g: Serialize + alloc::fmt::Debug + Clone + PartialEq),*)? { fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult { $( to.serialize_other(&self.$fname)?; @@ -140,7 +130,7 @@ macro_rules! __protocol_body_def_helper { } } - impl Deserialize for $bodyt { + impl$(<$($g),*>)? Deserialize for $bodyt$(<$($g),*> where $($g: Deserialize + alloc::fmt::Debug + Clone + PartialEq),*)? { fn mc_deserialize(_rest: &[u8]) -> DeserializeResult<'_, Self> { $(let Deserialized{ value: $fname, data: _rest } = <$ftyp>::mc_deserialize(_rest)?;)+ @@ -148,8 +138,23 @@ macro_rules! __protocol_body_def_helper { } } + #[allow(unused_parens)] + impl$(<$($g),*>)? From<($($ftyp),+)> for $bodyt$(<$($g),*>)? $(where $($g: alloc::fmt::Debug + Clone + PartialEq),*)? { + fn from(other: ($($ftyp),+)) -> Self { + let ($($fname),+) = other; + Self { $($fname),+ } + } + } + + #[allow(unused_parens)] + impl$(<$($g),*>)? From<$bodyt$(<$($g),*>)?> for ($($ftyp),+) $(where $($g: alloc::fmt::Debug + Clone + PartialEq),*)? { + fn from(other: $bodyt$(<$($g),*>)?) -> Self { + ($(other.$fname),+) + } + } + #[cfg(all(test, feature = "std"))] - impl TestRandom for $bodyt { + impl$(<$($g),*>)? TestRandom for $bodyt$(<$($g),*> where $($g: TestRandom + alloc::fmt::Debug + Clone + PartialEq),*)? { fn test_gen_random() -> Self { Self{ $($fname: <$ftyp>::test_gen_random()),+ } } @@ -159,7 +164,11 @@ macro_rules! __protocol_body_def_helper { #[macro_export] macro_rules! define_protocol { - ($packett: ident, $rawpackett: ident, $rawdt: ident, $directiont: ident, $statet: ident, $idt: ident, $idi: ident => { $($nam: ident, $id: literal, $state: ident, $direction: ident => $body: ident { $($fnam: ident: $ftyp: ty),* }),*}) => { + ($packett: ident, $rawpackett: ident, $rawdt: ident, $directiont: ident, $statet: ident, $idt: ident, $idi: ident => { + $($nam: ident, $id: literal, $state: ident, $direction: ident => $body: ident { + $($fnam: ident: $ftyp: ty),* }),* + } + ) => { #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct $idi { pub id: $idt, @@ -358,15 +367,15 @@ macro_rules! define_protocol { } } - $($crate::__protocol_body_def_helper!($body { $($fnam: $ftyp),* });)* + $($crate::proto_struct!($body { $($fnam: $ftyp),* });)* }; } #[macro_export] -macro_rules! count_num { - () => { 0 }; - ($item: tt) => { 1 }; - ($item: tt, $($rest: tt),+) => { 1 + count_num!($($rest),+) } +macro_rules! strip_plus { + (+ $($rest: tt)*) => { + $($rest)* + } } #[macro_export] @@ -415,6 +424,10 @@ macro_rules! proto_enum_with_type { } impl $typname { + pub const fn variant_count() -> usize { + crate::strip_plus!($(+ crate::instead_of_ident!($bval, 1))+) + } + pub fn deserialize_with_id<'a>(id: $typ, data: &'a[u8]) -> DeserializeResult<'a, Self> { match id.into() { $($bval => proto_enum_deserialize_variant!(data, $typname::$nam $(($bod))?)),*, @@ -450,7 +463,10 @@ macro_rules! proto_enum_with_type { #[cfg(all(test, feature = "std"))] impl TestRandom for $typname { fn test_gen_random() -> Self { - let mut idx: usize = (rand::random::<usize>() % (count_num!($($bval),+))) + 1; + let mut rng = rand::thread_rng(); + use rand::distributions::Distribution; + let distr = rand::distributions::Uniform::new(1, Self::variant_count() + 1); + let mut idx: usize = distr.sample(&mut rng); $( idx -= 1; if idx == 0 { @@ -511,6 +527,10 @@ macro_rules! proto_str_enum { } impl $typname { + pub const fn variant_count() -> usize { + crate::strip_plus!($(+ crate::instead_of_ident!($sval, 1))+) + } + pub fn name(&self) -> &str { match self { $($typname::$nam$((instead_of_ident!($bod, _)))? => $sval),+, @@ -554,7 +574,10 @@ macro_rules! proto_str_enum { #[cfg(all(test, feature = "std"))] impl TestRandom for $typname { fn test_gen_random() -> Self { - let mut idx: usize = (rand::random::<usize>() % (count_num!($($nam),+))) + 1; + let mut rng = rand::thread_rng(); + use rand::distributions::Distribution; + let distr = rand::distributions::Uniform::new(1, Self::variant_count() + 1); + let mut idx: usize = distr.sample(&mut rng); $( idx -= 1; if idx == 0 { @@ -569,38 +592,22 @@ macro_rules! proto_str_enum { #[macro_export] macro_rules! proto_byte_flag { - ($typname: ident, $($bval: literal :: $nam: ident),*) => { + ($typname: ident, $($bval: literal :: $isnam: ident $setnam: ident),*) => { #[derive(Clone, Copy, PartialEq, Eq, Debug, Default)] pub struct $typname(pub u8); impl $typname { - $(paste::paste! { - pub fn [<is_ $nam>](&self) -> bool { - self.0 & $bval != 0 - } - })* - - $(paste::paste! { - pub fn [<set_ $nam>](&mut self, value: bool) { - if value { - self.0 |= $bval; - } else { - self.0 ^= $bval; - } - } - })* - - $(paste::paste! { - pub fn [<with_ $nam>](mut self, value: bool) -> Self { - if value { - self.0 |= $bval; - } else { - self.0 ^= $bval; - } + $(pub fn $isnam(&self) -> bool { + self.0 & $bval != 0 + } - self + pub fn $setnam(&mut self, value: bool) { + if value { + self.0 |= $bval; + } else { + self.0 ^= $bval; } - })* + })+ } impl Serialize for $typname { @@ -619,137 +626,11 @@ macro_rules! proto_byte_flag { impl TestRandom for $typname { fn test_gen_random() -> Self { let mut out = <$typname>::default(); - $(paste::paste! { - out.[<set_ $nam>](rand::random::<bool>()); - })+ + $( + out.$setnam(rand::random::<bool>()); + )+ out } } } -} - -#[macro_export] -macro_rules! counted_array_type { - ($name: ident, $countert: ty, $tousize_fn: ident, $fromusize_fn: ident) => { - #[derive(Debug, Clone, PartialEq)] - pub struct $name<T> - where - T: Debug + Clone + PartialEq, - { - pub data: Vec<T>, - } - - impl<T> Serialize for $name<T> - where - T: Serialize + Debug + Clone + PartialEq, - { - fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult { - let count: $countert = $fromusize_fn(self.data.len()); - to.serialize_other(&count)?; - - for entry in &self.data { - to.serialize_other(entry)?; - } - - Ok(()) - } - } - - impl<T> Deserialize for $name<T> - where - T: Deserialize + Debug + Clone + PartialEq, - { - fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> { - let Deserialized { - value: raw_count, - mut data, - } = <$countert>::mc_deserialize(data)?; - let count: usize = $tousize_fn(raw_count); - - let mut out = Vec::with_capacity(count); - for _ in 0..count { - let Deserialized { - value: next, - data: rest, - } = T::mc_deserialize(data)?; - data = rest; - out.push(next); - } - - Deserialized::ok(Self { data: out }, data) - } - } - - impl<T> Into<Vec<T>> for $name<T> - where - T: Debug + Clone + PartialEq, - { - fn into(self) -> Vec<T> { - self.data - } - } - - impl<T> From<Vec<T>> for $name<T> - where - T: Debug + Clone + PartialEq, - { - fn from(data: Vec<T>) -> Self { - Self { data } - } - } - - impl<'a, T> IntoIterator for &'a mut $name<T> - where - T: Debug + Clone + PartialEq, - { - type Item = &'a mut T; - type IntoIter = alloc::slice::IterMut<'a, T>; - - fn into_iter(self) -> Self::IntoIter { - let data = &mut self.data; - data.iter_mut() - } - } - - impl<'a, T> IntoIterator for &'a $name<T> - where - T: Debug + Clone + PartialEq, - { - type Item = &'a T; - type IntoIter = alloc::slice::Iter<'a, T>; - - fn into_iter(self) -> Self::IntoIter { - let data = &self.data; - data.iter() - } - } - - impl<T> IntoIterator for $name<T> - where - T: Debug + Clone + PartialEq, - { - type Item = T; - type IntoIter = alloc::vec::IntoIter<T>; - - fn into_iter(self) -> Self::IntoIter { - self.data.into_iter() - } - } - - #[cfg(all(test, feature = "std"))] - impl<T> TestRandom for $name<T> - where - T: TestRandom + Debug + Clone + PartialEq, - { - fn test_gen_random() -> Self { - let elem_count: usize = rand::random::<usize>() % 32; - let mut out = Vec::with_capacity(elem_count); - for _ in 0..elem_count { - out.push(T::test_gen_random()); - } - - Self { data: out } - } - } - }; -} +}
\ No newline at end of file diff --git a/src/serialize.rs b/src/serialize.rs index c23ea09..9817797 100644 --- a/src/serialize.rs +++ b/src/serialize.rs @@ -1,4 +1,4 @@ -use alloc::{string::String, fmt, vec}; +use alloc::{string::String, fmt}; pub enum SerializeErr { FailedJsonEncode(String), @@ -34,7 +34,7 @@ pub trait Serializer: Sized { fn serialize_bytes(&mut self, data: &[u8]) -> SerializeResult; fn serialize_byte(&mut self, byte: u8) -> SerializeResult { - self.serialize_bytes(vec![byte].as_slice()) + self.serialize_bytes(&[byte]) } fn serialize_other<S: Serialize>(&mut self, other: &S) -> SerializeResult { diff --git a/src/test_macros.rs b/src/test_macros.rs index 1ab1716..1eeddb9 100644 --- a/src/test_macros.rs +++ b/src/test_macros.rs @@ -4,7 +4,7 @@ macro_rules! packet_test_cases { ($pnam: ident, $varnam: ident, $bodnam: ident, $testnam: ident, $benchnams: ident, $benchnamd: ident) => { #[test] fn $testnam() { - for k in 0..10 { + for k in 0..50 { let packet = $pnam::$varnam($bodnam::test_gen_random()); if k == 0 { println!("{:?}", packet); diff --git a/src/types.rs b/src/types.rs index ac2334c..f9b37e1 100644 --- a/src/types.rs +++ b/src/types.rs @@ -35,301 +35,148 @@ impl TestRandom for bool { } } -// u8 -impl Serialize for u8 { - fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult { - to.serialize_byte(*self) - } -} - -impl Deserialize for u8 { - fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> { - ProtoByteOrder::read_ubyte(data) - } -} - -#[cfg(all(test, feature = "std"))] -impl TestRandom for u8 { - fn test_gen_random() -> Self { - rand::random() - } -} - -// i8 -impl Serialize for i8 { - fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult { - to.serialize_byte(*self as u8) - } -} - -impl Deserialize for i8 { - fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> { - ProtoByteOrder::read_byte(data) - } -} - -#[cfg(all(test, feature = "std"))] -impl TestRandom for i8 { - fn test_gen_random() -> Self { - rand::random() - } -} - -// u16 -impl Serialize for u16 { - fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult { - let data = ProtoByteOrder::write_ushort(*self); - to.serialize_bytes(&data) - } -} - -impl Deserialize for u16 { - fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> { - ProtoByteOrder::read_ushort(data) - } -} - -#[cfg(all(test, feature = "std"))] -impl TestRandom for u16 { - fn test_gen_random() -> Self { - rand::random() - } -} - -// i16 -impl Serialize for i16 { - fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult { - let data = ProtoByteOrder::write_short(*self); - to.serialize_bytes(&data) - } -} - -impl Deserialize for i16 { - fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> { - ProtoByteOrder::read_short(data) - } -} - -#[cfg(all(test, feature = "std"))] -impl TestRandom for i16 { - fn test_gen_random() -> Self { - rand::random() - } -} - -// int -impl Serialize for i32 { - fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult { - let data = ProtoByteOrder::write_int(*self); - to.serialize_bytes(&data[..]) - } -} - -impl Deserialize for i32 { - fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> { - ProtoByteOrder::read_int(data) - } -} - -#[cfg(all(test, feature = "std"))] -impl TestRandom for i32 { - fn test_gen_random() -> Self { - rand::random() - } -} - -// long -impl Serialize for i64 { - fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult { - let data = ProtoByteOrder::write_long(*self); - to.serialize_bytes(&data[..]) - } -} - -impl Deserialize for i64 { - fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> { - ProtoByteOrder::read_long(data) - } -} - -#[cfg(all(test, feature = "std"))] -impl TestRandom for i64 { - fn test_gen_random() -> Self { - rand::random() - } -} - -// float -impl Serialize for f32 { - //noinspection ALL - fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult { - let data = ProtoByteOrder::write_float(*self); - to.serialize_bytes(&data[..]) - } -} - -impl Deserialize for f32 { - fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> { - ProtoByteOrder::read_float(data) - } -} - -#[cfg(all(test, feature = "std"))] -impl TestRandom for f32 { - fn test_gen_random() -> Self { - rand::random() - } -} - -// double -impl Serialize for f64 { - //noinspection ALL - fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult { - let data = ProtoByteOrder::write_double(*self); - to.serialize_bytes(&data[..]) - } -} +macro_rules! def_primitive { + ($nam: ty, $read: ident, $write: ident) => { + impl Serialize for $nam { + fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult { + let data = ProtoByteOrder::$write(*self); + to.serialize_bytes(&data) + } + } -impl Deserialize for f64 { - fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> { - ProtoByteOrder::read_double(data) - } -} + impl Deserialize for $nam { + fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> { + ProtoByteOrder::$read(data) + } + } -#[cfg(all(test, feature = "std"))] -impl TestRandom for f64 { - fn test_gen_random() -> Self { - rand::random() - } -} + #[cfg(all(test, feature = "std"))] + impl TestRandom for $nam { + fn test_gen_random() -> Self { + rand::random() + } + } + }; +} + +def_primitive!(u8, read_ubyte, write_ubyte); +def_primitive!(i8, read_byte, write_byte); +def_primitive!(u16, read_ushort, write_ushort); +def_primitive!(i16, read_short, write_short); +def_primitive!(u32, read_uint, write_uint); +def_primitive!(i32, read_int, write_int); +def_primitive!(u64, read_ulong, write_ulong); +def_primitive!(i64, read_long, write_long); +def_primitive!(u128, read_u2long, write_u2long); +def_primitive!(i128, read_2long, write_2long); +def_primitive!(f32, read_float, write_float); +def_primitive!(f64, read_double, write_double); // VAR INT AND VAR LONG -const VAR_INT_BYTES: usize = 5; -const VAR_LONG_BYTES: usize = 10; - -#[derive(Copy, Clone, PartialOrd, PartialEq, Debug, Default, Hash, Ord, Eq)] -pub struct VarInt(pub i32); - -impl Serialize for VarInt { - fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult { - let mut data = [0u8; VAR_INT_BYTES]; - to.serialize_bytes(serialize_var_num((self.0 as u32) as u64, &mut data)) - } -} - -impl Deserialize for VarInt { - fn mc_deserialize(orig_data: &[u8]) -> DeserializeResult<Self> { - Ok(deserialize_var_num(orig_data, VAR_INT_BYTES)?.map(move |v| VarInt(v as i32))) - } -} - -impl Into<i32> for VarInt { - fn into(self) -> i32 { - self.0 - } -} - -impl From<i32> for VarInt { - fn from(v: i32) -> Self { - Self(v) - } -} - -impl Into<usize> for VarInt { - fn into(self) -> usize { - self.0 as usize - } -} - -impl From<usize> for VarInt { - fn from(v: usize) -> Self { - Self(v as i32) - } -} - -impl fmt::Display for VarInt { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "VarInt({})", self.0) - } -} - -#[cfg(all(test, feature = "std"))] -impl TestRandom for VarInt { - fn test_gen_random() -> Self { - let out: i32 = rand::random(); - Self(out) - } -} +macro_rules! def_varnum { + ($nam: ident, $data_type: ty, $working_type: ty, $max_bytes: literal) => { + #[derive(Copy, Clone, PartialOrd, PartialEq, Default, Hash, Ord, Eq)] + pub struct $nam(pub $data_type); + + impl Serialize for $nam { + fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult { + let mut out = [0u8; $max_bytes]; + let mut v: $working_type = self.0 as $working_type; + let mut byte_idx = 0; + let mut has_more = true; + while has_more { + if byte_idx == out.len() { + panic!("tried to write too much data for {}", stringify!($nam)); + } + + let mut v_byte = (v & 0x7F) as u8; + v >>= 7; + has_more = v != 0; + if has_more { + v_byte |= 0x80; + } + + out[byte_idx] = v_byte; + byte_idx += 1; + } + + to.serialize_bytes(&out[..byte_idx]) + } + } -#[derive(Copy, Clone, PartialOrd, PartialEq, Debug, Default, Hash, Ord, Eq)] -pub struct VarLong(pub i64); + impl Deserialize for $nam { + fn mc_deserialize(orig_data: &[u8]) -> DeserializeResult<Self> { + let mut data = orig_data; + let mut v: $working_type = 0; + let mut bit_place: usize = 0; + let mut i: usize = 0; + let mut has_more = true; + + while has_more { + if i == $max_bytes { + return DeserializeErr::VarNumTooLong(Vec::from(&orig_data[..i])).into(); + } + let Deserialized { value: byte, data: rest } = ProtoByteOrder::read_ubyte(data)?; + data = rest; + has_more = byte & 0x80 != 0; + v |= ((byte as $working_type) & 0x7F) << bit_place; + bit_place += 7; + i += 1; + } + + Deserialized::ok(Self(v as $data_type), data) + } + } -impl Serialize for VarLong { - fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult { - let mut data = [0u8; VAR_LONG_BYTES]; - to.serialize_bytes(serialize_var_num(self.0 as u64, &mut data)) - } -} + impl From<$data_type> for $nam { + fn from(other: $data_type) -> Self { + Self(other) + } + } -impl Deserialize for VarLong { - fn mc_deserialize(orig_data: &[u8]) -> DeserializeResult<'_, Self> { - Ok(deserialize_var_num(orig_data, VAR_LONG_BYTES)?.map(move |v| VarLong(v as i64))) - } -} + impl From<$nam> for $data_type { + fn from(other: $nam) -> Self { + other.0 + } + } -#[cfg(all(test, feature = "std"))] -impl TestRandom for VarLong { - fn test_gen_random() -> Self { - let out: i64 = rand::random(); - Self(out) - } -} + impl core::ops::Deref for $nam { + type Target = $data_type; -fn serialize_var_num(data: u64, out: &mut [u8]) -> &[u8] { - let mut v: u64 = data; - let mut byte_idx = 0; - let mut has_more = true; - while has_more { - if byte_idx == out.len() { - panic!("tried to write too much data for Var num"); + fn deref(&self) -> &Self::Target { + &self.0 + } } - let mut v_byte = (v & 0x7F) as u8; - v >>= 7; - has_more = v != 0; - if has_more { - v_byte |= 0x80; + impl fmt::Display for $nam { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0) + } } - out[byte_idx] = v_byte; - byte_idx += 1; - } - - &out[..byte_idx] -} - -fn deserialize_var_num(orig_data: &[u8], max_bytes: usize) -> DeserializeResult<u64> { - let mut data = orig_data; - let mut v: u64 = 0; - let mut bit_place: usize = 0; - let mut i: usize = 0; - let mut has_more = true; + impl fmt::Debug for $nam { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(stringify!($nam))?; + f.write_str("(")?; + write!(f, "{}", self.0)?; + f.write_str(")")?; + Ok(()) + } + } - while has_more { - if i == max_bytes { - return DeserializeErr::VarNumTooLong(Vec::from(&orig_data[..i])).into(); + #[cfg(all(test, feature = "std"))] + impl TestRandom for $nam { + fn test_gen_random() -> Self { + let out: $data_type = rand::random(); + Self(out) + } } - let Deserialized { value: byte, data: rest} = ProtoByteOrder::read_ubyte(data)?; - data = rest; - has_more = byte & 0x80 != 0; - v |= ((byte as u64) & 0x7F) << bit_place; - bit_place += 7; - i += 1; } - - Deserialized::ok(v, data) } +def_varnum!(VarInt, i32, u32, 5); +def_varnum!(VarLong, i64, u64, 10); + // STRING impl Serialize for String { fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult { @@ -603,8 +450,8 @@ impl BytesSerializer { } impl<T> Serialize for Option<T> -where - T: Serialize, + where + T: Serialize, { fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult { match self { @@ -618,8 +465,8 @@ where } impl<T> Deserialize for Option<T> -where - T: Deserialize, + where + T: Deserialize, { fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> { bool::mc_deserialize(data)?.and_then(move |is_present, data| { @@ -634,8 +481,8 @@ where #[cfg(all(test, feature = "std"))] impl<T> TestRandom for Option<T> -where - T: TestRandom, + where + T: TestRandom, { fn test_gen_random() -> Self { let is_present: bool = rand::random(); @@ -649,13 +496,13 @@ where // SLOT #[derive(Debug, PartialEq, Clone)] -pub struct Slot { +pub struct ItemStack { pub item_id: VarInt, pub item_count: i8, pub nbt: Option<nbt::NamedTag>, } -impl Serialize for Slot { +impl Serialize for ItemStack { fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult { to.serialize_other(&self.item_id)?; to.serialize_other(&self.item_count)?; @@ -666,10 +513,10 @@ impl Serialize for Slot { } } -impl Deserialize for Slot { +impl Deserialize for ItemStack { fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> { - let Deserialized { value: item_id, data} = VarInt::mc_deserialize(data)?; - let Deserialized { value: item_count, data} = i8::mc_deserialize(data)?; + let Deserialized { value: item_id, data } = VarInt::mc_deserialize(data)?; + let Deserialized { value: item_count, data } = i8::mc_deserialize(data)?; if data.is_empty() { return Err(DeserializeErr::Eof); } @@ -682,8 +529,7 @@ impl Deserialize for Slot { data: rest, }, _ => nbt::read_named_tag(data)?.map(move |tag| Some(tag)), - } - .map(move |nbt| Slot { + }.map(move |nbt| Self { item_id, item_count, nbt, @@ -692,7 +538,7 @@ impl Deserialize for Slot { } #[cfg(all(test, feature = "std"))] -impl TestRandom for Slot { +impl TestRandom for ItemStack { fn test_gen_random() -> Self { let item_id = VarInt::test_gen_random(); let item_count = i8::test_gen_random() % 65; @@ -706,6 +552,292 @@ impl TestRandom for Slot { } } +pub type Slot = Option<ItemStack>; + +macro_rules! def_vector_type { + ($name: ident, $($fnam: ident),+) => { + crate::as_item! { + pub struct $name<T> { + $(pub $fnam: T),+ + } + } + + impl<T> Serialize for $name<T> where T: Serialize { + fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult { + $( + to.serialize_other(&self.$fnam)?; + )+ + Ok(()) + } + } + + impl<T> Deserialize for $name<T> where T: Deserialize { + fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> { + $(let Deserialized { value: $fnam, data } = T::mc_deserialize(data)?;)+ + Deserialized::ok(Self { $($fnam),+ }, data) + } + } + + #[cfg(all(test, feature = "std"))] + impl<T> TestRandom for $name<T> where T: TestRandom { + fn test_gen_random() -> Self { + Self { + $($fnam: T::test_gen_random(),)+ + } + } + } + + impl<T> Clone for $name<T> where T: Clone { + fn clone(&self) -> Self { + Self { + $($fnam: self.$fnam.clone(),)+ + } + } + } + + impl<T> Copy for $name<T> where T: Copy {} + + impl<T, Rhs> PartialEq<$name<Rhs>> for $name<T> where T: PartialEq<Rhs> { + fn eq(&self, other: &$name<Rhs>) -> bool { + $(self.$fnam.eq(&other.$fnam)) && + + } + + fn ne(&self, other: &$name<Rhs>) -> bool { + $(self.$fnam.ne(&other.$fnam)) || + + } + } + + impl<T> core::hash::Hash for $name<T> where T: core::hash::Hash { + fn hash<H: core::hash::Hasher>(&self, state: &mut H) { + $(self.$fnam.hash(state);)+ + } + } + + impl<T> fmt::Debug for $name<T> where T: fmt::Debug { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(stringify!($name))?; + f.write_str("( ")?; + $( + f.write_str(stringify!($fnam))?; + f.write_str("=")?; + self.$fnam.fmt(f)?; + f.write_str(" ")?; + )+ + f.write_str(")")?; + Ok(()) + } + } + + impl<T> fmt::Display for $name<T> where T: fmt::Display { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(stringify!($name))?; + f.write_str("( ")?; + $( + f.write_str(stringify!($fnam))?; + f.write_str("=")?; + self.$fnam.fmt(f)?; + f.write_str(" ")?; + )+ + f.write_str(")")?; + Ok(()) + } + } + + impl<T> From<$name<T>> for ($(crate::instead_of_ident!($fnam, T)),+) { + fn from(other: $name<T>) -> Self { + ($(other.$fnam),+) + } + } + + impl<'a, T> From<&'a $name<T>> for ($(&'a crate::instead_of_ident!($fnam, T)),+) { + fn from(other: &'a $name<T>) -> Self { + ($(&other.$fnam),+) + } + } + + impl<'a, T> From<&'a $name<T>> for ($(crate::instead_of_ident!($fnam, T)),+) where T: Clone { + fn from(other: &'a $name<T>) -> Self { + ($(other.$fnam.clone()),+) + } + } + + impl<T> From<($(crate::instead_of_ident!($fnam, T)),+)> for $name<T> { + fn from(other: ($(crate::instead_of_ident!($fnam, T)),+)) -> Self { + let ($($fnam),+) = other; + Self { $($fnam),+ } + } + } + + impl<'a, T> From<&'a ($(crate::instead_of_ident!($fnam, T)),+)> for $name<T> where T: Clone { + fn from(other: &'a ($(crate::instead_of_ident!($fnam, T)),+)) -> Self { + let ($($fnam),+) = other; + $(let $fnam = $fnam.clone();)+ + Self { $($fnam),+ } + } + } + + impl<'a, T> From<($(&'a crate::instead_of_ident!($fnam, T)),+)> for $name<T> where T: Clone { + fn from(other: ($(&'a crate::instead_of_ident!($fnam, T)),+)) -> Self { + let ($($fnam),+) = other; + $(let $fnam = $fnam.clone();)+ + Self { $($fnam),+ } + } + } + + impl<T> $name<T> { + pub fn from_other<O>(other: O) -> Self where O: Into<($(crate::instead_of_ident!($fnam, T)),+)> { + let ($($fnam),+) = other.into(); + Self { $($fnam,)+ } + } + + pub fn as_other<O>(&self) -> O where O: From<($(crate::instead_of_ident!($fnam, T)),+)>, T: Clone { + O::from(self.into()) + } + + pub fn into_other<O>(self) -> O where O: From<($(crate::instead_of_ident!($fnam, T)),+)> { + O::from(self.into()) + } + } + }; +} + +def_vector_type!(Vec3, x, y, z); +def_vector_type!(Vec2, x, y); +def_vector_type!(ChunkPosition, x, z); +pub type TopDownPosition<T> = ChunkPosition<T>; +def_vector_type!(EntityRotation, yaw, pitch); + +proto_struct!(EntityLocation<P, R> { + position: Vec3<P>, + rotation: EntityRotation<R> +}); + +#[derive(Clone, Debug, PartialEq)] +pub struct CountedArray<E, C> { + data: Vec<E>, + _counter_type: core::marker::PhantomData<C>, +} + +pub trait ArrayCounter: Serialize + Deserialize { + + fn as_count(&self) -> usize; + + fn from_count(count: usize) -> Self; +} + +impl<E, C> Serialize for CountedArray<E, C> where E: Serialize, C: ArrayCounter { + fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult { + let count = C::from_count(self.data.len()); + to.serialize_other(&count)?; + for elem in &self.data { + to.serialize_other(elem)?; + } + Ok(()) + } +} + +impl<E, C> Deserialize for CountedArray<E, C> where E: Deserialize, C: ArrayCounter { + fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> { + let Deserialized { value: count, mut data } = C::mc_deserialize(data)?; + let count = count.as_count(); + let mut elems = Vec::with_capacity(count); + for _ in 0..count { + let Deserialized { value: elem, data: rest } = E::mc_deserialize(data)?; + data = rest; + elems.push(elem); + } + + Deserialized::ok(Self { + data: elems, + _counter_type: core::marker::PhantomData, + }, data) + } +} + +impl<E, C> core::ops::Deref for CountedArray<E, C> where C: ArrayCounter { + type Target = Vec<E>; + + fn deref(&self) -> &Self::Target { + &self.data + } +} + +impl<E, C> core::ops::DerefMut for CountedArray<E, C> where C: ArrayCounter { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.data + } +} + +impl<E, C> From<CountedArray<E, C>> for Vec<E> where C: ArrayCounter { + fn from(other: CountedArray<E, C>) -> Self { + other.data + } +} + +impl<E, C> From<Vec<E>> for CountedArray<E, C> where C: ArrayCounter { + fn from(data: Vec<E>) -> Self { + Self { + data, + _counter_type: core::marker::PhantomData, + } + } +} + +#[cfg(all(test, feature = "std"))] +impl<E, C> TestRandom for CountedArray<E, C> + where E: TestRandom, C: ArrayCounter +{ + fn test_gen_random() -> Self { + let elem_count: usize = rand::random::<usize>() % 32; + let mut out = Vec::with_capacity(elem_count); + for _ in 0..elem_count { + out.push(E::test_gen_random()); + } + + out.into() + } +} + +impl ArrayCounter for VarInt { + fn as_count(&self) -> usize { + self.0 as usize + } + + fn from_count(count: usize) -> Self { + Self(count as i32) + } +} + +impl ArrayCounter for i16 { + fn as_count(&self) -> usize { + (*self) as usize + } + + fn from_count(count: usize) -> Self { + count as i16 + } +} + +impl ArrayCounter for i32 { + fn as_count(&self) -> usize { + (*self) as usize + } + + fn from_count(count: usize) -> Self { + count as i32 + } +} + +impl ArrayCounter for i8 { + fn as_count(&self) -> usize { + (*self) as usize + } + + fn from_count(count: usize) -> Self { + count as i8 + } +} + #[cfg(test)] mod tests { use super::*; @@ -815,7 +947,7 @@ mod tests { root: nbt::Tag::Compound(alloc::vec![ nbt::Tag::String("test 123".to_owned()).with_name("abc 123") ]) - .with_name("root"), + .with_name("root"), }) } diff --git a/src/v1_15_2.rs b/src/v1_15_2.rs index 150fbe6..81079de 100644 --- a/src/v1_15_2.rs +++ b/src/v1_15_2.rs @@ -70,8 +70,8 @@ define_protocol!(Packet578, RawPacket578, RawPacket578Body, PacketDirection, Sta }, LoginEncryptionRequest, 0x01, Login, ClientBound => LoginEncryptionRequestSpec { server_id: String, - public_key: VarIntCountedArray<u8>, - verify_token: VarIntCountedArray<u8> + public_key: CountedArray<u8, VarInt>, + verify_token: CountedArray<u8, VarInt> }, LoginSuccess, 0x02, Login, ClientBound => LoginSuccessSpec { uuid_string: String, @@ -89,8 +89,8 @@ define_protocol!(Packet578, RawPacket578, RawPacket578Body, PacketDirection, Sta name: String }, LoginEncryptionResponse, 0x01, Login, ServerBound => LoginEncryptionResponseSpec { - shared_secret: VarIntCountedArray<u8>, - verify_token: VarIntCountedArray<u8> + shared_secret: CountedArray<u8, VarInt>, + verify_token: CountedArray<u8, VarInt> }, LoginPluginResponse, 0x02, Login, ServerBound => LoginPluginResponseSpec { message_id: VarInt, @@ -104,43 +104,29 @@ define_protocol!(Packet578, RawPacket578, RawPacket578Body, PacketDirection, Sta entity_id: VarInt, object_uuid: UUID4, entity_type: VarInt, - x: f64, - y: f64, - z: f64, + position: Vec3<f64>, pitch: Angle, yaw: Angle, data: i32, - velocity_x: i16, - velocity_y: i16, - velocity_z: i16 + velocity: Vec3<i16> }, PlaySpawnExperienceOrb, 0x01, Play, ClientBound => PlaySpawnExperienceOrbSpec { entity_id: VarInt, - x: f64, - y: f64, - z: f64, + position: Vec3<f64>, count: i16 }, PlaySpawnWeatherEntity, 0x02, Play, ClientBound => PlaySpawnWeatherEntitySpec { entity_id: VarInt, entity_type: u8, - x: f64, - y: f64, - z: f64 + position: Vec3<f64> }, PlaySpawnLivingEntity, 0x03, Play, ClientBound => PlaySpawnLivingEntitySpec { entity_id: VarInt, entity_uuid: UUID4, entity_type: VarInt, - x: f64, - y: f64, - z: f64, - yaw: Angle, - pitch: Angle, + location: EntityLocation<f64, Angle>, head_pitch: Angle, - velocity_x: i16, - velocity_y: i16, - velocity_z: i16 + velocity: Vec3<i16> }, PlaySpawnPainting, 0x04, Play, ClientBound => PlaySpawnPaintingSpec { entity_id: VarInt, @@ -152,18 +138,14 @@ define_protocol!(Packet578, RawPacket578, RawPacket578Body, PacketDirection, Sta PlaySpawnPlayer, 0x05, Play, ClientBound => PlaySpawnPlayerSpec { entity_id: VarInt, uuid: UUID4, - x: f64, - y: f64, - z: f64, - yaw: Angle, - pitch: Angle + location: EntityLocation<f64, Angle> }, PlayEntityAnimation, 0x06, Play, ClientBound => PlayEntityAnimationSpec { entity_id: VarInt, animation: EntityAnimationKind }, PlayStatistics, 0x07, Play, ClientBound => PlayStatisticsSpec { - entries: VarIntCountedArray<Statistic> + entries: CountedArray<Statistic, VarInt> }, PlayAcknowledgePlayerDigging, 0x08, Play, ClientBound => PlayAcknowledgePlayerDiggingSpec { location: IntPosition, @@ -204,18 +186,17 @@ define_protocol!(Packet578, RawPacket578, RawPacket578Body, PacketDirection, Sta position: ChatPosition }, PlayMultiBlockChange, 0x10, Play, ClientBound => PlayMultiBlockChangeSpec { - chunk_x: i32, - chunk_z: i32, - changes: VarIntCountedArray<MultiBlockChangeRecord> + chunk: ChunkPosition<i32>, + changes: CountedArray<MultiBlockChangeRecord, VarInt> }, PlayTabComplete, 0x11, Play, ClientBound => PlayTabCompleteSpec { id: VarInt, start: VarInt, length: VarInt, - matches: VarIntCountedArray<TabCompleteMatch> + matches: CountedArray<TabCompleteMatch, VarInt> }, PlayDeclareCommands, 0x12, Play, ClientBound => PlayDeclareCommandsSpec { - nodes: VarIntCountedArray<CommandNodeSpec>, + nodes: CountedArray<CommandNodeSpec, VarInt>, root_index: VarInt }, PlayServerWindowConfirmation, 0x13, Play, ClientBound => PlayServerWindowConfirmationSpec { @@ -228,7 +209,7 @@ define_protocol!(Packet578, RawPacket578, RawPacket578Body, PacketDirection, Sta }, PlayWindowItems, 0x15, Play, ClientBound => PlayWindowItemsSpec { window_id: u8, - slots: ShortCountedArray<Option<Slot>> + slots: CountedArray<Slot, i16> }, PlayWindowProperty, 0x16, Play, ClientBound => PlayWindowPropertySpec { window_id: u8, @@ -238,7 +219,7 @@ define_protocol!(Packet578, RawPacket578, RawPacket578Body, PacketDirection, Sta PlaySetSlot, 0x17, Play, ClientBound => PlaySetSlotSpec { window_id: u8, slow: i16, - slot_data: Option<Slot> + slot_data: Slot }, PlaySetCooldown, 0x18, Play, ClientBound => PlaySetCooldownSpec { item_id: VarInt, @@ -251,9 +232,7 @@ define_protocol!(Packet578, RawPacket578, RawPacket578Body, PacketDirection, Sta PlayNamedSoundEffect, 0x1A, Play, ClientBound => PlayNamedSoundEffectSpec { sound_name: String, sound_category: SoundCategory, - position_x: FixedInt, - position_y: FixedInt, - position_z: FixedInt, + position: Vec3<FixedInt>, volume: f32, pitch: f32 }, @@ -265,18 +244,13 @@ define_protocol!(Packet578, RawPacket578, RawPacket578Body, PacketDirection, Sta raw_status: u8 // todo deal with the gigantic table }, PlayExplosion, 0x1D, Play, ClientBound => PlayExplosionSpec { - x: f32, - y: f32, - z: f32, + position: Vec3<f32>, strength: f32, - records: IntCountedArray<ExplosionRecord>, - player_motion_x: f32, - player_motion_y: f32, - player_motion_z: f32 + records: CountedArray<Vec3<i8>, i32>, + player_motion: Vec3<f32> }, PlayUnloadChunk, 0x1E, Play, ClientBound => PlayUnloadChunkSpec { - x: i32, - y: i32 + position: ChunkPosition<i32> }, PlayChangeGameState, 0x1F, Play, ClientBound => PlayChangeGameStateSpec { reason: GameChangeReason @@ -301,18 +275,13 @@ define_protocol!(Packet578, RawPacket578, RawPacket578Body, PacketDirection, Sta PlayParticle, 0x24, Play, ClientBound => PlayParticleSpec { particle_id: i32, long_distance: bool, - x: f64, - y: f64, - z: f64, - offset_x: f32, - offset_y: f32, - offset_z: f32, + position: Vec3<f64>, + offset: Vec3<f32>, particle_data: i32, data: RemainingBytes // todo }, PlayUpdateLight, 0x25, Play, ClientBound => PlayUpdateLightSpec { - chunk_x: VarInt, - chunk_z: VarInt, + chunk: ChunkPosition<VarInt>, update: LightingUpdateSpec }, PlayJoinGame, 0x26, Play, ClientBound => PlayJoinGameSpec { @@ -331,12 +300,12 @@ define_protocol!(Packet578, RawPacket578, RawPacket578Body, PacketDirection, Sta scale: i8, tracking_position: bool, locked: bool, - icons: VarIntCountedArray<MapIconSpec>, + icons: CountedArray<MapIconSpec, VarInt>, columns: MapColumns }, PlayTradeList, 0x28, Play, ClientBound => PlayTradeListSpec { window_id: VarInt, - trades: ByteCountedArray<TradeSpec>, + trades: CountedArray<TradeSpec, i8>, villager_level: VarInt, experience: VarInt, regular_villager: bool, @@ -344,35 +313,24 @@ define_protocol!(Packet578, RawPacket578, RawPacket578Body, PacketDirection, Sta }, PlayEntityPosition, 0x29, Play, ClientBound => PlayEntityPositionSpec { entity_id: VarInt, - delta_x: i16, - delta_y: i16, - delta_z: i16, + delta: Vec3<i16>, on_ground: bool }, PlayEntityPositionAndRotation, 0x2A, Play, ClientBound => PlayEntityPositionAndRotationSpec { entity_id: VarInt, - delta_x: i16, - delta_y: i16, - delta_z: i16, - yaw: Angle, - pitch: Angle, + delta: EntityLocation<i16, Angle>, on_ground: bool }, PlayEntityRotation, 0x2B, Play, ClientBound => PlayEntityRotationSpec { entity_id: VarInt, - yaw: Angle, - pitch: Angle, + rotation: EntityRotation<Angle>, on_ground: bool }, PlayEntityMovement, 0x2C, Play, ClientBound => PlayEntityMovementSpec { entity_id: VarInt }, PlayServerVehicleMove, 0x2D, Play, ClientBound => PlayEntityVehicleMoveSpec { - x: f64, - y: f64, - z: f64, - yaw: f32, - pitch: f32 + location: EntityLocation<f64, f32> }, PlayOpenBook, 0x2E, Play, ClientBound => PlayOpenBookSpec { hand: Hand @@ -402,17 +360,11 @@ define_protocol!(Packet578, RawPacket578, RawPacket578Body, PacketDirection, Sta }, PlayFacePlayer, 0x35, Play, ClientBound => PlayFacePlayerSpec { face_kind: FacePlayerKind, - target_x: f64, - target_y: f64, - target_z: f64, + target: Vec3<f64>, entity: Option<FacePlayerEntityTarget> }, PlayServerPlayerPositionAndLook, 0x36, Play, ClientBound => PlayServerPlayerPositionAndLookSpec { - x: f64, - y: f64, - z: f64, - yaw: f32, - pitch: f32, + location: EntityLocation<f64, f32>, flags: PositionAndLookFlags, teleport_id: VarInt }, @@ -422,11 +374,11 @@ define_protocol!(Packet578, RawPacket578, RawPacket578Body, PacketDirection, Sta crafting_book_active: bool, smelting_book_open: bool, smelting_book_active: bool, - recipe_ids: VarIntCountedArray<String>, + recipe_ids: CountedArray<String, VarInt>, other_recipe_ids: RemainingBytes // todo }, PlayDestroyEntities, 0x38, Play, ClientBound => PlayDestroyEntitiesSpec { - entity_ids: VarIntCountedArray<VarInt> + entity_ids: CountedArray<VarInt, VarInt> }, PlayRemoveEntityEffect, 0x39, Play, ClientBound => PlayRemoveEntityEffectSpec { entity_id: VarInt, @@ -459,8 +411,7 @@ define_protocol!(Packet578, RawPacket578, RawPacket578Body, PacketDirection, Sta slot: i8 }, PlayUpdateViewPosition, 0x41, Play, ClientBound => PlayUpdateViewPositionSpec { - chunk_x: VarInt, - chunk_z: VarInt + chunk: ChunkPosition<VarInt> }, PlayUpdateViewDistance, 0x42, Play, ClientBound => PlayUpdateViewDistanceSpec { view_distance: VarInt @@ -479,14 +430,12 @@ define_protocol!(Packet578, RawPacket578, RawPacket578Body, PacketDirection, Sta }, PlayEntityVelocity, 0x46, Play, ClientBound => PlayEntityVelocitySpec { entity_id: VarInt, - velocity_x: i16, - velocity_y: i16, - velocity_z: i16 + velocity: Vec3<i16> }, PlayEntityEquipment, 0x47, Play, ClientBound => PlayEntityEquiptmentSpec { entity_id: VarInt, slot: EquipmentSlot, - item: Option<Slot> + item: Slot }, PlaySetExperience, 0x48, Play, ClientBound => PlaySetExperienceSpec { experience_bar: f32, @@ -504,7 +453,7 @@ define_protocol!(Packet578, RawPacket578, RawPacket578Body, PacketDirection, Sta }, PlaySetPassengers, 0x4B, Play, ClientBound => PlaySetPassengersSpec { entity_id: VarInt, - passenger_entitiy_ids: VarIntCountedArray<VarInt> + passenger_entitiy_ids: CountedArray<VarInt, VarInt> }, PlayTeams, 0x4C, Play, ClientBound => PlayTeamsSpec { team_name: String, @@ -534,9 +483,7 @@ define_protocol!(Packet578, RawPacket578, RawPacket578Body, PacketDirection, Sta PlaySoundEffect, 0x52, Play, ClientBound => PlaySoundEffectSpec { sound_id: VarInt, sound_category: SoundCategory, - position_x: FixedInt, - position_y: FixedInt, - position_z: FixedInt, + position: Vec3<FixedInt>, volume: f32, pitch: f32 }, @@ -558,22 +505,18 @@ define_protocol!(Packet578, RawPacket578, RawPacket578Body, PacketDirection, Sta }, PlayEntityTeleport, 0x57, Play, ClientBound => PlayEntityTeleportSpec { entity_id: VarInt, - x: f64, - y: f64, - z: f64, - yaw: Angle, - pitch: Angle, + location: EntityLocation<f64, Angle>, on_ground: bool }, PlayAdvancements, 0x58, Play, ClientBound => PlayAdvancementsSpec { reset: bool, - mappings: VarIntCountedArray<AdvancementMappingEntrySpec>, - identifiers: VarIntCountedArray<String>, - progress: VarIntCountedArray<AdvancementProgressEntrySpec> + mappings: CountedArray<AdvancementMappingEntrySpec, VarInt>, + identifiers: CountedArray<String, VarInt>, + progress: CountedArray<AdvancementProgressEntrySpec, VarInt> }, PlayEntityProperties, 0x59, Play, ClientBound => PlayEntityPropertiesSpec { entity_id: VarInt, - properties: IntCountedArray<EntityPropertySpec> + properties: CountedArray<EntityPropertySpec, i32> }, PlayEntityEffect, 0x5A, Play, ClientBound => PlayEntityEffectSpec { entity_id: VarInt, @@ -583,13 +526,13 @@ define_protocol!(Packet578, RawPacket578, RawPacket578Body, PacketDirection, Sta flags: EntityEffectFlags }, PlayDeclareRecipes, 0x5B, Play, ClientBound => PlayDeclareRecipesSpec { - recipes: VarIntCountedArray<RecipeSpec> + recipes: CountedArray<RecipeSpec, VarInt> }, PlayTags, 0x5C, Play, ClientBound => PlayTagsSpec { - block_tags: VarIntCountedArray<TagSpec>, - item_tags: VarIntCountedArray<TagSpec>, - fluid_tags: VarIntCountedArray<TagSpec>, - entity_tags: VarIntCountedArray<TagSpec> + block_tags: CountedArray<TagSpec, VarInt>, + item_tags: CountedArray<TagSpec, VarInt>, + fluid_tags: CountedArray<TagSpec, VarInt>, + entity_tags: CountedArray<TagSpec, VarInt> }, // play server bound @@ -640,7 +583,7 @@ define_protocol!(Packet578, RawPacket578, RawPacket578Body, PacketDirection, Sta button: i8, action_number: i16, mode: InventoryOperationMode, - clicked_item: Option<Slot> + clicked_item: Slot }, PlayClientCloseWindow, 0x0A, Play, ServerBound => PlayClientCloseWindowSpec { window_id: u8 @@ -650,7 +593,7 @@ define_protocol!(Packet578, RawPacket578, RawPacket578Body, PacketDirection, Sta data: RemainingBytes }, PlayEditBook, 0x0C, Play, ServerBound => PlayEditBookSpec { - new_book: Option<Slot>, + new_book: Slot, is_signing: bool, hand: Hand }, @@ -665,33 +608,22 @@ define_protocol!(Packet578, RawPacket578, RawPacket578Body, PacketDirection, Sta locked: bool }, PlayPlayerPosition, 0x11, Play, ServerBound => PlayPlayerPositionSpec { - x: f64, - feet_y: f64, - z: f64, + feet_position: Vec3<f64>, on_ground: bool }, PlayClientPlayerPositionAndRotation, 0x12, Play, ServerBound => PlayClientPlayerPositionAndRotationSpec { - x: f64, - feet_y: f64, - z: f64, - yaw: f32, - pitch: f32, + feet_location: EntityLocation<f64, f32>, on_ground: bool }, PlayPlayerRotation, 0x13, Play, ServerBound => PlayPlayerRotationSpec { - yaw: f32, - pitch: f32, + rotation: EntityRotation<f32>, on_ground: bool }, PlayPlayerMovement, 0x14, Play, ServerBound => PlayPlayerMovementSpec { on_ground: bool }, PlayClientVehicleMove, 0x15, Play, ServerBound => PlayClientVehicleMoveSpec { - x: f64, - y: f64, - z: f64, - yaw: f32, - pitch: f32 + location: EntityLocation<f64, f32> }, PlaySteerBoat, 0x16, Play, ServerBound => PlaySteerBoatSpec { left_paddle_turning: bool, @@ -760,7 +692,7 @@ define_protocol!(Packet578, RawPacket578, RawPacket578Body, PacketDirection, Sta }, PlayCreativeInventoryAction, 0x26, Play, ServerBound => PlayCreativeInventoryActionSpec { slot: i16, - clicked_item: Option<Slot> + clicked_item: Slot }, PlayUpdateJigsawBlock, 0x27, Play, ServerBound => PlayUpdateJigsawBlockSpec { location: IntPosition, @@ -773,12 +705,8 @@ define_protocol!(Packet578, RawPacket578, RawPacket578Body, PacketDirection, Sta action: UpdateStructureBlockAction, mode: UpdateStructureBlockMode, name: String, - offset_x: i8, - offset_y: i8, - offset_z: i8, - size_x: i8, - size_y: i8, - size_z: i8, + offset: Vec3<i8>, + size: Vec3<i8>, mirror: UpdateStructureBlockMirror, rotation: UpdateStructureBlockRotation, metadata: String, @@ -803,9 +731,7 @@ define_protocol!(Packet578, RawPacket578, RawPacket578Body, PacketDirection, Sta hand: Hand, location: IntPosition, face: DiggingFace, - cursor_position_x: f32, - cursor_position_y: f32, - cursor_position_z: f32, + cursor_position: Vec3<f32>, inside_block: bool }, PlayUseItem, 0x2D, Play, ServerBound => PlayUseItemSpec { @@ -821,47 +747,6 @@ proto_byte_enum!(HandshakeNextState, 0x02 :: Login ); -fn varint_to_usize(v: VarInt) -> usize { - v.into() -} - -fn varint_from_usize(u: usize) -> VarInt { - u.into() -} -counted_array_type!( - VarIntCountedArray, - VarInt, - varint_to_usize, - varint_from_usize -); - -fn i16_to_usize(v: i16) -> usize { - v as usize -} - -fn i16_from_usize(u: usize) -> i16 { - u as i16 -} -counted_array_type!(ShortCountedArray, i16, i16_to_usize, i16_from_usize); - -fn i32_to_usize(v: i32) -> usize { - v as usize -} - -fn i32_from_usize(u: usize) -> i32 { - u as i32 -} -counted_array_type!(IntCountedArray, i32, i32_to_usize, i32_from_usize); - -fn i8_to_usize(v: i8) -> usize { - v as usize -} - -fn i8_from_usize(u: usize) -> i8 { - u as i8 -} -counted_array_type!(ByteCountedArray, i8, i8_to_usize, i8_from_usize); - #[derive(Debug, Clone, PartialEq)] pub struct RemainingBytes { pub data: Vec<u8>, @@ -990,7 +875,7 @@ proto_varint_enum!(StatisticKind, 0x31 :: OpenShulkerBox ); -__protocol_body_def_helper!(Statistic { +proto_struct!(Statistic { kind: StatisticCategory, value: VarInt }); @@ -1063,7 +948,7 @@ impl TestRandom for BlockChangeHorizontalPosition { } } -__protocol_body_def_helper!(MultiBlockChangeRecord { +proto_struct!(MultiBlockChangeRecord { horizontal_position: BlockChangeHorizontalPosition, y_coordinate: u8, block_id: VarInt @@ -1097,12 +982,12 @@ proto_varint_enum!(BossBarDivision, ); proto_byte_flag!(BossBarFlags, - 0x01 :: darken_sky, - 0x02 :: dragon_bar, - 0x04 :: create_fog + 0x01 :: is_darken_sky set_darken_sky, + 0x02 :: is_dragon_bar set_dragon_bar, + 0x04 :: is_create_fog set_create_fog ); -__protocol_body_def_helper!(BossBarAddSpec { +proto_struct!(BossBarAddSpec { title: Chat, health: f32, color: BossBarColor, @@ -1110,27 +995,27 @@ __protocol_body_def_helper!(BossBarAddSpec { flags: BossBarFlags }); -__protocol_body_def_helper!(BossBarUpdateHealthSpec { health: f32 }); +proto_struct!(BossBarUpdateHealthSpec { health: f32 }); -__protocol_body_def_helper!(BossBarUpdateTitleSpec { title: String }); +proto_struct!(BossBarUpdateTitleSpec { title: String }); -__protocol_body_def_helper!(BossBarUpdateStyleSpec { +proto_struct!(BossBarUpdateStyleSpec { color: BossBarColor, dividers: BossBarDivision }); -__protocol_body_def_helper!(BossBarUpdateFlagsSpec { +proto_struct!(BossBarUpdateFlagsSpec { flags: BossBarFlags }); -__protocol_body_def_helper!(TabCompleteMatch { +proto_struct!(TabCompleteMatch { match_: String, tooltip: Option<Chat> }); #[derive(Clone, Debug, PartialEq)] pub struct CommandNodeSpec { - pub children_indices: VarIntCountedArray<VarInt>, + pub children_indices: CountedArray<VarInt, VarInt>, pub redirect_node: Option<VarInt>, pub is_executable: bool, pub node: CommandNode, @@ -1186,7 +1071,7 @@ impl Serialize for CommandNodeSpec { impl Deserialize for CommandNodeSpec { fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> { let Deserialized { value: flags, data } = u8::mc_deserialize(data)?; - let Deserialized { value: children_indices, data } = <VarIntCountedArray<VarInt>>::mc_deserialize(data)?; + let Deserialized { value: children_indices, data } = <CountedArray<VarInt, VarInt>>::mc_deserialize(data)?; let (redirect_node, data) = if flags & 0x08 != 0 { let Deserialized { value: redirect_node, data } = VarInt::mc_deserialize(data)?; (Some(redirect_node), data) @@ -1215,7 +1100,7 @@ impl Deserialize for CommandNodeSpec { #[cfg(all(test, feature = "std"))] impl TestRandom for CommandNodeSpec { fn test_gen_random() -> Self { - let children_indices = <VarIntCountedArray<VarInt>>::test_gen_random(); + let children_indices = <CountedArray<VarInt, VarInt>>::test_gen_random(); let redirect_node = <Option<VarInt>>::test_gen_random(); let is_executable = rand::random::<bool>(); let idx = rand::random::<usize>() % 3; @@ -1293,7 +1178,7 @@ proto_str_enum!(SuggestionsTypeSpec, "minecraft:summonable_entities" :: SummonableEntities ); -__protocol_body_def_helper!(CommandLiteralNodeSpec { +proto_struct!(CommandLiteralNodeSpec { name: String }); @@ -1468,15 +1353,15 @@ proto_varint_enum!(StringParserMode, ); proto_byte_flag!(EntityParserFlags, - 0x01 :: single_target, - 0x02 :: players_only + 0x01 :: is_single_target set_single_target, + 0x02 :: is_players_only set_players_only ); proto_byte_flag!(ScoreHolderFlags, - 0x01 :: multiple + 0x01 :: is_multiple set_multiple ); -__protocol_body_def_helper!(RangeParserProps { +proto_struct!(RangeParserProps { decimal: bool }); @@ -1546,11 +1431,11 @@ proto_str_enum!(TeamCollisionRule, "never" :: Never ); -__protocol_body_def_helper!(TeamActionPlayerList { - entities: VarIntCountedArray<TeamMember> +proto_struct!(TeamActionPlayerList { + entities: CountedArray<TeamMember, VarInt> }); -__protocol_body_def_helper!(TeamActionCreateSpec { +proto_struct!(TeamActionCreateSpec { display_name: Chat, friendly_flags: TeamFriendlyFlags, tag_name_visibility: TeamTagNameVisibility, @@ -1558,10 +1443,10 @@ __protocol_body_def_helper!(TeamActionCreateSpec { color: VarInt, prefix: Chat, suffix: Chat, - entities: VarIntCountedArray<TeamMember> + entities: CountedArray<TeamMember, VarInt> }); -__protocol_body_def_helper!(TeamActionUpdateInfoSpec { +proto_struct!(TeamActionUpdateInfoSpec { display_name: Chat, friendly_flags: TeamFriendlyFlags, tag_name_visibility: TeamTagNameVisibility, @@ -1572,8 +1457,8 @@ __protocol_body_def_helper!(TeamActionUpdateInfoSpec { }); proto_byte_flag!(TeamFriendlyFlags, - 0x01 :: allow_friendly_fire, - 0x02 :: show_invisible_teammates + 0x01 :: allow_friendly_fire set_friendly_fire, + 0x02 :: show_invisible_teammates set_show_invisible_teammates ); proto_byte_enum!(UpdateScoreAction, @@ -1630,7 +1515,7 @@ proto_varint_enum!(TitleActionSpec, 0x05 :: Reset ); -__protocol_body_def_helper!(TitleTimesSpec { +proto_struct!(TitleTimesSpec { fade_in: i32, stay: i32, fade_out: i32 @@ -1730,12 +1615,6 @@ impl TestRandom for StopSoundSpec { } } -__protocol_body_def_helper!(ExplosionRecord { - x: i8, - y: i8, - z: i8 -}); - proto_byte_enum!(GameMode, 0x00 :: Survival, 0x01 :: Creative, @@ -1880,10 +1759,9 @@ proto_varint_enum!(MapIconType, 0x19 :: TreasureMarker ); -__protocol_body_def_helper!(MapIconSpec { +proto_struct!(MapIconSpec { kind: MapIconType, - x: i8, - z: i8, + position: TopDownPosition<i8>, direction: i8, display_name: Option<Chat> }); @@ -1894,12 +1772,11 @@ pub enum MapColumns { Updated(MapColumnsSpec), } -__protocol_body_def_helper!(MapColumnsSpec { +proto_struct!(MapColumnsSpec { columns: u8, rows: u8, - x: u8, - z: u8, - data: VarIntCountedArray<u8> + position: TopDownPosition<u8>, + data: CountedArray<u8, VarInt> }); impl Serialize for MapColumns { @@ -1937,7 +1814,13 @@ impl From<Option<MapColumnsSpec>> for MapColumns { fn from(other: Option<MapColumnsSpec>) -> Self { use MapColumns::*; match other { - Some(body) => Updated(body), + Some(body) => { + if body.columns == 0 { + NoUpdates + } else { + Updated(body) + } + }, None => NoUpdates, } } @@ -1950,10 +1833,10 @@ impl TestRandom for MapColumns { } } -__protocol_body_def_helper!(TradeSpec { - input_item_1: Option<Slot>, - output_item: Option<Slot>, - input_item_2: Option<Slot>, +proto_struct!(TradeSpec { + input_item_1: Slot, + output_item: Slot, + input_item_2: Slot, trade_disabled: bool, trade_uses: i32, max_trade_uses: i32, @@ -1995,10 +1878,10 @@ proto_varint_enum!(WindowType, ); proto_byte_flag!(PlayerAbilityFlags, - 0x01 :: invulnerable, - 0x02 :: flying, - 0x04 :: allow_flying, - 0x08 :: instant_break + 0x01 :: is_invulnerable set_invulnerable, + 0x02 :: is_flying set_flying, + 0x04 :: is_flight_allowed set_flight_allowed, + 0x08 :: is_instant_break set_instant_break ); proto_varint_enum!(CombatEvent, @@ -2007,73 +1890,39 @@ proto_varint_enum!(CombatEvent, 0x02 :: EntityDead(CombatEntityDeadSpec) ); -__protocol_body_def_helper!(CombatEndSpec { +proto_struct!(CombatEndSpec { duration_ticks: VarInt, entity_id: i32 }); -__protocol_body_def_helper!(CombatEntityDeadSpec { +proto_struct!(CombatEntityDeadSpec { player_id: VarInt, entity_id: i32, message: Chat }); -#[derive(Clone, PartialEq, Debug)] -pub struct PlayerInfoAction<A: Clone + PartialEq + Debug> { - pub uuid: UUID4, - pub action: A, -} - -impl<A> Serialize for PlayerInfoAction<A> - where - A: Serialize + Clone + PartialEq + Debug, -{ - fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult { - to.serialize_other(&self.uuid)?; - to.serialize_other(&self.action) - } -} - -impl<A> Deserialize for PlayerInfoAction<A> - where - A: Deserialize + Clone + PartialEq + Debug, -{ - fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> { - let Deserialized { value: uuid, data } = UUID4::mc_deserialize(data)?; - Ok(A::mc_deserialize(data)?.map(move |action| Self { uuid, action })) - } -} - -#[cfg(all(test, feature = "std"))] -impl<A> TestRandom for PlayerInfoAction<A> - where - A: Clone + PartialEq + Debug + TestRandom -{ - fn test_gen_random() -> Self { - Self { - uuid: UUID4::test_gen_random(), - action: A::test_gen_random(), - } - } -} +proto_struct!(PlayerInfoAction<A> { + uuid: UUID4, + action: A +}); proto_varint_enum!(PlayerInfoActionList, - 0x00 :: Add(VarIntCountedArray<PlayerInfoAction<PlayerAddActionSpec>>), - 0x01 :: UpdateGameMode(VarIntCountedArray<PlayerInfoAction<GameMode>>), - 0x02 :: UpdateLatency(VarIntCountedArray<PlayerInfoAction<VarInt>>), - 0x03 :: UpdateDisplayName(VarIntCountedArray<PlayerInfoAction<Option<Chat>>>), - 0x04 :: Remove(VarIntCountedArray<UUID4>) + 0x00 :: Add(CountedArray<PlayerInfoAction<PlayerAddActionSpec>, VarInt>), + 0x01 :: UpdateGameMode(CountedArray<PlayerInfoAction<GameMode>, VarInt>), + 0x02 :: UpdateLatency(CountedArray<PlayerInfoAction<VarInt>, VarInt>), + 0x03 :: UpdateDisplayName(CountedArray<PlayerInfoAction<Option<Chat>>, VarInt>), + 0x04 :: Remove(CountedArray<UUID4, VarInt>) ); -__protocol_body_def_helper!(PlayerAddActionSpec { +proto_struct!(PlayerAddActionSpec { name: String, - properties: VarIntCountedArray<PlayerAddProperty>, + properties: CountedArray<PlayerAddProperty, VarInt>, game_mode: GameMode, ping_ms: VarInt, display_name: Option<Chat> }); -__protocol_body_def_helper!(PlayerAddProperty { +proto_struct!(PlayerAddProperty { name: String, value: String, signature: Option<String> @@ -2084,17 +1933,17 @@ proto_varint_enum!(FacePlayerKind, 0x01 :: Eyes ); -__protocol_body_def_helper!(FacePlayerEntityTarget { +proto_struct!(FacePlayerEntityTarget { entity_id: VarInt, kind: FacePlayerKind }); proto_byte_flag!(PositionAndLookFlags, - 0x01 :: x, - 0x02 :: y, - 0x04 :: z, - 0x08 :: y_rotation, - 0x10 :: x_rotation + 0x01 :: is_x_rel set_x_rel, + 0x02 :: is_y_rel set_y_rel, + 0x04 :: is_z_rel set_z_rel, + 0x08 :: is_y_rotation_rel set_y_rotation_rel, + 0x10 :: is_x_rotation_rel set_x_rotation_rel ); proto_byte_enum!(EntityEffectKind, @@ -2135,25 +1984,24 @@ proto_byte_enum!(EntityEffectKind, proto_varint_enum!(WorldBorderAction, 0x00 :: SetSize(WorldBorderSetSizeSpec), 0x01 :: LerpSize(WorldBorderLerpSizeSpec), - 0x02 :: SetCenter(WorldBorderSetCenterSpec), + 0x02 :: SetCenter(TopDownPosition<f64>), 0x03 :: Initialize(WorldBorderInitiaializeSpec), 0x04 :: SetWarningTime(WorldBorderWarningTimeSpec), 0x05 :: SetWarningBlocks(WorldBorderWarningBlocksSpec) ); -__protocol_body_def_helper!(WorldBorderSetSizeSpec { diameter: f64 }); +proto_struct!(WorldBorderSetSizeSpec { + diameter: f64 +}); -__protocol_body_def_helper!(WorldBorderLerpSizeSpec { +proto_struct!(WorldBorderLerpSizeSpec { old_diameter: f64, new_diameter: f64, speed: VarLong }); -__protocol_body_def_helper!(WorldBorderSetCenterSpec { x: f64, z: f64 }); - -__protocol_body_def_helper!(WorldBorderInitiaializeSpec { - x: f64, - z: f64, +proto_struct!(WorldBorderInitiaializeSpec { + position: TopDownPosition<f64>, old_diameter: f64, new_diameter: f64, speed: VarLong, @@ -2162,11 +2010,11 @@ __protocol_body_def_helper!(WorldBorderInitiaializeSpec { warning_blocks: VarInt }); -__protocol_body_def_helper!(WorldBorderWarningTimeSpec { +proto_struct!(WorldBorderWarningTimeSpec { warning_time: VarInt }); -__protocol_body_def_helper!(WorldBorderWarningBlocksSpec { +proto_struct!(WorldBorderWarningBlocksSpec { warning_blocks: VarInt }); @@ -2197,31 +2045,30 @@ proto_varint_enum!(ScoreboardObjectiveKind, 0x01 :: Hearts ); -__protocol_body_def_helper!(ScoreboardObjectiveSpec { +proto_struct!(ScoreboardObjectiveSpec { text: Chat, kind: ScoreboardObjectiveKind }); -__protocol_body_def_helper!(AdvancementMappingEntrySpec { +proto_struct!(AdvancementMappingEntrySpec { key: String, value: AdvancementSpec }); -__protocol_body_def_helper!(AdvancementSpec { +proto_struct!(AdvancementSpec { parent: Option<String>, display: Option<AdvancementDisplaySpec>, - criteria: VarIntCountedArray<String>, - requirements: VarIntCountedArray<VarIntCountedArray<String>> + criteria: CountedArray<String, VarInt>, + requirements: CountedArray<CountedArray<String, VarInt>, VarInt> }); -__protocol_body_def_helper!(AdvancementDisplaySpec { +proto_struct!(AdvancementDisplaySpec { title: Chat, description: Chat, - icon: Option<Slot>, + icon: Slot, frame_type: AdvancementFrameType, flags: AdvancementDisplayFlags, - x: f32, - y: f32 + position: Vec2<f32> }); #[derive(Clone, Debug, PartialEq)] @@ -2299,31 +2146,31 @@ proto_varint_enum!(AdvancementFrameType, 0x02 :: Goal ); -__protocol_body_def_helper!(AdvancementProgressEntrySpec { +proto_struct!(AdvancementProgressEntrySpec { key: String, value: AdvancementProgressSpec }); -__protocol_body_def_helper!(AdvancementProgressSpec { - criteria: VarIntCountedArray<AdvancementCriteriaSpec> +proto_struct!(AdvancementProgressSpec { + criteria: CountedArray<AdvancementCriteriaSpec, VarInt> }); -__protocol_body_def_helper!(AdvancementCriteriaSpec { +proto_struct!(AdvancementCriteriaSpec { identifier: String, progress: AdvancementCriterionProgressSpec }); -__protocol_body_def_helper!(AdvancementCriterionProgressSpec { +proto_struct!(AdvancementCriterionProgressSpec { achieved_at: Option<i64> }); -__protocol_body_def_helper!(EntityPropertySpec { +proto_struct!(EntityPropertySpec { key: String, value: f64, - modifiers: VarIntCountedArray<EntityPropertyModifierSpec> + modifiers: CountedArray<EntityPropertyModifierSpec, VarInt> }); -__protocol_body_def_helper!(EntityPropertyModifierSpec { +proto_struct!(EntityPropertyModifierSpec { uuid: UUID4, amount: f64, operation: EntityPropertyModifierOperation @@ -2336,14 +2183,14 @@ proto_byte_enum!(EntityPropertyModifierOperation, ); proto_byte_flag!(EntityEffectFlags, - 0x01 :: ambient, - 0x02 :: show_particles, - 0x04 :: show_icon + 0x01 :: is_ambient set_ambient, + 0x02 :: is_show_particles set_show_particles, + 0x04 :: is_show_icon set_show_icon ); -__protocol_body_def_helper!(TagSpec { +proto_struct!(TagSpec { name: String, - entries: VarIntCountedArray<VarInt> + entries: CountedArray<VarInt, VarInt> }); proto_varint_enum!(ClientStatusAction, @@ -2363,13 +2210,13 @@ proto_varint_enum!(ClientMainHand, ); proto_byte_flag!(ClientDisplayedSkinParts, - 0x01 :: cape_enabled, - 0x02 :: jacket_enabled, - 0x04 :: left_sleeve_enabled, - 0x08 :: right_sleeve_enabled, - 0x10 :: left_pants_leg_enabled, - 0x20 :: right_pant_legs_enabled, - 0x40 :: hat_enabled + 0x01 :: is_cape_enabled set_cape_enabled, + 0x02 :: is_jacket_enabled set_jacket_enabled, + 0x04 :: is_left_sleeve_enabled set_left_sleeve_enabled, + 0x08 :: is_right_sleeve_enabled set_right_sleeve_enabled, + 0x10 :: is_left_pants_leg_enabled set_left_pants_leg_enabled, + 0x20 :: is_right_pant_legs_enabled set_right_pant_legs_enabled, + 0x40 :: is_hat_enabled set_hat_enabled ); proto_varint_enum!(InventoryOperationMode, @@ -2382,10 +2229,8 @@ proto_varint_enum!(InventoryOperationMode, 0x06 :: DoubleClick ); -__protocol_body_def_helper!(InteractAtSpec { - target_x: f32, - target_y: f32, - target_z: f32, +proto_struct!(InteractAtSpec { + target_position: Vec3<f32>, hand: Hand }); @@ -2396,10 +2241,10 @@ proto_varint_enum!(InteractKind, ); proto_byte_flag!(ClientPlayerAbilities, - 0x01 :: creative, - 0x02 :: flying, - 0x04 :: fly_enabled, - 0x08 :: damaged_disabled + 0x01 :: is_creative set_creative, + 0x02 :: is_flying set_flying, + 0x04 :: is_fly_enabled set_fly_enabled, + 0x08 :: is_damaged_disabled set_damaged_disabled ); proto_varint_enum!(PlayerDiggingStatus, @@ -2434,8 +2279,8 @@ proto_varint_enum!(EntityActionKind, ); proto_byte_flag!(SteerVehicleFlags, - 0x01 :: jump, - 0x02 :: unmount + 0x01 :: is_jump set_jump, + 0x02 :: is_unmount set_unmount ); proto_varint_enum!(RecipeBookStatus, @@ -2443,7 +2288,7 @@ proto_varint_enum!(RecipeBookStatus, 0x01 :: States(RecipeBookStates) ); -__protocol_body_def_helper!(RecipeBookStates { +proto_struct!(RecipeBookStates { crafting_book_open: bool, craftinb_filter_active: bool, smelting_book_open: bool, @@ -2473,9 +2318,9 @@ proto_varint_enum!(CommandBlockMode, ); proto_byte_flag!(CommandBlockFlags, - 0x01 :: track_output, - 0x02 :: conditional, - 0x04 :: automatic + 0x01 :: is_track_output set_track_output, + 0x02 :: is_conditional set_conditional, + 0x04 :: is_automatic set_automatic ); proto_varint_enum!(UpdateStructureBlockAction, @@ -2506,9 +2351,9 @@ proto_varint_enum!(UpdateStructureBlockRotation, ); proto_byte_flag!(UpdateStructureBlockFlags, - 0x01 :: ignore_entities, - 0x02 :: show_air, - 0x04 :: show_bounding_box + 0x01 :: is_ignore_entities set_ignore_entities, + 0x02 :: is_show_air set_show_air, + 0x04 :: is_show_bounding_box set_show_bounding_box ); #[derive(Clone, PartialEq, Debug)] @@ -2577,14 +2422,14 @@ impl TestRandom for RecipeSpec { } } -__protocol_body_def_helper!(RecipeIngredient { - items: VarIntCountedArray<Option<Slot>> +proto_struct!(RecipeIngredient { + items: CountedArray<Slot, VarInt> }); -__protocol_body_def_helper!(RecipeCraftingShapelessSpec { +proto_struct!(RecipeCraftingShapelessSpec { group: String, - ingredients: VarIntCountedArray<RecipeIngredient>, - result: Option<Slot> + ingredients: CountedArray<RecipeIngredient, VarInt>, + result: Slot }); #[derive(Debug, Clone, PartialEq)] @@ -2593,7 +2438,7 @@ pub struct RecipeCraftingShapedSpec { pub height: VarInt, pub group: String, pub ingredients: Vec<RecipeIngredient>, - pub result: Option<Slot>, + pub result: Slot, } impl Serialize for RecipeCraftingShapedSpec { @@ -2623,7 +2468,7 @@ impl Deserialize for RecipeCraftingShapedSpec { ingredients.push(elem); } - let Deserialized { value: result, data } = <Option<Slot>>::mc_deserialize(data)?; + let Deserialized { value: result, data } = Slot::mc_deserialize(data)?; Deserialized::ok( Self { @@ -2658,23 +2503,23 @@ impl TestRandom for RecipeCraftingShapedSpec { height, group: String::test_gen_random(), ingredients, - result: Some(Slot::test_gen_random()), + result: Some(ItemStack::test_gen_random()), } } } -__protocol_body_def_helper!(RecipeSmeltingSpec { +proto_struct!(RecipeSmeltingSpec { group: String, ingredient: RecipeIngredient, - result: Option<Slot>, + result: Slot, experience: f32, cooking_time: VarInt }); -__protocol_body_def_helper!(RecipeStonecuttingSpec { +proto_struct!(RecipeStonecuttingSpec { group: String, ingredient: RecipeIngredient, - result: Option<Slot> + result: Slot }); proto_varint_enum!(RecipeUnlockAction, @@ -2685,19 +2530,17 @@ proto_varint_enum!(RecipeUnlockAction, #[derive(Clone, PartialEq, Debug)] pub struct ChunkData { - pub chunk_x: i32, - pub chunk_z: i32, + pub position: ChunkPosition<i32>, pub primary_bit_mask: VarInt, pub heightmaps: NamedNbtTag, pub biomes: Option<[i32; 1024]>, - pub data: VarIntCountedArray<u8>, + pub data: CountedArray<u8, VarInt>, pub block_entities: Vec<NamedNbtTag>, } impl Serialize for ChunkData { fn mc_serialize<S: Serializer>(&self, to: &mut S) -> SerializeResult { - to.serialize_other(&self.chunk_x)?; - to.serialize_other(&self.chunk_z)?; + to.serialize_other(&self.position)?; let full_chunk = self.biomes.is_some(); to.serialize_other(&full_chunk)?; to.serialize_other(&self.primary_bit_mask)?; @@ -2723,8 +2566,7 @@ impl Serialize for ChunkData { impl Deserialize for ChunkData { fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> { - let Deserialized { value: chunk_x, data } = i32::mc_deserialize(data)?; - let Deserialized { value: chunk_z, data } = i32::mc_deserialize(data)?; + let Deserialized { value: position, data } = <ChunkPosition<i32>>::mc_deserialize(data)?; let Deserialized { value: is_full_chunk, data } = bool::mc_deserialize(data)?; let Deserialized { value: primary_bit_mask, data } = VarInt::mc_deserialize(data)?; let Deserialized { value: heightmaps, mut data } = NamedNbtTag::mc_deserialize(data)?; @@ -2739,7 +2581,7 @@ impl Deserialize for ChunkData { } else { None }; - let Deserialized { value: chunk_data, data } = VarIntCountedArray::<u8>::mc_deserialize(data)?; + let Deserialized { value: chunk_data, data } = <CountedArray<u8, VarInt>>::mc_deserialize(data)?; let Deserialized { value: n_block_entities_raw, mut data } = VarInt::mc_deserialize(data)?; let n_block_entities = n_block_entities_raw.0 as usize; let mut block_entities = Vec::with_capacity(n_block_entities); @@ -2750,8 +2592,7 @@ impl Deserialize for ChunkData { } Deserialized::ok(ChunkData { - chunk_x, - chunk_z, + position, primary_bit_mask, heightmaps, biomes, @@ -2765,12 +2606,11 @@ impl Deserialize for ChunkData { impl TestRandom for ChunkData { fn test_gen_random() -> Self { ChunkData { - chunk_x: rand::random(), - chunk_z: rand::random(), + position: <ChunkPosition<i32>>::test_gen_random(), primary_bit_mask: VarInt::test_gen_random(), heightmaps: NamedNbtTag::test_gen_random(), biomes: None, - data: <VarIntCountedArray<u8>>::test_gen_random(), + data: <CountedArray<u8, VarInt>>::test_gen_random(), block_entities: vec![], } } @@ -3090,9 +2930,9 @@ proto_varint_enum!(EntityMetadataFieldData, 0x03 :: String(String), 0x04 :: Chat(Chat), 0x05 :: OptChat(Option<Chat>), - 0x06 :: Slot(Option<Slot>), + 0x06 :: Slot(Slot), 0x07 :: Boolean(bool), - 0x08 :: Rotation(EntityRotation), + 0x08 :: Rotation(Vec3<f32>), 0x09 :: Position(IntPosition), 0x0A :: OptPosition(Option<IntPosition>), 0x0B :: Direction(EntityDirection), @@ -3105,12 +2945,6 @@ proto_varint_enum!(EntityMetadataFieldData, 0x12 :: Pose(EntityPose) ); -__protocol_body_def_helper!(EntityRotation { - x: f32, - y: f32, - z: f32 -}); - proto_varint_enum!(EntityDirection, 0x00 :: Down, 0x01 :: Up, @@ -3120,7 +2954,7 @@ proto_varint_enum!(EntityDirection, 0x05 :: East ); -__protocol_body_def_helper!(EntityVillagerData { +proto_struct!(EntityVillagerData { villager_type: VillagerType, villager_profession: VillagerProfession, level: VarInt @@ -3197,7 +3031,7 @@ proto_varint_enum!(ParticleSpec, 0x1D :: Composter, 0x1E :: Heart, 0x1F :: InstantEffect, - 0x20 :: Item(Option<Slot>), + 0x20 :: Item(Slot), 0x21 :: ItemSlime, 0x22 :: ItemSnowball, 0x23 :: LargeSmoke, @@ -3229,11 +3063,11 @@ proto_varint_enum!(ParticleSpec, 0x3D :: FallingNectar ); -__protocol_body_def_helper!(BlockParticleData { +proto_struct!(BlockParticleData { block_state: VarInt }); -__protocol_body_def_helper!(DustParticleData { +proto_struct!(DustParticleData { red: f32, green: f32, blue: f32, |