diff options
| author | mat <27899617+mat-1@users.noreply.github.com> | 2026-01-13 10:51:45 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-01-13 10:51:45 -0600 |
| commit | b21ac946cafaacc9ee2478ea48ed9e72554f79ed (patch) | |
| tree | 4d05744b9801e94f5da6563d8fabddfb20d1c7b7 | |
| parent | d5fa5e32b37754b3b5c136e58821e48cd3b7c2ff (diff) | |
| download | azalea-drasl-b21ac946cafaacc9ee2478ea48ed9e72554f79ed.tar.xz | |
Merge AzaleaRead and AzaleaWrite (#305)
79 files changed, 1034 insertions, 1431 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index d95581e1..ff994529 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ is breaking anyways, semantic versioning is not followed. - Most functions on `Client` that previously returned `Entity` now return `EntityRef` instead. - Deprecate pathfinder `InverseGoal`. - Add a `bevy_ecs` feature to `azalea-protocol` and related crates to allow disabling the Bevy dependencies. +- Replace `azalea-buf`'s `AzaleaRead` and `AzaleaWrite` traits with a single `AzBuf` trait. ### Fixed @@ -33,7 +34,7 @@ is breaking anyways, semantic versioning is not followed. - `Identifier` had an incorrect `Hash` and `PartialEq` implementation. - The pathfinder now avoids magma blocks. - Explosion knockback was being applied incorrectly. -- Fixed several panics/OOMs in `azalea-protocol`. +- Fixed several panics, OOMs, and memory leaks in `azalea-protocol`. ## [0.15.0+mc1.21.11] - 2025-12-18 diff --git a/azalea-auth/src/game_profile.rs b/azalea-auth/src/game_profile.rs index 99af322d..ff456bc9 100644 --- a/azalea-auth/src/game_profile.rs +++ b/azalea-auth/src/game_profile.rs @@ -3,9 +3,7 @@ use std::{ sync::Arc, }; -use azalea_buf::{ - AzBuf, AzaleaRead, AzaleaReadLimited, AzaleaReadVar, AzaleaWrite, AzaleaWriteVar, BufReadError, -}; +use azalea_buf::{AzBuf, AzBufLimited, AzBufVar, BufReadError}; use indexmap::IndexMap; use serde::{Deserialize, Serialize, Serializer}; use uuid::Uuid; @@ -53,7 +51,7 @@ impl From<SerializableGameProfile> for GameProfile { pub struct GameProfileProperties { pub map: IndexMap<String, ProfilePropertyValue>, } -impl AzaleaRead for GameProfileProperties { +impl AzBuf for GameProfileProperties { fn azalea_read(buf: &mut io::Cursor<&[u8]>) -> Result<Self, BufReadError> { let mut properties = IndexMap::new(); let properties_len = u32::azalea_read_var(buf)?; @@ -70,8 +68,6 @@ impl AzaleaRead for GameProfileProperties { } Ok(GameProfileProperties { map: properties }) } -} -impl AzaleaWrite for GameProfileProperties { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { (self.map.len() as u64).azalea_write_var(buf)?; for (key, value) in &self.map { @@ -87,14 +83,12 @@ pub struct ProfilePropertyValue { pub value: String, pub signature: Option<String>, } -impl AzaleaRead for ProfilePropertyValue { +impl AzBuf for ProfilePropertyValue { fn azalea_read(buf: &mut io::Cursor<&[u8]>) -> Result<Self, BufReadError> { let value = String::azalea_read_limited(buf, 32767)?; let signature = Option::<String>::azalea_read_limited(buf, 1024)?; Ok(ProfilePropertyValue { value, signature }) } -} -impl AzaleaWrite for ProfilePropertyValue { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { self.value.azalea_write(buf)?; self.signature.azalea_write(buf)?; diff --git a/azalea-block/src/block_state.rs b/azalea-block/src/block_state.rs index 08baad2f..9a3eece8 100644 --- a/azalea-block/src/block_state.rs +++ b/azalea-block/src/block_state.rs @@ -3,7 +3,7 @@ use std::{ io::{self, Cursor, Write}, }; -use azalea_buf::{AzaleaRead, AzaleaReadVar, AzaleaWrite, AzaleaWriteVar, BufReadError}; +use azalea_buf::{AzBuf, AzBufVar, BufReadError}; use azalea_registry::builtin::BlockKind; use crate::BlockTrait; @@ -113,15 +113,13 @@ impl From<BlockState> for u32 { } } -impl AzaleaRead for BlockState { +impl AzBuf for BlockState { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let state_id = u32::azalea_read_var(buf)?; Self::try_from(state_id).map_err(|_| BufReadError::UnexpectedEnumVariant { id: state_id as i32, }) } -} -impl AzaleaWrite for BlockState { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { u32::azalea_write_var(&(self.id as u32), buf) } diff --git a/azalea-brigadier/src/suggestion/mod.rs b/azalea-brigadier/src/suggestion/mod.rs index 95a451f3..b2107889 100644 --- a/azalea-brigadier/src/suggestion/mod.rs +++ b/azalea-brigadier/src/suggestion/mod.rs @@ -2,18 +2,12 @@ mod suggestion_provider; mod suggestions; mod suggestions_builder; -#[cfg(feature = "azalea-buf")] -use std::io::{self, Write}; use std::{ cmp::Ordering, fmt::{self, Display}, hash::Hash, }; -#[cfg(feature = "azalea-buf")] -use azalea_buf::AzaleaWrite; -#[cfg(feature = "azalea-buf")] -use azalea_chat::FormattedText; pub use suggestion_provider::SuggestionProvider; pub use suggestions::Suggestions; pub use suggestions_builder::SuggestionsBuilder; @@ -138,15 +132,3 @@ impl PartialOrd for SuggestionValue { Some(self.cmp(other)) } } - -#[cfg(feature = "azalea-buf")] -impl AzaleaWrite for Suggestion { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - self.value.to_string().azalea_write(buf)?; - self.tooltip - .clone() - .map(FormattedText::from) - .azalea_write(buf)?; - Ok(()) - } -} diff --git a/azalea-brigadier/src/suggestion/suggestions.rs b/azalea-brigadier/src/suggestion/suggestions.rs index c0090a35..64156154 100644 --- a/azalea-brigadier/src/suggestion/suggestions.rs +++ b/azalea-brigadier/src/suggestion/suggestions.rs @@ -3,7 +3,7 @@ use std::io::{self, Cursor, Write}; use std::{collections::HashSet, hash::Hash}; #[cfg(feature = "azalea-buf")] -use azalea_buf::{AzBuf, AzaleaRead, AzaleaReadVar, AzaleaWrite, AzaleaWriteVar, BufReadError}; +use azalea_buf::{AzBuf, AzBufVar, BufReadError}; #[cfg(feature = "azalea-buf")] use azalea_chat::FormattedText; @@ -77,7 +77,7 @@ impl Suggestions { } #[cfg(feature = "azalea-buf")] -impl AzaleaRead for Suggestions { +impl AzBuf for Suggestions { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { #[derive(AzBuf)] struct StandaloneSuggestion { @@ -90,7 +90,7 @@ impl AzaleaRead for Suggestions { let range = StringRange::between(start, start + length); // the range of a Suggestion depends on the Suggestions containing it, - // so we can't just `impl AzaleaRead for Suggestion` + // so we can't just `impl AzBuf for Suggestion` let mut suggestions = Vec::<StandaloneSuggestion>::azalea_read(buf)? .into_iter() .map(|s| Suggestion { @@ -103,14 +103,22 @@ impl AzaleaRead for Suggestions { Ok(Suggestions { range, suggestions }) } -} - -#[cfg(feature = "azalea-buf")] -impl AzaleaWrite for Suggestions { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { (self.range.start() as u32).azalea_write_var(buf)?; (self.range.length() as u32).azalea_write_var(buf)?; - self.suggestions.azalea_write(buf)?; + // self.suggestions.azalea_write(buf)?; + + self.suggestions + .iter() + .map(|s| { + ( + s.value.to_string(), + s.tooltip.clone().map(FormattedText::from), + ) + }) + .collect::<Box<_>>() + .azalea_write(buf)?; + Ok(()) } } diff --git a/azalea-buf/azalea-buf-macros/src/lib.rs b/azalea-buf/azalea-buf-macros/src/lib.rs index 965e19c9..e71daf11 100644 --- a/azalea-buf/azalea-buf-macros/src/lib.rs +++ b/azalea-buf/azalea-buf-macros/src/lib.rs @@ -5,30 +5,6 @@ use proc_macro::TokenStream; use quote::quote; use syn::{DeriveInput, parse_macro_input}; -#[proc_macro_derive(AzaleaRead, attributes(var))] -pub fn derive_azalearead(input: TokenStream) -> TokenStream { - let DeriveInput { - ident, - generics, - data, - .. - } = parse_macro_input!(input); - - read::create_impl_azalearead(&ident, &generics, &data).into() -} - -#[proc_macro_derive(AzaleaWrite, attributes(var))] -pub fn derive_azaleawrite(input: TokenStream) -> TokenStream { - let DeriveInput { - ident, - generics, - data, - .. - } = parse_macro_input!(input); - - write::create_impl_azaleawrite(&ident, &generics, &data).into() -} - #[proc_macro_derive(AzBuf, attributes(var, limit))] pub fn derive_azbuf(input: TokenStream) -> TokenStream { let DeriveInput { @@ -38,11 +14,15 @@ pub fn derive_azbuf(input: TokenStream) -> TokenStream { .. } = parse_macro_input!(input); - let writable = write::create_impl_azaleawrite(&ident, &generics, &data); - let readable = read::create_impl_azalearead(&ident, &generics, &data); + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + + let writable = write::create_fn_azalea_write(&data); + let readable = read::create_fn_azalea_read(&data); quote! { - #writable - #readable + impl #impl_generics azalea_buf::AzBuf for #ident #ty_generics #where_clause { + #writable + #readable + } } .into() } diff --git a/azalea-buf/azalea-buf-macros/src/read.rs b/azalea-buf/azalea-buf-macros/src/read.rs index 9f4fa78a..7c8f1c9e 100644 --- a/azalea-buf/azalea-buf-macros/src/read.rs +++ b/azalea-buf/azalea-buf-macros/src/read.rs @@ -1,20 +1,13 @@ use quote::{ToTokens, quote}; -use syn::{Data, Field, FieldsNamed, Generics, Ident, punctuated::Punctuated, token::Comma}; - -pub fn create_impl_azalearead( - ident: &Ident, - generics: &Generics, - data: &Data, -) -> proc_macro2::TokenStream { - let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); +use syn::{Data, Field, FieldsNamed, Ident, punctuated::Punctuated, token::Comma}; +pub fn create_fn_azalea_read(data: &Data) -> proc_macro2::TokenStream { match data { syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields { syn::Fields::Named(FieldsNamed { named, .. }) => { let (read_fields, read_field_names) = read_named_fields(named); quote! { - impl #impl_generics azalea_buf::AzaleaRead for #ident #ty_generics #where_clause { fn azalea_read(buf: &mut std::io::Cursor<&[u8]>) -> std::result::Result<Self, azalea_buf::BufReadError> { #(#read_fields)* Ok(Self { @@ -22,29 +15,24 @@ pub fn create_impl_azalearead( }) } } - } } syn::Fields::Unit => { quote! { - impl #impl_generics azalea_buf::AzaleaRead for #ident #ty_generics #where_clause { fn azalea_read(buf: &mut std::io::Cursor<&[u8]>) -> std::result::Result<Self, azalea_buf::BufReadError> { Ok(Self) } } - } } syn::Fields::Unnamed(fields) => { let read_fields = read_unnamed_fields(&fields.unnamed); quote! { - impl #impl_generics azalea_buf::AzaleaRead for #ident #ty_generics #where_clause { fn azalea_read(buf: &mut std::io::Cursor<&[u8]>) -> std::result::Result<Self, azalea_buf::BufReadError> { Ok(Self( #(#read_fields),* )) } } - } } }, syn::Data::Enum(syn::DataEnum { variants, .. }) => { @@ -81,7 +69,7 @@ pub fn create_impl_azalearead( quote! { #(#read_fields)* - Ok(#ident::#variant_name { + Ok(Self::#variant_name { #(#read_field_names: #read_field_names),* }) } @@ -98,7 +86,7 @@ pub fn create_impl_azalearead( .map(|a| { a.parse_args::<syn::LitInt>() .unwrap() - .base10_parse::<usize>() + .base10_parse::<u32>() .unwrap() }); @@ -108,15 +96,15 @@ pub fn create_impl_azalearead( if is_variable_length { reader_code.extend(quote! { - Self::#variant_name(azalea_buf::AzaleaReadVar::azalea_read_var(buf)?), + Self::#variant_name(azalea_buf::AzBufVar::azalea_read_var(buf)?), }); } else if let Some(limit) = limit { reader_code.extend(quote! { - Self::#variant_name(azalea_buf::AzaleaReadLimited::azalea_read_limited(buf, #limit)?), + Self::#variant_name(azalea_buf::AzBufLimited::azalea_read_limited(buf, #limit)?), }); } else { reader_code.extend(quote! { - Self::#variant_name(azalea_buf::AzaleaRead::azalea_read(buf)?), + Self::#variant_name(azalea_buf::AzBuf::azalea_read(buf)?), }); } } @@ -141,15 +129,9 @@ pub fn create_impl_azalearead( let first_reader = first_reader.expect("There should be at least one variant"); quote! { - impl #impl_generics azalea_buf::AzaleaRead for #ident #ty_generics #where_clause { fn azalea_read(buf: &mut std::io::Cursor<&[u8]>) -> std::result::Result<Self, azalea_buf::BufReadError> { - let id = azalea_buf::AzaleaReadVar::azalea_read_var(buf)?; - Self::azalea_read_id(buf, id) - } - } + let id = azalea_buf::AzBufVar::azalea_read_var(buf)?; - impl #impl_generics #ident #ty_generics #where_clause { - pub fn azalea_read_id(buf: &mut std::io::Cursor<&[u8]>, id: u32) -> std::result::Result<Self, azalea_buf::BufReadError> { match id { #match_contents // you'd THINK this throws an error, but mojang decided to make it default for some reason @@ -157,7 +139,6 @@ pub fn create_impl_azalearead( } } } - } } _ => panic!("#[derive(AzBuf)] can only be used on structs"), } @@ -202,7 +183,7 @@ fn get_reader_call(f: &Field) -> proc_macro2::TokenStream { .map(|a| { a.parse_args::<syn::LitInt>() .unwrap() - .base10_parse::<usize>() + .base10_parse::<u32>() .unwrap() }); @@ -218,15 +199,15 @@ fn get_reader_call(f: &Field) -> proc_macro2::TokenStream { syn::Type::Path(_) | syn::Type::Array(_) => { if is_variable_length { quote! { - azalea_buf::AzaleaReadVar::azalea_read_var(buf)? + azalea_buf::AzBufVar::azalea_read_var(buf)? } } else if let Some(limit) = limit { quote! { - azalea_buf::AzaleaReadLimited::azalea_read_limited(buf, #limit)? + azalea_buf::AzBufLimited::azalea_read_limited(buf, #limit)? } } else { quote! { - azalea_buf::AzaleaRead::azalea_read(buf)? + azalea_buf::AzBuf::azalea_read(buf)? } } } diff --git a/azalea-buf/azalea-buf-macros/src/write.rs b/azalea-buf/azalea-buf-macros/src/write.rs index 7bd58d29..f7d7e07a 100644 --- a/azalea-buf/azalea-buf-macros/src/write.rs +++ b/azalea-buf/azalea-buf-macros/src/write.rs @@ -1,14 +1,8 @@ use proc_macro2::Span; use quote::{ToTokens, quote}; -use syn::{Data, Field, FieldsNamed, Generics, Ident, punctuated::Punctuated, token::Comma}; - -pub fn create_impl_azaleawrite( - ident: &Ident, - generics: &Generics, - data: &Data, -) -> proc_macro2::TokenStream { - let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); +use syn::{Data, Field, FieldsNamed, Ident, punctuated::Punctuated, token::Comma}; +pub fn create_fn_azalea_write(data: &Data) -> proc_macro2::TokenStream { match data { syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields { syn::Fields::Named(FieldsNamed { named, .. }) => { @@ -16,20 +10,16 @@ pub fn create_impl_azaleawrite( write_named_fields(named, Some(&Ident::new("self", Span::call_site()))); quote! { - impl #impl_generics azalea_buf::AzaleaWrite for #ident #ty_generics #where_clause { - fn azalea_write(&self, buf: &mut impl std::io::Write) -> std::result::Result<(), std::io::Error> { - #write_fields - Ok(()) - } + fn azalea_write(&self, buf: &mut impl std::io::Write) -> std::result::Result<(), std::io::Error> { + #write_fields + Ok(()) } } } syn::Fields::Unit => { quote! { - impl #impl_generics azalea_buf::AzaleaWrite for #ident #ty_generics #where_clause { - fn azalea_write(&self, buf: &mut impl std::io::Write) -> std::result::Result<(), std::io::Error> { - Ok(()) - } + fn azalea_write(&self, buf: &mut impl std::io::Write) -> std::result::Result<(), std::io::Error> { + Ok(()) } } } @@ -37,11 +27,9 @@ pub fn create_impl_azaleawrite( let write_fields = write_unnamed_fields(&fields.unnamed); quote! { - impl #impl_generics azalea_buf::AzaleaWrite for #ident #ty_generics #where_clause { - fn azalea_write(&self, buf: &mut impl std::io::Write) -> std::result::Result<(), std::io::Error> { - #write_fields - Ok(()) - } + fn azalea_write(&self, buf: &mut impl std::io::Write) -> std::result::Result<(), std::io::Error> { + #write_fields + Ok(()) } } } @@ -83,7 +71,7 @@ pub fn create_impl_azaleawrite( // the variant number that we're going to write let write_the_variant = quote! { - azalea_buf::AzaleaWriteVar::azalea_write_var(&#variant_discrim, buf)?; + azalea_buf::AzBufVar::azalea_write_var(&#variant_discrim, buf)?; }; match &variant.fields { syn::Fields::Named(f) => { @@ -125,11 +113,11 @@ pub fn create_impl_azaleawrite( params_code.extend(quote! { #param_ident, }); if f.attrs.iter().any(|attr| attr.path().is_ident("var")) { writers_code.extend(quote! { - azalea_buf::AzaleaWriteVar::azalea_write_var(#param_ident, buf)?; + azalea_buf::AzBufVar::azalea_write_var(#param_ident, buf)?; }); } else { writers_code.extend(quote! { - azalea_buf::AzaleaWrite::azalea_write(#param_ident, buf)?; + azalea_buf::AzBuf::azalea_write(#param_ident, buf)?; }); } } @@ -141,7 +129,7 @@ pub fn create_impl_azaleawrite( }); match_arms_without_id.extend(quote! { Self::#variant_name(data) => { - azalea_buf::AzaleaWrite::azalea_write(data, buf)?; + azalea_buf::AzBuf::azalea_write(data, buf)?; } }); } @@ -149,30 +137,18 @@ pub fn create_impl_azaleawrite( } if is_data_enum { quote! { - impl #impl_generics azalea_buf::AzaleaWrite for #ident #ty_generics #where_clause { - fn azalea_write(&self, buf: &mut impl std::io::Write) -> std::result::Result<(), std::io::Error> { - match self { - #match_arms - } - Ok(()) - } - } - impl #impl_generics #ident #ty_generics #where_clause { - pub fn write_without_id(&self, buf: &mut impl std::io::Write) -> std::result::Result<(), std::io::Error> { - match self { - #match_arms_without_id - } - Ok(()) + fn azalea_write(&self, buf: &mut impl std::io::Write) -> std::result::Result<(), std::io::Error> { + match self { + #match_arms } + Ok(()) } } } else { // optimization: if it doesn't have data we can just do `as u32` quote! { - impl #impl_generics azalea_buf::AzaleaWrite for #ident #ty_generics #where_clause { - fn azalea_write(&self, buf: &mut impl std::io::Write) -> std::result::Result<(), std::io::Error> { - azalea_buf::AzaleaWriteVar::azalea_write_var(&(*self as u32), buf) - } + fn azalea_write(&self, buf: &mut impl std::io::Write) -> std::result::Result<(), std::io::Error> { + azalea_buf::AzBufVar::azalea_write_var(&(*self as u32), buf) } } } @@ -218,11 +194,11 @@ fn make_write_call( syn::Type::Path(_) | syn::Type::Array(_) => { if f.attrs.iter().any(|attr| attr.path().is_ident("var")) { quote! { - azalea_buf::AzaleaWriteVar::azalea_write_var(#ident_dot_field, buf)?; + azalea_buf::AzBufVar::azalea_write_var(#ident_dot_field, buf)?; } } else { quote! { - azalea_buf::AzaleaWrite::azalea_write(#ident_dot_field, buf)?; + azalea_buf::AzBuf::azalea_write(#ident_dot_field, buf)?; } } } diff --git a/azalea-buf/src/impls/extra.rs b/azalea-buf/src/impls/extra.rs new file mode 100644 index 00000000..f22ddb1a --- /dev/null +++ b/azalea-buf/src/impls/extra.rs @@ -0,0 +1,309 @@ +use std::{ + collections::HashMap, + hash::Hash, + io::{self, Cursor, Write}, + sync::Arc, +}; + +use indexmap::IndexMap; + +use crate::{ + AzBuf, AzBufLimited, AzBufVar, BufReadError, MAX_STRING_LENGTH, UnsizedByteArray, read_bytes, + read_utf_with_len, write_utf_with_len, +}; + +impl AzBuf for UnsizedByteArray { + fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + // read to end of the buffer + let data = buf.get_ref()[buf.position() as usize..].to_vec(); + buf.set_position((buf.position()) + data.len() as u64); + Ok(UnsizedByteArray(data)) + } + fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { + buf.write_all(self) + } +} + +macro_rules! impl_for_map_type { + ($ty: ident) => { + impl<K: AzBuf + Eq + Hash, V: AzBuf> AzBuf for $ty<K, V> { + fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + let length = i32::azalea_read_var(buf)? as usize; + let mut contents = Self::with_capacity(usize::min(length, 65536)); + for _ in 0..length { + contents.insert(K::azalea_read(buf)?, V::azalea_read(buf)?); + } + Ok(contents) + } + fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { + u32::azalea_write_var(&(self.len() as u32), buf)?; + for (key, value) in self { + key.azalea_write(buf)?; + value.azalea_write(buf)?; + } + + Ok(()) + } + } + impl<K: AzBuf + Eq + Hash, V: AzBufVar> AzBufVar for $ty<K, V> { + fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + let length = i32::azalea_read_var(buf)? as usize; + let mut contents = Self::with_capacity(usize::min(length, 65536)); + for _ in 0..length { + contents.insert(K::azalea_read(buf)?, V::azalea_read_var(buf)?); + } + Ok(contents) + } + fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()> { + u32::azalea_write_var(&(self.len() as u32), buf)?; + for (key, value) in self { + key.azalea_write(buf)?; + value.azalea_write_var(buf)?; + } + + Ok(()) + } + } + }; +} + +impl_for_map_type!(HashMap); +impl_for_map_type!(IndexMap); + +macro_rules! impl_for_list_type { + ($ty: ty) => { + impl<T: AzBuf> AzBuf for $ty { + default fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + let length = u32::azalea_read_var(buf)? as usize; + // we limit the capacity to not get exploited into allocating a bunch + let mut contents = Vec::with_capacity(usize::min(length, 65536)); + for _ in 0..length { + contents.push(T::azalea_read(buf)?); + } + Ok(contents.into()) + } + default fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { + (self.len() as u32).azalea_write_var(buf)?; + for item in self { + T::azalea_write(item, buf)?; + } + Ok(()) + } + } + impl<T: AzBufVar> AzBufVar for $ty { + fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + let length = i32::azalea_read_var(buf)? as usize; + let mut contents = Vec::with_capacity(usize::min(length, 65536)); + for _ in 0..length { + contents.push(T::azalea_read_var(buf)?); + } + Ok(contents.into()) + } + fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()> { + (self.len() as u32).azalea_write_var(buf)?; + for item in self { + T::azalea_write_var(item, buf)?; + } + Ok(()) + } + } + impl<T: AzBuf> AzBufLimited for $ty { + fn azalea_read_limited( + buf: &mut Cursor<&[u8]>, + limit: u32, + ) -> Result<Self, BufReadError> { + let length = u32::azalea_read_var(buf)?; + if length > limit { + return Err(BufReadError::VecLengthTooLong { + length: length as u32, + max_length: limit as u32, + }); + } + + let mut contents = Vec::with_capacity(u32::min(length, 65536) as usize); + for _ in 0..length { + contents.push(T::azalea_read(buf)?); + } + Ok(contents.into()) + } + } + }; +} + +impl_for_list_type!(Vec<T>); +impl_for_list_type!(Box<[T]>); + +impl AzBuf for Vec<u8> { + fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + let length = i32::azalea_read_var(buf)? as usize; + read_bytes(buf, length).map(|b| b.to_vec()) + } + fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { + (self.len() as u32).azalea_write_var(buf)?; + buf.write_all(self) + } +} + +impl AzBuf for String { + fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + read_utf_with_len(buf, MAX_STRING_LENGTH).map(Into::into) + } + fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { + write_utf_with_len(buf, self, MAX_STRING_LENGTH) + } +} +impl AzBufLimited for String { + fn azalea_read_limited(buf: &mut Cursor<&[u8]>, limit: u32) -> Result<Self, BufReadError> { + read_utf_with_len(buf, limit).map(Into::into) + } +} + +impl AzBuf for Box<str> { + fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + read_utf_with_len(buf, MAX_STRING_LENGTH).map(Into::into) + } + fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { + write_utf_with_len(buf, self, MAX_STRING_LENGTH) + } +} + +impl AzBufLimited for Box<str> { + fn azalea_read_limited(buf: &mut Cursor<&[u8]>, limit: u32) -> Result<Self, BufReadError> { + String::azalea_read_limited(buf, limit).map(Into::into) + } +} + +impl<T: AzBuf> AzBuf for Option<T> { + fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + let present = bool::azalea_read(buf)?; + Ok(if present { + Some(T::azalea_read(buf)?) + } else { + None + }) + } + fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { + if let Some(s) = self { + true.azalea_write(buf)?; + s.azalea_write(buf)?; + } else { + false.azalea_write(buf)?; + }; + Ok(()) + } +} + +impl<T: AzBufVar> AzBufVar for Option<T> { + fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + let present = bool::azalea_read(buf)?; + Ok(if present { + Some(T::azalea_read_var(buf)?) + } else { + None + }) + } + fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()> { + if let Some(s) = self { + true.azalea_write(buf)?; + s.azalea_write_var(buf)?; + } else { + false.azalea_write(buf)?; + }; + Ok(()) + } +} +impl<T: AzBufLimited> AzBufLimited for Option<T> { + fn azalea_read_limited(buf: &mut Cursor<&[u8]>, limit: u32) -> Result<Self, BufReadError> { + let present = bool::azalea_read(buf)?; + Ok(if present { + Some(T::azalea_read_limited(buf, limit)?) + } else { + None + }) + } +} + +impl<T: AzBuf, const N: usize> AzBuf for [T; N] { + fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + let mut contents = Vec::with_capacity(N); + for _ in 0..N { + contents.push(T::azalea_read(buf)?); + } + Ok(contents + .try_into() + .unwrap_or_else(|_| unreachable!("The vec is the same size as the array"))) + } + fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { + for i in self { + i.azalea_write(buf)?; + } + Ok(()) + } +} + +impl AzBuf for simdnbt::owned::NbtTag { + fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + Ok(simdnbt::owned::read_tag(buf).map_err(simdnbt::Error::from)?) + } + fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { + let mut data = Vec::new(); + self.write(&mut data); + buf.write_all(&data) + } +} + +impl AzBuf for simdnbt::owned::NbtCompound { + fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + match simdnbt::owned::read_tag(buf).map_err(simdnbt::Error::from)? { + simdnbt::owned::NbtTag::Compound(compound) => Ok(compound), + _ => Err(BufReadError::Custom("Expected compound tag".to_owned())), + } + } + fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { + let mut data = Vec::new(); + simdnbt::owned::NbtTag::Compound(self.clone()).write(&mut data); + buf.write_all(&data) + } +} + +impl AzBuf for simdnbt::owned::Nbt { + fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + Ok(simdnbt::owned::read_unnamed(buf)?) + } + fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { + let mut data = Vec::new(); + self.write_unnamed(&mut data); + buf.write_all(&data) + } +} + +impl<T> AzBuf for Box<T> +where + T: AzBuf, +{ + fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + T::azalea_read(buf).map(Box::new) + } + fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { + T::azalea_write(&**self, buf) + } +} + +impl<A: AzBuf, B: AzBuf> AzBuf for (A, B) { + fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + Ok((A::azalea_read(buf)?, B::azalea_read(buf)?)) + } + fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { + self.0.azalea_write(buf)?; + self.1.azalea_write(buf) + } +} + +impl<T: AzBuf> AzBuf for Arc<T> { + fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + Ok(Arc::new(T::azalea_read(buf)?)) + } + fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { + T::azalea_write(&**self, buf) + } +} diff --git a/azalea-buf/src/impls/mod.rs b/azalea-buf/src/impls/mod.rs new file mode 100644 index 00000000..37f53624 --- /dev/null +++ b/azalea-buf/src/impls/mod.rs @@ -0,0 +1,158 @@ +mod extra; +mod primitives; + +use std::{ + backtrace::Backtrace, + io::{self, Cursor, Write}, +}; + +use thiserror::Error; + +/// A trait that's implemented on types that are used by the Minecraft protocol. +pub trait AzBuf +where + Self: Sized, +{ + fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError>; + fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()>; +} + +/// Used for types that have an alternative variable-length encoding. +/// +/// This mostly exists for varints. +pub trait AzBufVar +where + Self: Sized, +{ + fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError>; + fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()>; +} + +/// Used for types that have some configurable limit. +/// +/// For example, the implementation of this on `String` limits the maximum +/// length of the string. +/// +/// This exists partially as an anti-abuse mechanism in Minecraft, so there is +/// no limited write function. +pub trait AzBufLimited +where + Self: Sized, +{ + fn azalea_read_limited(buf: &mut Cursor<&[u8]>, limit: u32) -> Result<Self, BufReadError>; +} + +#[derive(Debug, Error)] +pub enum BufReadError { + #[error("Invalid VarInt")] + InvalidVarInt, + #[error("Invalid VarLong")] + InvalidVarLong, + #[error("Error reading bytes")] + CouldNotReadBytes, + #[error( + "The received encoded string buffer length is longer than maximum allowed ({length} > {max_length})" + )] + StringLengthTooLong { length: u32, max_length: u32 }, + #[error("The received Vec length is longer than maximum allowed ({length} > {max_length})")] + VecLengthTooLong { length: u32, max_length: u32 }, + #[error("{source}")] + Io { + #[from] + #[backtrace] + source: io::Error, + }, + #[error("Invalid UTF-8: {bytes:?} (lossy: {lossy:?})")] + InvalidUtf8 { + bytes: Vec<u8>, + lossy: String, + // backtrace: Backtrace, + }, + #[error("Unexpected enum variant {id}")] + UnexpectedEnumVariant { id: i32 }, + #[error("Unexpected enum variant {id}")] + UnexpectedStringEnumVariant { id: String }, + #[error("Tried to read {attempted_read} bytes but there were only {actual_read}")] + UnexpectedEof { + attempted_read: usize, + actual_read: usize, + backtrace: Backtrace, + }, + #[error("{0}")] + Custom(String), + #[cfg(feature = "serde_json")] + #[error("{source}")] + Deserialization { + #[from] + #[backtrace] + source: serde_json::Error, + }, + #[error("{source}")] + Nbt { + #[from] + #[backtrace] + source: simdnbt::Error, + }, + #[error("{source}")] + DeserializeNbt { + #[from] + #[backtrace] + source: simdnbt::DeserializeError, + }, +} + +pub(crate) fn read_bytes<'a>( + buf: &'a mut Cursor<&[u8]>, + length: usize, +) -> Result<&'a [u8], BufReadError> { + if length > (buf.get_ref().len() - buf.position() as usize) { + return Err(BufReadError::UnexpectedEof { + attempted_read: length, + actual_read: buf.get_ref().len() - buf.position() as usize, + backtrace: Backtrace::capture(), + }); + } + let initial_position = buf.position() as usize; + buf.set_position(buf.position() + length as u64); + let data = &buf.get_ref()[initial_position..initial_position + length]; + Ok(data) +} + +pub(crate) fn read_utf_with_len<'a>( + buf: &'a mut Cursor<&[u8]>, + max_length: u32, +) -> Result<&'a str, BufReadError> { + let length = u32::azalea_read_var(buf)?; + // i don't know why it's multiplied by 4 but it's like that in mojang's code so + if length > max_length * 4 { + return Err(BufReadError::StringLengthTooLong { + length, + max_length: max_length * 4, + }); + } + + let buffer = read_bytes(buf, length as usize)?; + let string = std::str::from_utf8(buffer).map_err(|_| BufReadError::InvalidUtf8 { + bytes: buffer.to_vec(), + lossy: String::from_utf8_lossy(buffer).to_string(), + // backtrace: Backtrace::capture(), + })?; + if string.len() > length as usize { + return Err(BufReadError::StringLengthTooLong { length, max_length }); + } + + Ok(string) +} + +pub(crate) fn write_utf_with_len( + buf: &mut impl Write, + string: &str, + max_len: u32, +) -> io::Result<()> { + let actual_len = string.len(); + if actual_len > max_len as usize { + panic!("String too big (was {actual_len} bytes encoded, max {max_len})"); + } + string.as_bytes().to_vec().azalea_write(buf)?; + Ok(()) +} diff --git a/azalea-buf/src/impls/primitives.rs b/azalea-buf/src/impls/primitives.rs new file mode 100644 index 00000000..023086bb --- /dev/null +++ b/azalea-buf/src/impls/primitives.rs @@ -0,0 +1,213 @@ +use std::io::{self, Cursor, Read, Write}; + +use byteorder::{BE, ReadBytesExt, WriteBytesExt}; +use tracing::warn; + +use crate::{AzBuf, AzBufVar, BufReadError}; + +impl AzBuf for () { + fn azalea_read(_buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + Ok(()) + } + fn azalea_write(&self, _buf: &mut impl Write) -> io::Result<()> { + Ok(()) + } +} + +impl AzBuf for i32 { + fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + Ok(buf.read_i32::<BE>()?) + } + fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { + buf.write_i32::<BE>(*self) + } +} + +impl AzBufVar for i32 { + /// Read a single varint from the reader and return the value + fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + // fast varint impl based on https://github.com/luojia65/mc-varint/blob/master/src/lib.rs#L67 + let mut buffer = [0]; + let mut ans = 0; + for i in 0..5 { + buf.read_exact(&mut buffer)?; + ans |= ((buffer[0] & 0b0111_1111) as i32) << (7 * i); + if buffer[0] & 0b1000_0000 == 0 { + break; + } + } + Ok(ans) + } + + fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()> { + let mut buffer = [0]; + let mut value = *self; + if value == 0 { + buf.write_all(&buffer)?; + } + while value != 0 { + buffer[0] = (value & 0b0111_1111) as u8; + value = (value >> 7) & (i32::MAX >> 6); + if value != 0 { + buffer[0] |= 0b1000_0000; + } + buf.write_all(&buffer)?; + } + Ok(()) + } +} + +impl AzBufVar for i64 { + fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + let mut buffer = [0]; + let mut ans = 0; + for i in 0..10 { + buf.read_exact(&mut buffer) + .map_err(|_| BufReadError::InvalidVarLong)?; + ans |= ((buffer[0] & 0b0111_1111) as i64) << (7 * i); + if buffer[0] & 0b1000_0000 == 0 { + break; + } + } + Ok(ans) + } + + fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()> { + let mut buffer = [0]; + let mut value = *self; + if value == 0 { + buf.write_all(&buffer).unwrap(); + } + while value != 0 { + buffer[0] = (value & 0b0111_1111) as u8; + value = (value >> 7) & (i64::MAX >> 6); + if value != 0 { + buffer[0] |= 0b1000_0000; + } + buf.write_all(&buffer)?; + } + Ok(()) + } +} + +impl AzBufVar for u64 { + fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + i64::azalea_read_var(buf).map(|i| i as u64) + } + fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()> { + i64::azalea_write_var(&(*self as i64), buf) + } +} + +impl AzBuf for u32 { + fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + Ok(i32::azalea_read(buf)? as u32) + } + fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { + i32::azalea_write(&(*self as i32), buf) + } +} + +impl AzBufVar for u32 { + fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + Ok(i32::azalea_read_var(buf)? as u32) + } + fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()> { + i32::azalea_write_var(&(*self as i32), buf) + } +} + +impl AzBuf for u16 { + fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + i16::azalea_read(buf).map(|i| i as u16) + } + fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { + i16::azalea_write(&(*self as i16), buf) + } +} + +impl AzBuf for i16 { + fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + Ok(buf.read_i16::<BE>()?) + } + fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { + buf.write_i16::<BE>(*self) + } +} + +impl AzBufVar for u16 { + fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + Ok(i32::azalea_read_var(buf)? as u16) + } + fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()> { + i32::azalea_write_var(&(*self as i32), buf) + } +} + +impl AzBuf for i64 { + fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + Ok(buf.read_i64::<BE>()?) + } + fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { + buf.write_i64::<BE>(*self) + } +} + +impl AzBuf for u64 { + fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + i64::azalea_read(buf).map(|i| i as u64) + } + fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { + buf.write_u64::<BE>(*self) + } +} + +impl AzBuf for bool { + fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + let byte = u8::azalea_read(buf)?; + if byte > 1 { + warn!("Boolean value was not 0 or 1, but {byte}"); + } + Ok(byte != 0) + } + fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { + let byte = u8::from(*self); + byte.azalea_write(buf) + } +} + +impl AzBuf for u8 { + fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + Ok(buf.read_u8()?) + } + fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { + buf.write_u8(*self) + } +} + +impl AzBuf for i8 { + fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + u8::azalea_read(buf).map(|i| i as i8) + } + fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { + (*self as u8).azalea_write(buf) + } +} + +impl AzBuf for f32 { + fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + Ok(buf.read_f32::<BE>()?) + } + fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { + buf.write_f32::<BE>(*self) + } +} + +impl AzBuf for f64 { + fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + Ok(buf.read_f64::<BE>()?) + } + fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { + buf.write_f64::<BE>(*self) + } +} diff --git a/azalea-buf/src/lib.rs b/azalea-buf/src/lib.rs index 966b1372..d6eb9299 100644 --- a/azalea-buf/src/lib.rs +++ b/azalea-buf/src/lib.rs @@ -4,18 +4,16 @@ #![feature(error_generic_member_access)] mod definitions; -mod read; +pub mod impls; mod serializable_uuid; -mod write; pub use azalea_buf_macros::*; pub use definitions::*; -pub use read::{AzaleaRead, AzaleaReadLimited, AzaleaReadVar, BufReadError}; +pub use impls::*; pub use serializable_uuid::*; -pub use write::{AzaleaWrite, AzaleaWriteVar}; // const DEFAULT_NBT_QUOTA: u32 = 2097152; -const MAX_STRING_LENGTH: u16 = 32767; +const MAX_STRING_LENGTH: u32 = 32767; // const MAX_COMPONENT_STRING_LENGTH: u32 = 262144; #[cfg(test)] diff --git a/azalea-buf/src/read.rs b/azalea-buf/src/read.rs deleted file mode 100644 index f4d6a951..00000000 --- a/azalea-buf/src/read.rs +++ /dev/null @@ -1,465 +0,0 @@ -use std::{ - backtrace::Backtrace, - collections::HashMap, - hash::Hash, - io::{self, Cursor, Read}, - sync::Arc, -}; - -use byteorder::{BE, ReadBytesExt}; -use indexmap::IndexMap; -use thiserror::Error; -use tracing::warn; - -use super::{MAX_STRING_LENGTH, UnsizedByteArray}; - -#[derive(Debug, Error)] -pub enum BufReadError { - #[error("Invalid VarInt")] - InvalidVarInt, - #[error("Invalid VarLong")] - InvalidVarLong, - #[error("Error reading bytes")] - CouldNotReadBytes, - #[error( - "The received encoded string buffer length is longer than maximum allowed ({length} > {max_length})" - )] - StringLengthTooLong { length: u32, max_length: u32 }, - #[error("The received Vec length is longer than maximum allowed ({length} > {max_length})")] - VecLengthTooLong { length: u32, max_length: u32 }, - #[error("{source}")] - Io { - #[from] - #[backtrace] - source: io::Error, - }, - #[error("Invalid UTF-8: {bytes:?} (lossy: {lossy:?})")] - InvalidUtf8 { - bytes: Vec<u8>, - lossy: String, - // backtrace: Backtrace, - }, - #[error("Unexpected enum variant {id}")] - UnexpectedEnumVariant { id: i32 }, - #[error("Unexpected enum variant {id}")] - UnexpectedStringEnumVariant { id: String }, - #[error("Tried to read {attempted_read} bytes but there were only {actual_read}")] - UnexpectedEof { - attempted_read: usize, - actual_read: usize, - backtrace: Backtrace, - }, - #[error("{0}")] - Custom(String), - #[cfg(feature = "serde_json")] - #[error("{source}")] - Deserialization { - #[from] - #[backtrace] - source: serde_json::Error, - }, - #[error("{source}")] - Nbt { - #[from] - #[backtrace] - source: simdnbt::Error, - }, - #[error("{source}")] - DeserializeNbt { - #[from] - #[backtrace] - source: simdnbt::DeserializeError, - }, -} - -fn read_bytes<'a>(buf: &'a mut Cursor<&[u8]>, length: usize) -> Result<&'a [u8], BufReadError> { - if length > (buf.get_ref().len() - buf.position() as usize) { - return Err(BufReadError::UnexpectedEof { - attempted_read: length, - actual_read: buf.get_ref().len() - buf.position() as usize, - backtrace: Backtrace::capture(), - }); - } - let initial_position = buf.position() as usize; - buf.set_position(buf.position() + length as u64); - let data = &buf.get_ref()[initial_position..initial_position + length]; - Ok(data) -} - -fn read_utf_with_len(buf: &mut Cursor<&[u8]>, max_length: u32) -> Result<String, BufReadError> { - let length = u32::azalea_read_var(buf)?; - // i don't know why it's multiplied by 4 but it's like that in mojang's code so - if length > max_length * 4 { - return Err(BufReadError::StringLengthTooLong { - length, - max_length: max_length * 4, - }); - } - - let buffer = read_bytes(buf, length as usize)?; - let string = std::str::from_utf8(buffer) - .map_err(|_| BufReadError::InvalidUtf8 { - bytes: buffer.to_vec(), - lossy: String::from_utf8_lossy(buffer).to_string(), - // backtrace: Backtrace::capture(), - })? - .to_owned(); - if string.len() > length as usize { - return Err(BufReadError::StringLengthTooLong { length, max_length }); - } - - Ok(string) -} - -pub trait AzaleaRead -where - Self: Sized, -{ - fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError>; -} - -pub trait AzaleaReadVar -where - Self: Sized, -{ - fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError>; -} - -// note that there's no Write equivalent for this trait since we don't really -// care if we're writing over the limit (and maybe we already know that the -// server implementation accepts it) -pub trait AzaleaReadLimited -where - Self: Sized, -{ - fn azalea_read_limited(buf: &mut Cursor<&[u8]>, limit: usize) -> Result<Self, BufReadError>; -} - -impl AzaleaRead for () { - fn azalea_read(_buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - Ok(()) - } -} - -impl AzaleaRead for i32 { - fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - Ok(buf.read_i32::<BE>()?) - } -} - -impl AzaleaReadVar for i32 { - /// Read a single varint from the reader and return the value - fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - // fast varint impl based on https://github.com/luojia65/mc-varint/blob/master/src/lib.rs#L67 - let mut buffer = [0]; - let mut ans = 0; - for i in 0..5 { - buf.read_exact(&mut buffer)?; - ans |= ((buffer[0] & 0b0111_1111) as i32) << (7 * i); - if buffer[0] & 0b1000_0000 == 0 { - break; - } - } - Ok(ans) - } -} - -impl AzaleaReadVar for i64 { - fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - let mut buffer = [0]; - let mut ans = 0; - for i in 0..10 { - buf.read_exact(&mut buffer) - .map_err(|_| BufReadError::InvalidVarLong)?; - ans |= ((buffer[0] & 0b0111_1111) as i64) << (7 * i); - if buffer[0] & 0b1000_0000 == 0 { - break; - } - } - Ok(ans) - } -} -impl AzaleaReadVar for u64 { - fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - i64::azalea_read_var(buf).map(|i| i as u64) - } -} - -impl AzaleaRead for UnsizedByteArray { - fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - // read to end of the buffer - let data = buf.get_ref()[buf.position() as usize..].to_vec(); - buf.set_position((buf.position()) + data.len() as u64); - Ok(UnsizedByteArray(data)) - } -} - -macro_rules! impl_for_map_type { - ($ty: ident) => { - impl<K: AzaleaRead + Send + Eq + Hash, V: AzaleaRead + Send> AzaleaRead for $ty<K, V> { - fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - let length = i32::azalea_read_var(buf)? as usize; - let mut contents = Self::with_capacity(usize::min(length, 65536)); - for _ in 0..length { - contents.insert(K::azalea_read(buf)?, V::azalea_read(buf)?); - } - Ok(contents) - } - } - impl<K: AzaleaRead + Send + Eq + Hash, V: AzaleaReadVar + Send> AzaleaReadVar - for $ty<K, V> - { - fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - let length = i32::azalea_read_var(buf)? as usize; - let mut contents = Self::with_capacity(usize::min(length, 65536)); - for _ in 0..length { - contents.insert(K::azalea_read(buf)?, V::azalea_read_var(buf)?); - } - Ok(contents) - } - } - }; -} - -impl_for_map_type!(HashMap); -impl_for_map_type!(IndexMap); - -macro_rules! impl_for_list_type { - ($ty: ty) => { - impl<T: AzaleaRead> AzaleaRead for $ty { - default fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - let length = u32::azalea_read_var(buf)? as usize; - // we limit the capacity to not get exploited into allocating a bunch - let mut contents = Vec::with_capacity(usize::min(length, 65536)); - for _ in 0..length { - contents.push(T::azalea_read(buf)?); - } - Ok(contents.into()) - } - } - impl<T: AzaleaReadVar> AzaleaReadVar for $ty { - fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - let length = i32::azalea_read_var(buf)? as usize; - let mut contents = Vec::with_capacity(usize::min(length, 65536)); - for _ in 0..length { - contents.push(T::azalea_read_var(buf)?); - } - Ok(contents.into()) - } - } - impl<T: AzaleaRead> AzaleaReadLimited for $ty { - fn azalea_read_limited( - buf: &mut Cursor<&[u8]>, - limit: usize, - ) -> Result<Self, BufReadError> { - let length = u32::azalea_read_var(buf)? as usize; - if length > limit { - return Err(BufReadError::VecLengthTooLong { - length: length as u32, - max_length: limit as u32, - }); - } - - let mut contents = Vec::with_capacity(usize::min(length, 65536)); - for _ in 0..length { - contents.push(T::azalea_read(buf)?); - } - Ok(contents.into()) - } - } - }; -} - -impl_for_list_type!(Vec<T>); -impl_for_list_type!(Box<[T]>); - -impl AzaleaRead for Vec<u8> { - fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - let length = i32::azalea_read_var(buf)? as usize; - read_bytes(buf, length).map(|b| b.to_vec()) - } -} - -impl AzaleaRead for String { - fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - read_utf_with_len(buf, MAX_STRING_LENGTH.into()) - } -} -impl AzaleaRead for Box<str> { - fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - String::azalea_read(buf).map(Into::into) - } -} -impl AzaleaReadLimited for String { - fn azalea_read_limited(buf: &mut Cursor<&[u8]>, limit: usize) -> Result<Self, BufReadError> { - read_utf_with_len(buf, limit as u32) - } -} -impl AzaleaReadLimited for Box<str> { - fn azalea_read_limited(buf: &mut Cursor<&[u8]>, limit: usize) -> Result<Self, BufReadError> { - String::azalea_read_limited(buf, limit).map(Into::into) - } -} - -impl AzaleaRead for u32 { - fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - Ok(i32::azalea_read(buf)? as u32) - } -} - -impl AzaleaReadVar for u32 { - fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - Ok(i32::azalea_read_var(buf)? as u32) - } -} - -impl AzaleaRead for u16 { - fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - i16::azalea_read(buf).map(|i| i as u16) - } -} - -impl AzaleaRead for i16 { - fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - Ok(buf.read_i16::<BE>()?) - } -} - -impl AzaleaReadVar for u16 { - fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - Ok(i32::azalea_read_var(buf)? as u16) - } -} - -impl AzaleaRead for i64 { - fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - Ok(buf.read_i64::<BE>()?) - } -} - -impl AzaleaRead for u64 { - fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - i64::azalea_read(buf).map(|i| i as u64) - } -} - -impl AzaleaRead for bool { - fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - let byte = u8::azalea_read(buf)?; - if byte > 1 { - warn!("Boolean value was not 0 or 1, but {}", byte); - } - Ok(byte != 0) - } -} - -impl AzaleaRead for u8 { - fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - Ok(buf.read_u8()?) - } -} - -impl AzaleaRead for i8 { - fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - u8::azalea_read(buf).map(|i| i as i8) - } -} - -impl AzaleaRead for f32 { - fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - Ok(buf.read_f32::<BE>()?) - } -} - -impl AzaleaRead for f64 { - fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - Ok(buf.read_f64::<BE>()?) - } -} - -impl<T: AzaleaRead> AzaleaRead for Option<T> { - fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - let present = bool::azalea_read(buf)?; - Ok(if present { - Some(T::azalea_read(buf)?) - } else { - None - }) - } -} - -impl<T: AzaleaReadVar> AzaleaReadVar for Option<T> { - fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - let present = bool::azalea_read(buf)?; - Ok(if present { - Some(T::azalea_read_var(buf)?) - } else { - None - }) - } -} -impl<T: AzaleaReadLimited> AzaleaReadLimited for Option<T> { - fn azalea_read_limited(buf: &mut Cursor<&[u8]>, limit: usize) -> Result<Self, BufReadError> { - let present = bool::azalea_read(buf)?; - Ok(if present { - Some(T::azalea_read_limited(buf, limit)?) - } else { - None - }) - } -} - -// [String; 4] -impl<T: AzaleaRead, const N: usize> AzaleaRead for [T; N] { - fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - let mut contents = Vec::with_capacity(N); - for _ in 0..N { - contents.push(T::azalea_read(buf)?); - } - contents.try_into().map_err(|_| { - unreachable!("Panic is not possible since the Vec is the same size as the array") - }) - } -} - -impl AzaleaRead for simdnbt::owned::NbtTag { - fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - Ok(simdnbt::owned::read_tag(buf).map_err(simdnbt::Error::from)?) - } -} - -impl AzaleaRead for simdnbt::owned::NbtCompound { - fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - match simdnbt::owned::read_tag(buf).map_err(simdnbt::Error::from)? { - simdnbt::owned::NbtTag::Compound(compound) => Ok(compound), - _ => Err(BufReadError::Custom("Expected compound tag".to_owned())), - } - } -} - -impl AzaleaRead for simdnbt::owned::Nbt { - fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - Ok(simdnbt::owned::read_unnamed(buf)?) - } -} - -impl<T> AzaleaRead for Box<T> -where - T: AzaleaRead, -{ - fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - Ok(Box::new(T::azalea_read(buf)?)) - } -} - -impl<A: AzaleaRead, B: AzaleaRead> AzaleaRead for (A, B) { - fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - Ok((A::azalea_read(buf)?, B::azalea_read(buf)?)) - } -} - -impl<T: AzaleaRead> AzaleaRead for Arc<T> { - fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - Ok(Arc::new(T::azalea_read(buf)?)) - } -} diff --git a/azalea-buf/src/serializable_uuid.rs b/azalea-buf/src/serializable_uuid.rs index 76737034..a455a13a 100644 --- a/azalea-buf/src/serializable_uuid.rs +++ b/azalea-buf/src/serializable_uuid.rs @@ -2,7 +2,7 @@ use std::io::{self, Cursor, Write}; use uuid::Uuid; -use crate::{AzaleaRead, AzaleaWrite, read::BufReadError}; +use crate::{AzBuf, BufReadError}; pub trait SerializableUuid { fn to_int_array(&self) -> [u32; 4]; @@ -34,7 +34,7 @@ impl SerializableUuid for Uuid { } } -impl AzaleaRead for Uuid { +impl AzBuf for Uuid { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { Ok(Uuid::from_int_array([ u32::azalea_read(buf)?, @@ -43,9 +43,6 @@ impl AzaleaRead for Uuid { u32::azalea_read(buf)?, ])) } -} - -impl AzaleaWrite for Uuid { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { let [a, b, c, d] = self.to_int_array(); a.azalea_write(buf)?; diff --git a/azalea-buf/src/write.rs b/azalea-buf/src/write.rs deleted file mode 100644 index 4fcce7a0..00000000 --- a/azalea-buf/src/write.rs +++ /dev/null @@ -1,341 +0,0 @@ -use std::{ - collections::HashMap, - io::{self, Write}, - sync::Arc, -}; - -use byteorder::{BigEndian, WriteBytesExt}; -use indexmap::IndexMap; - -use super::{MAX_STRING_LENGTH, UnsizedByteArray}; - -fn write_utf_with_len(buf: &mut impl Write, string: &str, len: usize) -> io::Result<()> { - if string.len() > len { - panic!( - "String too big (was {} bytes encoded, max {})", - string.len(), - len - ); - } - string.as_bytes().to_vec().azalea_write(buf)?; - Ok(()) -} - -pub trait AzaleaWrite { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()>; -} - -pub trait AzaleaWriteVar { - fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()>; -} - -impl AzaleaWrite for () { - fn azalea_write(&self, _buf: &mut impl Write) -> io::Result<()> { - Ok(()) - } -} - -impl AzaleaWrite for i32 { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - WriteBytesExt::write_i32::<BigEndian>(buf, *self) - } -} - -impl AzaleaWriteVar for i32 { - fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()> { - let mut buffer = [0]; - let mut value = *self; - if value == 0 { - buf.write_all(&buffer)?; - } - while value != 0 { - buffer[0] = (value & 0b0111_1111) as u8; - value = (value >> 7) & (i32::MAX >> 6); - if value != 0 { - buffer[0] |= 0b1000_0000; - } - buf.write_all(&buffer)?; - } - Ok(()) - } -} - -impl AzaleaWrite for UnsizedByteArray { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - buf.write_all(self) - } -} - -impl<T: AzaleaWrite> AzaleaWrite for Vec<T> { - default fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - self[..].azalea_write(buf) - } -} -impl<T: AzaleaWrite> AzaleaWrite for Box<[T]> { - default fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - self[..].azalea_write(buf) - } -} - -impl<T: AzaleaWrite> AzaleaWrite for [T] { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - (self.len() as u32).azalea_write_var(buf)?; - for item in self { - T::azalea_write(item, buf)?; - } - Ok(()) - } -} - -macro_rules! impl_for_map_type { - ($ty: ident) => { - impl<K: AzaleaWrite, V: AzaleaWrite> AzaleaWrite for $ty<K, V> { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - u32::azalea_write_var(&(self.len() as u32), buf)?; - for (key, value) in self { - key.azalea_write(buf)?; - value.azalea_write(buf)?; - } - - Ok(()) - } - } - impl<K: AzaleaWrite, V: AzaleaWriteVar> AzaleaWriteVar for $ty<K, V> { - fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()> { - u32::azalea_write_var(&(self.len() as u32), buf)?; - for (key, value) in self { - key.azalea_write(buf)?; - value.azalea_write_var(buf)?; - } - - Ok(()) - } - } - }; -} - -impl_for_map_type!(HashMap); -impl_for_map_type!(IndexMap); - -impl AzaleaWrite for Vec<u8> { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - (self.len() as u32).azalea_write_var(buf)?; - buf.write_all(self) - } -} - -impl AzaleaWrite for String { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - self.as_str().azalea_write(buf) - } -} - -impl AzaleaWrite for Box<str> { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - (&**self).azalea_write(buf) - } -} - -impl AzaleaWrite for &str { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - write_utf_with_len(buf, self, MAX_STRING_LENGTH.into()) - } -} - -impl AzaleaWrite for u32 { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - i32::azalea_write(&(*self as i32), buf) - } -} - -impl AzaleaWriteVar for u32 { - fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()> { - i32::azalea_write_var(&(*self as i32), buf) - } -} - -impl AzaleaWriteVar for i64 { - fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()> { - let mut buffer = [0]; - let mut value = *self; - if value == 0 { - buf.write_all(&buffer).unwrap(); - } - while value != 0 { - buffer[0] = (value & 0b0111_1111) as u8; - value = (value >> 7) & (i64::MAX >> 6); - if value != 0 { - buffer[0] |= 0b1000_0000; - } - buf.write_all(&buffer)?; - } - Ok(()) - } -} - -impl AzaleaWriteVar for u64 { - fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()> { - i64::azalea_write_var(&(*self as i64), buf) - } -} - -impl AzaleaWrite for u16 { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - i16::azalea_write(&(*self as i16), buf) - } -} - -impl AzaleaWriteVar for u16 { - fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()> { - i32::azalea_write_var(&(*self as i32), buf) - } -} - -impl<T: AzaleaWriteVar> AzaleaWriteVar for [T] { - fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()> { - u32::azalea_write_var(&(self.len() as u32), buf)?; - for i in self { - i.azalea_write_var(buf)?; - } - Ok(()) - } -} -impl<T: AzaleaWriteVar> AzaleaWriteVar for Vec<T> { - fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()> { - self[..].azalea_write_var(buf) - } -} -impl<T: AzaleaWriteVar> AzaleaWriteVar for Box<[T]> { - fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()> { - self[..].azalea_write_var(buf) - } -} - -impl AzaleaWrite for u8 { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - WriteBytesExt::write_u8(buf, *self) - } -} - -impl AzaleaWrite for i16 { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - WriteBytesExt::write_i16::<BigEndian>(buf, *self) - } -} - -impl AzaleaWrite for i64 { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - WriteBytesExt::write_i64::<BigEndian>(buf, *self) - } -} - -impl AzaleaWrite for u64 { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - i64::azalea_write(&(*self as i64), buf) - } -} - -impl AzaleaWrite for bool { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - let byte = u8::from(*self); - byte.azalea_write(buf) - } -} - -impl AzaleaWrite for i8 { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - (*self as u8).azalea_write(buf) - } -} - -impl AzaleaWrite for f32 { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - WriteBytesExt::write_f32::<BigEndian>(buf, *self) - } -} - -impl AzaleaWrite for f64 { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - WriteBytesExt::write_f64::<BigEndian>(buf, *self) - } -} - -impl<T: AzaleaWrite> AzaleaWrite for Option<T> { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - if let Some(s) = self { - true.azalea_write(buf)?; - s.azalea_write(buf)?; - } else { - false.azalea_write(buf)?; - }; - Ok(()) - } -} - -impl<T: AzaleaWriteVar> AzaleaWriteVar for Option<T> { - fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()> { - if let Some(s) = self { - true.azalea_write(buf)?; - s.azalea_write_var(buf)?; - } else { - false.azalea_write(buf)?; - }; - Ok(()) - } -} - -// [T; N] -impl<T: AzaleaWrite, const N: usize> AzaleaWrite for [T; N] { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - for i in self { - i.azalea_write(buf)?; - } - Ok(()) - } -} - -impl AzaleaWrite for simdnbt::owned::NbtTag { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - let mut data = Vec::new(); - self.write(&mut data); - buf.write_all(&data) - } -} - -impl AzaleaWrite for simdnbt::owned::NbtCompound { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - let mut data = Vec::new(); - simdnbt::owned::NbtTag::Compound(self.clone()).write(&mut data); - buf.write_all(&data) - } -} - -impl AzaleaWrite for simdnbt::owned::Nbt { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - let mut data = Vec::new(); - self.write_unnamed(&mut data); - buf.write_all(&data) - } -} - -impl<T> AzaleaWrite for Box<T> -where - T: AzaleaWrite, -{ - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - T::azalea_write(&**self, buf) - } -} - -impl<A: AzaleaWrite, B: AzaleaWrite> AzaleaWrite for (A, B) { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - self.0.azalea_write(buf)?; - self.1.azalea_write(buf) - } -} - -impl<T: AzaleaWrite> AzaleaWrite for Arc<T> { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - T::azalea_write(&**self, buf) - } -} diff --git a/azalea-chat/src/component.rs b/azalea-chat/src/component.rs index c64ee559..b338fe2d 100644 --- a/azalea-chat/src/component.rs +++ b/azalea-chat/src/component.rs @@ -6,7 +6,7 @@ use std::{ }; #[cfg(all(feature = "azalea-buf", feature = "simdnbt"))] -use azalea_buf::{AzaleaRead, AzaleaWrite, BufReadError}; +use azalea_buf::{AzBuf, BufReadError}; use serde::{Deserialize, Deserializer, Serialize, de}; use crate::{ @@ -635,7 +635,7 @@ impl From<&simdnbt::Mutf8Str> for FormattedText { } #[cfg(all(feature = "azalea-buf", feature = "simdnbt"))] -impl AzaleaRead for FormattedText { +impl AzBuf for FormattedText { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { use simdnbt::FromNbtTag; use tracing::trace; @@ -652,10 +652,6 @@ impl AzaleaRead for FormattedText { _ => Ok(FormattedText::default()), } } -} - -#[cfg(all(feature = "azalea-buf", feature = "simdnbt"))] -impl AzaleaWrite for FormattedText { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { use simdnbt::Serialize; diff --git a/azalea-chat/src/numbers.rs b/azalea-chat/src/numbers.rs index 60b599e8..f739c543 100644 --- a/azalea-chat/src/numbers.rs +++ b/azalea-chat/src/numbers.rs @@ -5,7 +5,7 @@ use std::io::{self, Cursor, Write}; #[cfg(feature = "azalea-buf")] -use azalea_buf::{AzaleaRead, AzaleaWrite}; +use azalea_buf::AzBuf; #[cfg(feature = "azalea-buf")] use azalea_registry::builtin::NumberFormatKind; use simdnbt::owned::Nbt; @@ -20,7 +20,7 @@ pub enum NumberFormat { } #[cfg(feature = "azalea-buf")] -impl AzaleaRead for NumberFormat { +impl AzBuf for NumberFormat { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, azalea_buf::BufReadError> { let kind = NumberFormatKind::azalea_read(buf)?; match kind { @@ -33,10 +33,6 @@ impl AzaleaRead for NumberFormat { }), } } -} - -#[cfg(feature = "azalea-buf")] -impl AzaleaWrite for NumberFormat { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { match self { NumberFormat::Blank => NumberFormatKind::Blank.azalea_write(buf)?, diff --git a/azalea-client/src/plugins/brand.rs b/azalea-client/src/plugins/brand.rs index 3b118efd..b8fa0efe 100644 --- a/azalea-client/src/plugins/brand.rs +++ b/azalea-client/src/plugins/brand.rs @@ -1,4 +1,4 @@ -use azalea_buf::AzaleaWrite; +use azalea_buf::AzBuf; use azalea_protocol::packets::config::s_custom_payload::ServerboundCustomPayload; use bevy_app::prelude::*; use bevy_ecs::prelude::*; @@ -21,7 +21,7 @@ pub fn send_brand(mut commands: Commands, mut removed: RemovedComponents<InLogin for entity in removed.read() { let mut brand_data = Vec::new(); // pretend to be vanilla - "vanilla".azalea_write(&mut brand_data).unwrap(); + "vanilla".to_owned().azalea_write(&mut brand_data).unwrap(); commands.trigger(SendConfigPacketEvent::new( entity, ServerboundCustomPayload { diff --git a/azalea-client/src/test_utils/simulation.rs b/azalea-client/src/test_utils/simulation.rs index ce4c919d..6af7ba59 100644 --- a/azalea-client/src/test_utils/simulation.rs +++ b/azalea-client/src/test_utils/simulation.rs @@ -2,7 +2,7 @@ use std::{any, collections::VecDeque, fmt::Debug, sync::Arc}; use azalea_auth::game_profile::GameProfile; use azalea_block::BlockState; -use azalea_buf::AzaleaWrite; +use azalea_buf::AzBuf; use azalea_core::{ delta::LpVec3, entity_id::MinecraftEntityId, diff --git a/azalea-core/src/bitset.rs b/azalea-core/src/bitset.rs index 6abb5d1d..f8c9da28 100644 --- a/azalea-core/src/bitset.rs +++ b/azalea-core/src/bitset.rs @@ -3,7 +3,7 @@ use std::{ ops::Range, }; -use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite, BufReadError}; +use azalea_buf::{AzBuf, BufReadError}; /// Represents Java's BitSet, a list of bits. #[derive(AzBuf, Clone, Debug, Default, Eq, Hash, PartialEq)] @@ -176,8 +176,8 @@ impl From<Vec<u8>> for BitSet { /// /// Note that this is optimized for fast serialization and deserialization for /// Minecraft, and may not be as performant as it could be for other purposes. -/// Consider using [`FastFixedBitSet`] if you don't need the -/// `AzaleaRead`/`AzaleaWrite` implementation. +/// Consider using [`FastFixedBitSet`] if you don't need the `AzBuf` +/// implementation. #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct FixedBitSet<const N: usize> where @@ -211,7 +211,7 @@ where } } -impl<const N: usize> AzaleaRead for FixedBitSet<N> +impl<const N: usize> AzBuf for FixedBitSet<N> where [u8; bits_to_bytes(N)]: Sized, { @@ -222,11 +222,6 @@ where } Ok(FixedBitSet { data }) } -} -impl<const N: usize> AzaleaWrite for FixedBitSet<N> -where - [u8; bits_to_bytes(N)]: Sized, -{ fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { for i in 0..bits_to_bytes(N) { self.data[i].azalea_write(buf)?; @@ -253,7 +248,7 @@ pub const fn bits_to_bytes(n: usize) -> usize { /// use it like `FastFixedBitSet<20>` if you need 20 bits. /// /// This is almost identical to [`FixedBitSet`], but more efficient (~20% faster -/// access) and doesn't implement `AzaleaRead`/`AzaleaWrite`. +/// access) and doesn't implement `AzBuf`. #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct FastFixedBitSet<const N: usize> where diff --git a/azalea-core/src/delta.rs b/azalea-core/src/delta.rs index 055ba3b8..c45900d8 100644 --- a/azalea-core/src/delta.rs +++ b/azalea-core/src/delta.rs @@ -1,7 +1,7 @@ use std::io::{self, Cursor, Write}; pub use azalea_buf::AzBuf; -use azalea_buf::{AzaleaRead, AzaleaReadVar, AzaleaWrite, AzaleaWriteVar, BufReadError}; +use azalea_buf::{AzBufVar, BufReadError}; use crate::{math, position::Vec3}; @@ -91,7 +91,7 @@ pub enum LpVec3 { }, } -impl AzaleaRead for LpVec3 { +impl AzBuf for LpVec3 { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let a = u8::azalea_read(buf)?; if a == 0 { @@ -106,8 +106,6 @@ impl AzaleaRead for LpVec3 { Ok(LpVec3::Normal { a, b, c }) } } -} -impl AzaleaWrite for LpVec3 { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { match self { LpVec3::Zero => { @@ -218,8 +216,6 @@ impl From<Vec3> for LpVec3 { } #[cfg(test)] mod tests { - use azalea_buf::AzaleaWrite; - use super::*; static TEST_VALUES: [Vec3; 3] = [ diff --git a/azalea-core/src/difficulty.rs b/azalea-core/src/difficulty.rs index 7a018a8e..81db0f3a 100644 --- a/azalea-core/src/difficulty.rs +++ b/azalea-core/src/difficulty.rs @@ -3,7 +3,7 @@ use std::{ io::{self, Cursor, Write}, }; -use azalea_buf::{AzaleaRead, AzaleaWrite, BufReadError}; +use azalea_buf::{AzBuf, BufReadError}; #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub enum Difficulty { @@ -61,13 +61,10 @@ impl Difficulty { } } -impl AzaleaRead for Difficulty { +impl AzBuf for Difficulty { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { Ok(Difficulty::by_id(u8::azalea_read(buf)?)) } -} - -impl AzaleaWrite for Difficulty { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { u8::azalea_write(&self.id(), buf) } diff --git a/azalea-core/src/entity_id.rs b/azalea-core/src/entity_id.rs index c66d3a2e..59798e05 100644 --- a/azalea-core/src/entity_id.rs +++ b/azalea-core/src/entity_id.rs @@ -4,7 +4,7 @@ use std::{ io::{self, Cursor}, }; -use azalea_buf::{AzaleaRead, AzaleaReadVar, AzaleaWrite, AzaleaWriteVar, BufReadError}; +use azalea_buf::{AzBuf, AzBufVar, BufReadError}; use derive_more::{Deref, DerefMut}; // note: this is here instead of in azalea-entity because azalea-world depends @@ -41,22 +41,18 @@ impl nohash_hasher::IsEnabled for MinecraftEntityId {} // we can't have the default be #[var] because mojang doesn't use varints for // entities sometimes :( -impl AzaleaRead for MinecraftEntityId { +impl AzBuf for MinecraftEntityId { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { i32::azalea_read(buf).map(MinecraftEntityId) } -} -impl AzaleaWrite for MinecraftEntityId { fn azalea_write(&self, buf: &mut impl io::Write) -> io::Result<()> { i32::azalea_write(&self.0, buf) } } -impl AzaleaReadVar for MinecraftEntityId { +impl AzBufVar for MinecraftEntityId { fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { i32::azalea_read_var(buf).map(MinecraftEntityId) } -} -impl AzaleaWriteVar for MinecraftEntityId { fn azalea_write_var(&self, buf: &mut impl io::Write) -> io::Result<()> { i32::azalea_write_var(&self.0, buf) } diff --git a/azalea-core/src/filterable.rs b/azalea-core/src/filterable.rs index 1c9766b6..16de6711 100644 --- a/azalea-core/src/filterable.rs +++ b/azalea-core/src/filterable.rs @@ -3,7 +3,7 @@ use std::{ io::{self, Cursor, Write}, }; -use azalea_buf::{AzaleaRead, AzaleaReadLimited, AzaleaReadVar, AzaleaWrite}; +use azalea_buf::{AzBuf, AzBufLimited, AzBufVar}; /// Used for written books. #[cfg_attr(feature = "serde", derive(serde::Serialize))] @@ -13,36 +13,39 @@ pub struct Filterable<T> { pub filtered: Option<T>, } -impl<T: AzaleaWrite> azalea_buf::AzaleaWrite for Filterable<T> { +impl<T: AzBuf> AzBuf for Filterable<T> { + fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, azalea_buf::BufReadError> { + let raw = AzBuf::azalea_read(buf)?; + let filtered = AzBuf::azalea_read(buf)?; + Ok(Self { raw, filtered }) + } fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { self.raw.azalea_write(buf)?; self.filtered.azalea_write(buf)?; Ok(()) } } -impl<T: AzaleaRead> azalea_buf::AzaleaRead for Filterable<T> { - fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, azalea_buf::BufReadError> { - let raw = AzaleaRead::azalea_read(buf)?; - let filtered = AzaleaRead::azalea_read(buf)?; - Ok(Self { raw, filtered }) - } -} -impl<T: AzaleaReadLimited> azalea_buf::AzaleaReadLimited for Filterable<T> { +impl<T: AzBufLimited> AzBufLimited for Filterable<T> { fn azalea_read_limited( buf: &mut Cursor<&[u8]>, - limit: usize, + limit: u32, ) -> Result<Self, azalea_buf::BufReadError> { - let raw = AzaleaReadLimited::azalea_read_limited(buf, limit)?; - let filtered = AzaleaReadLimited::azalea_read_limited(buf, limit)?; + let raw = AzBufLimited::azalea_read_limited(buf, limit)?; + let filtered = AzBufLimited::azalea_read_limited(buf, limit)?; Ok(Self { raw, filtered }) } } -impl<T: AzaleaReadVar> azalea_buf::AzaleaReadVar for Filterable<T> { +impl<T: AzBufVar> AzBufVar for Filterable<T> { fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, azalea_buf::BufReadError> { - let raw = AzaleaReadVar::azalea_read_var(buf)?; - let filtered = AzaleaReadVar::azalea_read_var(buf)?; + let raw = AzBufVar::azalea_read_var(buf)?; + let filtered = AzBufVar::azalea_read_var(buf)?; Ok(Self { raw, filtered }) } + fn azalea_write_var(&self, buf: &mut impl Write) -> io::Result<()> { + self.raw.azalea_write_var(buf)?; + self.filtered.azalea_write_var(buf)?; + Ok(()) + } } impl<T: Clone> Clone for Filterable<T> { diff --git a/azalea-core/src/game_type.rs b/azalea-core/src/game_type.rs index 95d330d2..a8c73a41 100644 --- a/azalea-core/src/game_type.rs +++ b/azalea-core/src/game_type.rs @@ -1,6 +1,6 @@ use std::io::{self, Cursor, Write}; -use azalea_buf::{AzaleaRead, AzaleaReadVar, AzaleaWrite, BufReadError}; +use azalea_buf::{AzBuf, AzBufVar, BufReadError}; use azalea_chat::translatable_component::TranslatableComponent; use tracing::debug; @@ -93,7 +93,7 @@ impl GameMode { } } -impl AzaleaRead for GameMode { +impl AzBuf for GameMode { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let id = u32::azalea_read_var(buf)?; let id = id.try_into().unwrap_or_else(|_| { @@ -105,15 +105,12 @@ impl AzaleaRead for GameMode { GameMode::Survival })) } -} - -impl AzaleaWrite for GameMode { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { u8::azalea_write(&self.to_id(), buf) } } -/// Rust doesn't let us `impl AzaleaRead for Option<GameType>` so we have to +/// Rust doesn't let us `impl AzBuf for Option<GameType>` so we have to /// make a new type :( #[derive(Clone, Copy, Debug, Hash, PartialEq)] pub struct OptionalGameType(pub Option<GameMode>); @@ -130,14 +127,11 @@ impl From<OptionalGameType> for Option<GameMode> { } } -impl AzaleaRead for OptionalGameType { +impl AzBuf for OptionalGameType { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let id = i8::azalea_read(buf)?; GameMode::from_optional_id(id).ok_or(BufReadError::UnexpectedEnumVariant { id: id as i32 }) } -} - -impl AzaleaWrite for OptionalGameType { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { GameMode::to_optional_id(*self).azalea_write(buf) } diff --git a/azalea-core/src/position.rs b/azalea-core/src/position.rs index 6da037ff..3f2a724f 100644 --- a/azalea-core/src/position.rs +++ b/azalea-core/src/position.rs @@ -12,7 +12,7 @@ use std::{ str::FromStr, }; -use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite, BufReadError}; +use azalea_buf::{AzBuf, BufReadError}; use azalea_registry::identifier::Identifier; #[cfg(feature = "serde")] use serde::Serializer; @@ -584,13 +584,11 @@ impl From<u64> for ChunkPos { } } } -impl AzaleaRead for ChunkPos { +impl AzBuf for ChunkPos { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let long = u64::azalea_read(buf)?; Ok(ChunkPos::from(long)) } -} -impl AzaleaWrite for ChunkPos { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { u64::from(*self).azalea_write(buf)?; Ok(()) @@ -986,7 +984,7 @@ const PACKED_Z_MASK: u64 = (1 << PACKED_Z_LENGTH) - 1; const Z_OFFSET: u64 = PACKED_Y_LENGTH; const X_OFFSET: u64 = PACKED_Y_LENGTH + PACKED_Z_LENGTH; -impl AzaleaRead for BlockPos { +impl AzBuf for BlockPos { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let val = i64::azalea_read(buf)?; let x = (val << (64 - X_OFFSET - PACKED_X_LENGTH) >> (64 - PACKED_X_LENGTH)) as i32; @@ -994,18 +992,31 @@ impl AzaleaRead for BlockPos { let z = (val << (64 - Z_OFFSET - PACKED_Z_LENGTH) >> (64 - PACKED_Z_LENGTH)) as i32; Ok(BlockPos { x, y, z }) } + fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { + let mut val: u64 = 0; + val |= ((self.x as u64) & PACKED_X_MASK) << X_OFFSET; + val |= (self.y as u64) & PACKED_Y_MASK; + val |= ((self.z as u64) & PACKED_Z_MASK) << Z_OFFSET; + val.azalea_write(buf) + } } -impl AzaleaRead for GlobalPos { +impl AzBuf for GlobalPos { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { Ok(GlobalPos { dimension: Identifier::azalea_read(buf)?, pos: BlockPos::azalea_read(buf)?, }) } + fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { + Identifier::azalea_write(&self.dimension, buf)?; + BlockPos::azalea_write(&self.pos, buf)?; + + Ok(()) + } } -impl AzaleaRead for ChunkSectionPos { +impl AzBuf for ChunkSectionPos { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let long = i64::azalea_read(buf)?; Ok(ChunkSectionPos { @@ -1014,28 +1025,6 @@ impl AzaleaRead for ChunkSectionPos { z: (long << 22 >> 42) as i32, }) } -} - -impl AzaleaWrite for BlockPos { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - let mut val: u64 = 0; - val |= ((self.x as u64) & PACKED_X_MASK) << X_OFFSET; - val |= (self.y as u64) & PACKED_Y_MASK; - val |= ((self.z as u64) & PACKED_Z_MASK) << Z_OFFSET; - val.azalea_write(buf) - } -} - -impl AzaleaWrite for GlobalPos { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - Identifier::azalea_write(&self.dimension, buf)?; - BlockPos::azalea_write(&self.pos, buf)?; - - Ok(()) - } -} - -impl AzaleaWrite for ChunkSectionPos { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { let long = (((self.x & 0x3FFFFF) as i64) << 42) | (self.y & 0xFFFFF) as i64 diff --git a/azalea-crypto/src/signing.rs b/azalea-crypto/src/signing.rs index c91146ea..dde17b3c 100644 --- a/azalea-crypto/src/signing.rs +++ b/azalea-crypto/src/signing.rs @@ -2,7 +2,7 @@ use std::time::{SystemTime, UNIX_EPOCH}; -use azalea_buf::{AzBuf, AzaleaWrite}; +use azalea_buf::AzBuf; use rsa::{ RsaPrivateKey, signature::{RandomizedSigner, SignatureEncoding}, diff --git a/azalea-entity/src/data.rs b/azalea-entity/src/data.rs index 0b973bcb..e481b9d1 100644 --- a/azalea-entity/src/data.rs +++ b/azalea-entity/src/data.rs @@ -5,7 +5,7 @@ use std::io::{self, Cursor, Write}; -use azalea_buf::{AzBuf, AzaleaRead, AzaleaReadVar, AzaleaWrite, AzaleaWriteVar, BufReadError}; +use azalea_buf::{AzBuf, AzBufVar, BufReadError}; use azalea_chat::FormattedText; use azalea_core::{ direction::Direction, @@ -30,7 +30,7 @@ pub struct EntityDataItem { pub value: EntityDataValue, } -impl AzaleaRead for EntityMetadataItems { +impl AzBuf for EntityMetadataItems { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let mut metadata = Vec::new(); loop { @@ -43,9 +43,6 @@ impl AzaleaRead for EntityMetadataItems { } Ok(EntityMetadataItems(metadata)) } -} - -impl AzaleaWrite for EntityMetadataItems { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { for item in &self.0 { item.index.azalea_write(buf)?; @@ -126,7 +123,7 @@ pub enum ArmadilloStateKind { Scared, } -impl AzaleaRead for OptionalUnsignedInt { +impl AzBuf for OptionalUnsignedInt { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let val = u32::azalea_read_var(buf)?; Ok(OptionalUnsignedInt(if val == 0 { @@ -135,8 +132,6 @@ impl AzaleaRead for OptionalUnsignedInt { Some(val - 1) })) } -} -impl AzaleaWrite for OptionalUnsignedInt { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { match self.0 { Some(val) => (val + 1).azalea_write_var(buf), diff --git a/azalea-entity/src/effects.rs b/azalea-entity/src/effects.rs index 39074ebd..72c757d6 100644 --- a/azalea-entity/src/effects.rs +++ b/azalea-entity/src/effects.rs @@ -3,7 +3,7 @@ use std::{ io::{self, Cursor, Write}, }; -use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite, BufReadError}; +use azalea_buf::{AzBuf, BufReadError}; use azalea_core::bitset::FixedBitSet; use azalea_registry::builtin::MobEffect; @@ -27,7 +27,7 @@ pub struct MobEffectFlags { pub blend: bool, } -impl AzaleaRead for MobEffectFlags { +impl AzBuf for MobEffectFlags { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let bitset = FixedBitSet::<8>::azalea_read(buf)?; let ambient = bitset.index(0); @@ -41,9 +41,6 @@ impl AzaleaRead for MobEffectFlags { blend, }) } -} - -impl AzaleaWrite for MobEffectFlags { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { let mut bitset = FixedBitSet::<8>::new(); if self.ambient { diff --git a/azalea-inventory/src/components/mod.rs b/azalea-inventory/src/components/mod.rs index 5e055592..3d13725a 100644 --- a/azalea-inventory/src/components/mod.rs +++ b/azalea-inventory/src/components/mod.rs @@ -9,7 +9,7 @@ use std::{ mem::ManuallyDrop, }; -use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite, BufReadError}; +use azalea_buf::{AzBuf, BufReadError}; use azalea_chat::FormattedText; use azalea_core::{ attribute_modifier_operation::AttributeModifierOperation, @@ -54,7 +54,7 @@ pub trait EncodableDataComponent: Send + Sync + Any { impl<T> EncodableDataComponent for T where - T: DataComponentTrait + Clone + AzaleaWrite + AzaleaRead + PartialEq, + T: DataComponentTrait + Clone + AzBuf + PartialEq, { fn encode(&self, buf: &mut Vec<u8>) -> io::Result<()> { self.azalea_write(buf) diff --git a/azalea-inventory/src/slot.rs b/azalea-inventory/src/slot.rs index 92dd40b1..c06ac71a 100644 --- a/azalea-inventory/src/slot.rs +++ b/azalea-inventory/src/slot.rs @@ -5,7 +5,7 @@ use std::{ io::{self, Cursor, Write}, }; -use azalea_buf::{AzaleaRead, AzaleaReadVar, AzaleaWrite, AzaleaWriteVar, BufReadError}; +use azalea_buf::{AzBuf, AzBufVar, BufReadError}; use azalea_core::codec_utils::is_default; use azalea_registry::builtin::{DataComponentKind, ItemKind}; use indexmap::IndexMap; @@ -216,7 +216,7 @@ impl ItemStackData { } } -impl AzaleaRead for ItemStack { +impl AzBuf for ItemStack { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let count = i32::azalea_read_var(buf)?; if count <= 0 { @@ -231,9 +231,6 @@ impl AzaleaRead for ItemStack { })) } } -} - -impl AzaleaWrite for ItemStack { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { match self { ItemStack::Empty => 0_i32.azalea_write_var(buf)?, @@ -380,7 +377,7 @@ impl Drop for DataComponentPatch { } } -impl AzaleaRead for DataComponentPatch { +impl AzBuf for DataComponentPatch { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let components_with_data_count = u32::azalea_read_var(buf)?; let components_without_data_count = u32::azalea_read_var(buf)?; @@ -407,9 +404,6 @@ impl AzaleaRead for DataComponentPatch { Ok(components) } -} - -impl AzaleaWrite for DataComponentPatch { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { let mut components_with_data_count: u32 = 0; let mut components_without_data_count: u32 = 0; diff --git a/azalea-protocol/azalea-protocol-macros/src/lib.rs b/azalea-protocol/azalea-protocol-macros/src/lib.rs index bba35762..fcac9c91 100644 --- a/azalea-protocol/azalea-protocol-macros/src/lib.rs +++ b/azalea-protocol/azalea-protocol-macros/src/lib.rs @@ -24,13 +24,13 @@ fn as_packet_derive(input: TokenStream, state: proc_macro2::TokenStream) -> Toke let contents = quote! { impl #ident { pub fn write(&self, buf: &mut impl std::io::Write) -> std::io::Result<()> { - azalea_buf::AzaleaWrite::azalea_write(self, buf) + azalea_buf::AzBuf::azalea_write(self, buf) } pub fn read( buf: &mut std::io::Cursor<&[u8]>, ) -> Result<#state, azalea_buf::BufReadError> { - use azalea_buf::AzaleaRead; + use azalea_buf::AzBuf; Ok(crate::packets::Packet::into_variant(Self::azalea_read(buf)?)) } diff --git a/azalea-protocol/fuzz/README.md b/azalea-protocol/fuzz/README.md index 28b1cf4b..1a9b592c 100644 --- a/azalea-protocol/fuzz/README.md +++ b/azalea-protocol/fuzz/README.md @@ -11,12 +11,12 @@ Additionally, you should be aware that this fuzzer only targets `azalea-protocol ```sh cargo install cargo-fuzz -cargo fuzz run clientbound_game -s none -- -rss_limit_mb=16384 -malloc_limit_mb=1024 -# other valid targets: {clientbound,serverbound}_{config,game,handshake,login,status} -# note: the rss_limit_mb is increased (from the default of 2048) so libfuzzer -# doesn't oom due to the branchiness of the code :( +cargo fuzz run clientbound_game -s none -- -rss_limit_mb=4096 -malloc_limit_mb=1024 +# other valid targets: +# {clientbound,serverbound}_{config,game,handshake,login,status} -# also, the `-s none` is there for increased performance, but at the cost of catching less bugs. feel free to remove it. +# the `-s none` is there for increased performance, but at the cost of catching +# less bugs. feel free to remove it. # also see https://appsec.guide/docs/fuzzing/rust/cargo-fuzz/ ``` diff --git a/azalea-protocol/src/common/client_information.rs b/azalea-protocol/src/common/client_information.rs index 189f1019..46202b45 100644 --- a/azalea-protocol/src/common/client_information.rs +++ b/azalea-protocol/src/common/client_information.rs @@ -1,6 +1,6 @@ use std::io::{self, Cursor}; -use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite}; +use azalea_buf::AzBuf; use azalea_core::bitset::FixedBitSet; use azalea_entity::HumanoidArm; @@ -94,7 +94,7 @@ impl Default for ModelCustomization { } } -impl AzaleaRead for ModelCustomization { +impl AzBuf for ModelCustomization { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, azalea_buf::BufReadError> { let set = FixedBitSet::<7>::azalea_read(buf)?; Ok(Self { @@ -107,9 +107,6 @@ impl AzaleaRead for ModelCustomization { hat: set.index(6), }) } -} - -impl AzaleaWrite for ModelCustomization { fn azalea_write(&self, buf: &mut impl io::Write) -> io::Result<()> { let mut set = FixedBitSet::<7>::new(); if self.cape { @@ -141,7 +138,7 @@ impl AzaleaWrite for ModelCustomization { mod tests { use std::io::Cursor; - use azalea_buf::{AzaleaRead, AzaleaWrite}; + use azalea_buf::AzBuf; use super::*; diff --git a/azalea-protocol/src/common/movements.rs b/azalea-protocol/src/common/movements.rs index 82559f86..67cfb272 100644 --- a/azalea-protocol/src/common/movements.rs +++ b/azalea-protocol/src/common/movements.rs @@ -3,7 +3,7 @@ use std::{ ops::Add, }; -use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite, BufReadError}; +use azalea_buf::{AzBuf, BufReadError}; use azalea_core::{bitset::FixedBitSet, math, position::Vec3}; use azalea_entity::{LookDirection, Physics, Position}; @@ -91,7 +91,7 @@ fn apply_change<T: Add<Output = T>>(base: T, condition: bool, change: T) -> T { if condition { base + change } else { change } } -impl AzaleaRead for RelativeMovements { +impl AzBuf for RelativeMovements { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { // yes minecraft seriously wastes that many bits, smh let set = u32::azalea_read(buf)?; @@ -108,9 +108,6 @@ impl AzaleaRead for RelativeMovements { rotate_delta: set.index(8), }) } -} - -impl AzaleaWrite for RelativeMovements { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { let mut set = FixedBitSet::<32>::new(); let mut set_bit = |index: usize, value: bool| { @@ -138,7 +135,16 @@ pub struct MoveFlags { pub on_ground: bool, pub horizontal_collision: bool, } -impl AzaleaWrite for MoveFlags { +impl AzBuf for MoveFlags { + fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { + let bitset = FixedBitSet::<8>::azalea_read(buf)?; + let on_ground = bitset.index(0); + let horizontal_collision = bitset.index(1); + Ok(Self { + on_ground, + horizontal_collision, + }) + } fn azalea_write(&self, buf: &mut impl io::Write) -> Result<(), io::Error> { let mut bitset = FixedBitSet::<8>::new(); if self.on_ground { @@ -151,14 +157,3 @@ impl AzaleaWrite for MoveFlags { Ok(()) } } -impl AzaleaRead for MoveFlags { - fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - let bitset = FixedBitSet::<8>::azalea_read(buf)?; - let on_ground = bitset.index(0); - let horizontal_collision = bitset.index(1); - Ok(Self { - on_ground, - horizontal_collision, - }) - } -} diff --git a/azalea-protocol/src/common/tags.rs b/azalea-protocol/src/common/tags.rs index 3f9a2ef2..75c50ff5 100644 --- a/azalea-protocol/src/common/tags.rs +++ b/azalea-protocol/src/common/tags.rs @@ -3,7 +3,7 @@ use std::{ ops::Deref, }; -use azalea_buf::{AzaleaRead, AzaleaReadVar, AzaleaWrite, AzaleaWriteVar, BufReadError}; +use azalea_buf::{AzBuf, AzBufVar, BufReadError}; use azalea_registry::identifier::Identifier; use indexmap::IndexMap; @@ -16,7 +16,7 @@ pub struct Tags { pub elements: Vec<i32>, } -impl AzaleaRead for TagMap { +impl AzBuf for TagMap { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let length = u32::azalea_read_var(buf)? as usize; let mut data = IndexMap::new(); @@ -32,9 +32,6 @@ impl AzaleaRead for TagMap { } Ok(TagMap(data)) } -} - -impl AzaleaWrite for TagMap { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { (self.len() as u32).azalea_write_var(buf)?; for (k, v) in &self.0 { @@ -44,15 +41,12 @@ impl AzaleaWrite for TagMap { Ok(()) } } -impl AzaleaRead for Tags { +impl AzBuf for Tags { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let name = Identifier::azalea_read(buf)?; let elements = Vec::<i32>::azalea_read_var(buf)?; Ok(Tags { name, elements }) } -} - -impl AzaleaWrite for Tags { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { self.name.azalea_write(buf)?; self.elements.azalea_write_var(buf)?; diff --git a/azalea-protocol/src/packets/game/c_boss_event.rs b/azalea-protocol/src/packets/game/c_boss_event.rs index 10cf30d4..19bd74a9 100644 --- a/azalea-protocol/src/packets/game/c_boss_event.rs +++ b/azalea-protocol/src/packets/game/c_boss_event.rs @@ -3,7 +3,7 @@ use std::{ io::{Cursor, Write}, }; -use azalea_buf::{AzBuf, AzaleaRead, AzaleaReadVar, AzaleaWrite, AzaleaWriteVar, BufReadError}; +use azalea_buf::{AzBuf, AzBufVar, BufReadError}; use azalea_chat::FormattedText; use azalea_core::bitset::FixedBitSet; use azalea_protocol_macros::ClientboundGamePacket; @@ -25,7 +25,7 @@ pub enum Operation { UpdateProperties(Properties), } -impl AzaleaRead for Operation { +impl AzBuf for Operation { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let operation_id = u32::azalea_read_var(buf)?; Ok(match operation_id { @@ -42,9 +42,6 @@ impl AzaleaRead for Operation { } }) } -} - -impl AzaleaWrite for Operation { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { match self { Operation::Add(add) => { @@ -116,7 +113,7 @@ pub struct Properties { pub create_world_fog: bool, } -impl AzaleaRead for Properties { +impl AzBuf for Properties { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let set = FixedBitSet::<3>::azalea_read(buf)?; Ok(Self { @@ -125,9 +122,6 @@ impl AzaleaRead for Properties { create_world_fog: set.index(2), }) } -} - -impl AzaleaWrite for Properties { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { let mut set = FixedBitSet::<3>::new(); if self.darken_screen { diff --git a/azalea-protocol/src/packets/game/c_command_suggestions.rs b/azalea-protocol/src/packets/game/c_command_suggestions.rs index a0036edf..09307ee1 100644 --- a/azalea-protocol/src/packets/game/c_command_suggestions.rs +++ b/azalea-protocol/src/packets/game/c_command_suggestions.rs @@ -14,7 +14,7 @@ mod tests { use std::io::Cursor; use azalea_brigadier::{context::StringRange, suggestion::Suggestion}; - use azalea_buf::{AzaleaRead, AzaleaWrite}; + use azalea_buf::AzBuf; use super::*; diff --git a/azalea-protocol/src/packets/game/c_commands.rs b/azalea-protocol/src/packets/game/c_commands.rs index f8d95ac9..12d47e53 100644 --- a/azalea-protocol/src/packets/game/c_commands.rs +++ b/azalea-protocol/src/packets/game/c_commands.rs @@ -1,6 +1,6 @@ use std::io::{self, Cursor, Write}; -use azalea_buf::{AzBuf, AzaleaRead, AzaleaReadVar, AzaleaWrite, AzaleaWriteVar, BufReadError}; +use azalea_buf::{AzBuf, AzBufVar, BufReadError}; use azalea_core::bitset::FixedBitSet; use azalea_protocol_macros::ClientboundGamePacket; use azalea_registry::identifier::Identifier; @@ -46,7 +46,7 @@ impl<T: PartialEq> PartialEq for BrigadierNumber<T> { } } -impl<T: AzaleaRead> AzaleaRead for BrigadierNumber<T> { +impl<T: AzBuf> AzBuf for BrigadierNumber<T> { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let flags = FixedBitSet::<2>::azalea_read(buf)?; let min = if flags.index(0) { @@ -61,8 +61,6 @@ impl<T: AzaleaRead> AzaleaRead for BrigadierNumber<T> { }; Ok(BrigadierNumber { min, max }) } -} -impl<T: AzaleaWrite> AzaleaWrite for BrigadierNumber<T> { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { let mut flags = FixedBitSet::<2>::new(); if self.min.is_some() { @@ -160,7 +158,7 @@ pub struct EntityParser { pub single: bool, pub players_only: bool, } -impl AzaleaRead for EntityParser { +impl AzBuf for EntityParser { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let flags = FixedBitSet::<2>::azalea_read(buf)?; Ok(EntityParser { @@ -168,8 +166,6 @@ impl AzaleaRead for EntityParser { players_only: flags.index(1), }) } -} -impl AzaleaWrite for EntityParser { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { let mut flags = FixedBitSet::<2>::new(); if self.single { @@ -184,7 +180,7 @@ impl AzaleaWrite for EntityParser { } // TODO: BrigadierNodeStub should have more stuff -impl AzaleaRead for BrigadierNodeStub { +impl AzBuf for BrigadierNodeStub { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let flags = FixedBitSet::<8>::azalea_read(buf)?; if flags.index(6) || flags.index(7) { @@ -247,9 +243,6 @@ impl AzaleaRead for BrigadierNodeStub { }) } } -} - -impl AzaleaWrite for BrigadierNodeStub { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { let mut flags = FixedBitSet::<4>::new(); if self.is_executable { diff --git a/azalea-protocol/src/packets/game/c_container_set_content.rs b/azalea-protocol/src/packets/game/c_container_set_content.rs index a97973ee..bb487b20 100644 --- a/azalea-protocol/src/packets/game/c_container_set_content.rs +++ b/azalea-protocol/src/packets/game/c_container_set_content.rs @@ -16,7 +16,7 @@ pub struct ClientboundContainerSetContent { mod tests { use std::io::Cursor; - use azalea_buf::AzaleaRead; + use azalea_buf::AzBuf; use super::ClientboundContainerSetContent; diff --git a/azalea-protocol/src/packets/game/c_damage_event.rs b/azalea-protocol/src/packets/game/c_damage_event.rs index 76ceb8ec..e24878d4 100644 --- a/azalea-protocol/src/packets/game/c_damage_event.rs +++ b/azalea-protocol/src/packets/game/c_damage_event.rs @@ -1,9 +1,8 @@ use std::io::{self, Cursor, Write}; -use azalea_buf::{AzBuf, AzaleaRead, AzaleaReadVar, AzaleaWrite, AzaleaWriteVar}; -use azalea_core::position::Vec3; +use azalea_buf::{AzBuf, AzBufVar}; +use azalea_core::{entity_id::MinecraftEntityId, position::Vec3}; use azalea_protocol_macros::ClientboundGamePacket; -use azalea_core::entity_id::MinecraftEntityId; #[derive(AzBuf, ClientboundGamePacket, Clone, Debug, PartialEq)] pub struct ClientboundDamageEvent { @@ -18,15 +17,13 @@ pub struct ClientboundDamageEvent { #[derive(Clone, Debug, PartialEq)] pub struct OptionalEntityId(pub Option<u32>); -impl AzaleaRead for OptionalEntityId { +impl AzBuf for OptionalEntityId { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, azalea_buf::BufReadError> { match u32::azalea_read_var(buf)? { 0 => Ok(OptionalEntityId(None)), id => Ok(OptionalEntityId(Some(id - 1))), } } -} -impl AzaleaWrite for OptionalEntityId { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { match self.0 { Some(id) => (id + 1).azalea_write_var(buf), diff --git a/azalea-protocol/src/packets/game/c_explode.rs b/azalea-protocol/src/packets/game/c_explode.rs index be86abb6..651c856d 100644 --- a/azalea-protocol/src/packets/game/c_explode.rs +++ b/azalea-protocol/src/packets/game/c_explode.rs @@ -1,4 +1,4 @@ -use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite}; +use azalea_buf::AzBuf; use azalea_core::position::Vec3; use azalea_entity::particle::Particle; use azalea_protocol_macros::ClientboundGamePacket; @@ -16,7 +16,7 @@ pub struct ClientboundExplode { } #[derive(AzBuf, Clone, Debug, PartialEq)] -pub struct Weighted<T: AzaleaRead + AzaleaWrite> { +pub struct Weighted<T: AzBuf> { pub value: T, #[var] pub weight: i32, diff --git a/azalea-protocol/src/packets/game/c_map_item_data.rs b/azalea-protocol/src/packets/game/c_map_item_data.rs index 2330ce07..2d93f0e1 100644 --- a/azalea-protocol/src/packets/game/c_map_item_data.rs +++ b/azalea-protocol/src/packets/game/c_map_item_data.rs @@ -1,6 +1,6 @@ use std::io::{self, Cursor, Write}; -use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite}; +use azalea_buf::AzBuf; use azalea_chat::FormattedText; use azalea_protocol_macros::ClientboundGamePacket; @@ -28,7 +28,7 @@ pub struct MapDecoration { #[derive(Clone, Debug, PartialEq)] pub struct OptionalMapPatch(pub Option<MapPatch>); -impl AzaleaRead for OptionalMapPatch { +impl AzBuf for OptionalMapPatch { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, azalea_buf::BufReadError> { let pos = buf.position(); Ok(Self(if u8::azalea_read(buf)? == 0 { @@ -38,9 +38,6 @@ impl AzaleaRead for OptionalMapPatch { Some(MapPatch::azalea_read(buf)?) })) } -} - -impl AzaleaWrite for OptionalMapPatch { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { match &self.0 { None => 0u8.azalea_write(buf), diff --git a/azalea-protocol/src/packets/game/c_merchant_offers.rs b/azalea-protocol/src/packets/game/c_merchant_offers.rs index 957060b4..fb2de37a 100644 --- a/azalea-protocol/src/packets/game/c_merchant_offers.rs +++ b/azalea-protocol/src/packets/game/c_merchant_offers.rs @@ -5,7 +5,7 @@ use std::{ mem::ManuallyDrop, }; -use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite, BufReadError}; +use azalea_buf::{AzBuf, BufReadError}; use azalea_inventory::{ DataComponentPatch, ItemStack, ItemStackData, components::{self, DataComponentUnion}, @@ -107,14 +107,12 @@ impl TypedDataComponent { component_any.downcast_ref::<T>() } } -impl AzaleaRead for TypedDataComponent { +impl AzBuf for TypedDataComponent { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let kind = DataComponentKind::azalea_read(buf)?; let value = DataComponentUnion::azalea_read_as(kind, buf)?; Ok(Self { kind, value }) } -} -impl AzaleaWrite for TypedDataComponent { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { self.kind.azalea_write(buf)?; unsafe { self.value.azalea_write_as(self.kind, buf) } diff --git a/azalea-protocol/src/packets/game/c_player_abilities.rs b/azalea-protocol/src/packets/game/c_player_abilities.rs index 926f4f2f..ac856ca4 100644 --- a/azalea-protocol/src/packets/game/c_player_abilities.rs +++ b/azalea-protocol/src/packets/game/c_player_abilities.rs @@ -1,6 +1,6 @@ use std::io::{self, Cursor, Write}; -use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite, BufReadError}; +use azalea_buf::{AzBuf, BufReadError}; use azalea_core::bitset::FixedBitSet; use azalea_entity::PlayerAbilities; use azalea_protocol_macros::ClientboundGamePacket; @@ -21,7 +21,7 @@ pub struct PlayerAbilitiesFlags { pub instant_break: bool, } -impl AzaleaRead for PlayerAbilitiesFlags { +impl AzBuf for PlayerAbilitiesFlags { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let set = FixedBitSet::<4>::azalea_read(buf)?; Ok(PlayerAbilitiesFlags { @@ -31,9 +31,6 @@ impl AzaleaRead for PlayerAbilitiesFlags { instant_break: set.index(3), }) } -} - -impl AzaleaWrite for PlayerAbilitiesFlags { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { let mut set = FixedBitSet::<4>::new(); if self.invulnerable { diff --git a/azalea-protocol/src/packets/game/c_player_chat.rs b/azalea-protocol/src/packets/game/c_player_chat.rs index a63ab56d..cfb08803 100644 --- a/azalea-protocol/src/packets/game/c_player_chat.rs +++ b/azalea-protocol/src/packets/game/c_player_chat.rs @@ -3,7 +3,7 @@ use std::{ sync::LazyLock, }; -use azalea_buf::{AzBuf, AzaleaRead, AzaleaReadVar, AzaleaWrite, AzaleaWriteVar, BufReadError}; +use azalea_buf::{AzBuf, AzBufVar, BufReadError}; use azalea_chat::{ FormattedText, translatable_component::{PrimitiveOrComponent, TranslatableComponent}, @@ -180,7 +180,7 @@ impl ChatTypeBound { } } -impl AzaleaRead for PackedMessageSignature { +impl AzBuf for PackedMessageSignature { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let id = u32::azalea_read_var(buf)?; if id == 0 { @@ -191,8 +191,6 @@ impl AzaleaRead for PackedMessageSignature { Ok(PackedMessageSignature::Id(id - 1)) } } -} -impl AzaleaWrite for PackedMessageSignature { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { match self { PackedMessageSignature::Signature(full_signature) => { diff --git a/azalea-protocol/src/packets/game/c_player_info_update.rs b/azalea-protocol/src/packets/game/c_player_info_update.rs index 4a18233e..0bce5724 100644 --- a/azalea-protocol/src/packets/game/c_player_info_update.rs +++ b/azalea-protocol/src/packets/game/c_player_info_update.rs @@ -4,7 +4,7 @@ use std::{ }; use azalea_auth::game_profile::{GameProfile, GameProfileProperties}; -use azalea_buf::{AzBuf, AzaleaRead, AzaleaReadVar, AzaleaWrite, AzaleaWriteVar, BufReadError}; +use azalea_buf::{AzBuf, AzBufVar, BufReadError}; use azalea_chat::FormattedText; use azalea_core::{bitset::FixedBitSet, game_type::GameMode}; use azalea_protocol_macros::ClientboundGamePacket; @@ -66,7 +66,7 @@ pub struct UpdateListOrderAction { pub list_order: i32, } -impl AzaleaRead for ClientboundPlayerInfoUpdate { +impl AzBuf for ClientboundPlayerInfoUpdate { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let actions = ActionEnumSet::azalea_read(buf)?; let mut entries = Vec::new(); @@ -116,9 +116,6 @@ impl AzaleaRead for ClientboundPlayerInfoUpdate { Ok(ClientboundPlayerInfoUpdate { actions, entries }) } -} - -impl AzaleaWrite for ClientboundPlayerInfoUpdate { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { self.actions.azalea_write(buf)?; @@ -181,7 +178,7 @@ pub struct ActionEnumSet { pub update_list_order: bool, } -impl AzaleaRead for ActionEnumSet { +impl AzBuf for ActionEnumSet { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let set = FixedBitSet::<7>::azalea_read(buf)?; Ok(ActionEnumSet { @@ -195,9 +192,6 @@ impl AzaleaRead for ActionEnumSet { update_list_order: set.index(7), }) } -} - -impl AzaleaWrite for ActionEnumSet { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { let mut set = FixedBitSet::<7>::new(); if self.add_player { diff --git a/azalea-protocol/src/packets/game/c_section_blocks_update.rs b/azalea-protocol/src/packets/game/c_section_blocks_update.rs index 070d2a9e..8803e34a 100644 --- a/azalea-protocol/src/packets/game/c_section_blocks_update.rs +++ b/azalea-protocol/src/packets/game/c_section_blocks_update.rs @@ -1,7 +1,7 @@ use std::io::{self, Cursor, Write}; use azalea_block::BlockState; -use azalea_buf::{AzBuf, AzaleaRead, AzaleaReadVar, AzaleaWrite, AzaleaWriteVar, BufReadError}; +use azalea_buf::{AzBuf, AzBufVar, BufReadError}; use azalea_core::position::{ChunkSectionBlockPos, ChunkSectionPos}; use azalea_protocol_macros::ClientboundGamePacket; @@ -17,7 +17,7 @@ pub struct BlockStateWithPosition { pub state: BlockState, } -impl AzaleaRead for BlockStateWithPosition { +impl AzBuf for BlockStateWithPosition { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let data = u64::azalea_read_var(buf)?; let position_part = data & 4095; @@ -31,9 +31,6 @@ impl AzaleaRead for BlockStateWithPosition { }; Ok(BlockStateWithPosition { pos, state }) } -} - -impl AzaleaWrite for BlockStateWithPosition { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { let data = ((self.state.id() as u64) << 12) | ((u64::from(self.pos.x) << 8) | (u64::from(self.pos.z) << 4) | u64::from(self.pos.y)); diff --git a/azalea-protocol/src/packets/game/c_server_links.rs b/azalea-protocol/src/packets/game/c_server_links.rs index 75869492..433254d6 100644 --- a/azalea-protocol/src/packets/game/c_server_links.rs +++ b/azalea-protocol/src/packets/game/c_server_links.rs @@ -12,7 +12,7 @@ pub struct ClientboundServerLinks { mod tests { use std::io::Cursor; - use azalea_buf::AzaleaRead; + use azalea_buf::AzBuf; use super::*; diff --git a/azalea-protocol/src/packets/game/c_set_entity_data.rs b/azalea-protocol/src/packets/game/c_set_entity_data.rs index d9effc37..1b4b46cd 100644 --- a/azalea-protocol/src/packets/game/c_set_entity_data.rs +++ b/azalea-protocol/src/packets/game/c_set_entity_data.rs @@ -1,7 +1,7 @@ use azalea_buf::AzBuf; +use azalea_core::entity_id::MinecraftEntityId; use azalea_entity::EntityMetadataItems; use azalea_protocol_macros::ClientboundGamePacket; -use azalea_core::entity_id::MinecraftEntityId; #[derive(AzBuf, ClientboundGamePacket, Clone, Debug, PartialEq)] pub struct ClientboundSetEntityData { @@ -14,7 +14,7 @@ pub struct ClientboundSetEntityData { mod tests { use std::io::Cursor; - use azalea_buf::AzaleaRead; + use azalea_buf::AzBuf; use super::*; diff --git a/azalea-protocol/src/packets/game/c_set_equipment.rs b/azalea-protocol/src/packets/game/c_set_equipment.rs index 7d7ceac9..11ee8b3a 100644 --- a/azalea-protocol/src/packets/game/c_set_equipment.rs +++ b/azalea-protocol/src/packets/game/c_set_equipment.rs @@ -1,9 +1,9 @@ use std::io::{self, Cursor, Write}; -use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite, BufReadError}; +use azalea_buf::{AzBuf, BufReadError}; +use azalea_core::entity_id::MinecraftEntityId; use azalea_inventory::{ItemStack, components::EquipmentSlot}; use azalea_protocol_macros::ClientboundGamePacket; -use azalea_core::entity_id::MinecraftEntityId; #[derive(AzBuf, ClientboundGamePacket, Clone, Debug, PartialEq)] pub struct ClientboundSetEquipment { @@ -17,7 +17,7 @@ pub struct EquipmentSlots { pub slots: Vec<(EquipmentSlot, ItemStack)>, } -impl AzaleaRead for EquipmentSlots { +impl AzBuf for EquipmentSlots { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let mut slots = vec![]; @@ -38,8 +38,6 @@ impl AzaleaRead for EquipmentSlots { Ok(EquipmentSlots { slots }) } -} -impl AzaleaWrite for EquipmentSlots { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { for i in 0..self.slots.len() { let (equipment_slot, item) = &self.slots[i]; diff --git a/azalea-protocol/src/packets/game/c_set_objective.rs b/azalea-protocol/src/packets/game/c_set_objective.rs index dad4ccdf..237cd2ea 100644 --- a/azalea-protocol/src/packets/game/c_set_objective.rs +++ b/azalea-protocol/src/packets/game/c_set_objective.rs @@ -1,6 +1,6 @@ use std::io::{self, Cursor, Write}; -use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite}; +use azalea_buf::AzBuf; use azalea_chat::{FormattedText, numbers::NumberFormat}; use azalea_core::objectives::ObjectiveCriteria; use azalea_protocol_macros::ClientboundGamePacket; @@ -33,7 +33,7 @@ pub enum Method { }, } -impl AzaleaRead for Method { +impl AzBuf for Method { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, azalea_buf::BufReadError> { let kind = MethodKind::azalea_read(buf)?; match kind { @@ -50,9 +50,6 @@ impl AzaleaRead for Method { }), } } -} - -impl AzaleaWrite for Method { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { match self { Method::Add { diff --git a/azalea-protocol/src/packets/game/c_set_player_team.rs b/azalea-protocol/src/packets/game/c_set_player_team.rs index e8c85886..a1105231 100644 --- a/azalea-protocol/src/packets/game/c_set_player_team.rs +++ b/azalea-protocol/src/packets/game/c_set_player_team.rs @@ -50,7 +50,7 @@ type PlayerList = Vec<String>; mod tests { use std::io::Cursor; - use azalea_buf::AzaleaRead; + use azalea_buf::AzBuf; use crate::packets::game::ClientboundSetPlayerTeam; diff --git a/azalea-protocol/src/packets/game/c_sound.rs b/azalea-protocol/src/packets/game/c_sound.rs index a380532c..e2a4f513 100644 --- a/azalea-protocol/src/packets/game/c_sound.rs +++ b/azalea-protocol/src/packets/game/c_sound.rs @@ -34,7 +34,7 @@ pub enum SoundSource { mod tests { use std::io::Cursor; - use azalea_buf::AzaleaRead; + use azalea_buf::AzBuf; use crate::packets::game::ClientboundSound; diff --git a/azalea-protocol/src/packets/game/c_stop_sound.rs b/azalea-protocol/src/packets/game/c_stop_sound.rs index 6225a759..0afba2c7 100644 --- a/azalea-protocol/src/packets/game/c_stop_sound.rs +++ b/azalea-protocol/src/packets/game/c_stop_sound.rs @@ -1,6 +1,6 @@ use std::io::{self, Cursor, Write}; -use azalea_buf::{AzaleaRead, AzaleaWrite, BufReadError}; +use azalea_buf::{AzBuf, BufReadError}; use azalea_core::bitset::FixedBitSet; use azalea_protocol_macros::ClientboundGamePacket; use azalea_registry::identifier::Identifier; @@ -13,7 +13,7 @@ pub struct ClientboundStopSound { pub name: Option<Identifier>, } -impl AzaleaRead for ClientboundStopSound { +impl AzBuf for ClientboundStopSound { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let set = FixedBitSet::<2>::azalea_read(buf)?; let source = if set.index(0) { @@ -29,9 +29,6 @@ impl AzaleaRead for ClientboundStopSound { Ok(Self { source, name }) } -} - -impl AzaleaWrite for ClientboundStopSound { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { let mut set = FixedBitSet::<2>::new(); if self.source.is_some() { diff --git a/azalea-protocol/src/packets/game/c_system_chat.rs b/azalea-protocol/src/packets/game/c_system_chat.rs index 491825f4..a72c003e 100644 --- a/azalea-protocol/src/packets/game/c_system_chat.rs +++ b/azalea-protocol/src/packets/game/c_system_chat.rs @@ -12,7 +12,7 @@ pub struct ClientboundSystemChat { mod tests { use std::io::Cursor; - use azalea_buf::AzaleaRead; + use azalea_buf::AzBuf; use super::*; diff --git a/azalea-protocol/src/packets/game/c_tab_list.rs b/azalea-protocol/src/packets/game/c_tab_list.rs index 9a360dac..160c1a1e 100644 --- a/azalea-protocol/src/packets/game/c_tab_list.rs +++ b/azalea-protocol/src/packets/game/c_tab_list.rs @@ -12,7 +12,7 @@ pub struct ClientboundTabList { mod tests { use std::io::Cursor; - use azalea_buf::AzaleaRead; + use azalea_buf::AzBuf; use super::*; diff --git a/azalea-protocol/src/packets/game/c_update_advancements.rs b/azalea-protocol/src/packets/game/c_update_advancements.rs index 24baebc5..e4cc745a 100644 --- a/azalea-protocol/src/packets/game/c_update_advancements.rs +++ b/azalea-protocol/src/packets/game/c_update_advancements.rs @@ -3,7 +3,7 @@ use std::{ io::{self, Cursor, Write}, }; -use azalea_buf::{AzBuf, AzaleaWrite}; +use azalea_buf::AzBuf; use azalea_chat::FormattedText; use azalea_inventory::ItemStack; use azalea_protocol_macros::ClientboundGamePacket; @@ -40,7 +40,37 @@ pub struct DisplayInfo { pub y: f32, } -impl AzaleaWrite for DisplayInfo { +impl AzBuf for DisplayInfo { + fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, azalea_buf::BufReadError> { + let title = AzBuf::azalea_read(buf)?; + let description = AzBuf::azalea_read(buf)?; + let icon = AzBuf::azalea_read(buf)?; + let frame = AzBuf::azalea_read(buf)?; + + let data = u32::azalea_read(buf)?; + let has_background = (data & 0b1) != 0; + let show_toast = (data & 0b10) != 0; + let hidden = (data & 0b100) != 0; + + let background = if has_background { + Some(Identifier::azalea_read(buf)?) + } else { + None + }; + let x = AzBuf::azalea_read(buf)?; + let y = AzBuf::azalea_read(buf)?; + Ok(DisplayInfo { + title, + description, + icon, + frame, + show_toast, + hidden, + background, + x, + y, + }) + } fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { self.title.azalea_write(buf)?; self.description.azalea_write(buf)?; @@ -67,38 +97,6 @@ impl AzaleaWrite for DisplayInfo { Ok(()) } } -impl azalea_buf::AzaleaRead for DisplayInfo { - fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, azalea_buf::BufReadError> { - let title = azalea_buf::AzaleaRead::azalea_read(buf)?; - let description = azalea_buf::AzaleaRead::azalea_read(buf)?; - let icon = azalea_buf::AzaleaRead::azalea_read(buf)?; - let frame = azalea_buf::AzaleaRead::azalea_read(buf)?; - - let data = u32::azalea_read(buf)?; - let has_background = (data & 0b1) != 0; - let show_toast = (data & 0b10) != 0; - let hidden = (data & 0b100) != 0; - - let background = if has_background { - Some(Identifier::azalea_read(buf)?) - } else { - None - }; - let x = azalea_buf::AzaleaRead::azalea_read(buf)?; - let y = azalea_buf::AzaleaRead::azalea_read(buf)?; - Ok(DisplayInfo { - title, - description, - icon, - frame, - show_toast, - hidden, - background, - x, - y, - }) - } -} #[derive(AzBuf, Clone, Copy, Debug, PartialEq)] pub enum FrameType { @@ -122,7 +120,7 @@ pub struct AdvancementHolder { #[cfg(test)] mod tests { - use azalea_buf::{AzaleaRead, AzaleaWrite}; + use azalea_buf::AzBuf; use super::*; diff --git a/azalea-protocol/src/packets/game/c_waypoint.rs b/azalea-protocol/src/packets/game/c_waypoint.rs index 38a160e9..45f4ff6a 100644 --- a/azalea-protocol/src/packets/game/c_waypoint.rs +++ b/azalea-protocol/src/packets/game/c_waypoint.rs @@ -1,6 +1,6 @@ use std::io::{self, Cursor, Write}; -use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite, BufReadError}; +use azalea_buf::{AzBuf, BufReadError}; use azalea_core::{color::RgbColor, position::Vec3i}; use azalea_protocol_macros::ClientboundGamePacket; use azalea_registry::identifier::Identifier; @@ -37,7 +37,7 @@ pub struct WaypointIcon { pub style: Identifier, pub color: Option<RgbColor>, } -impl AzaleaWrite for WaypointIcon { +impl AzBuf for WaypointIcon { fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> { self.style.azalea_write(buf)?; let color = self.color.map(|c| CompactRgbColor { @@ -48,8 +48,6 @@ impl AzaleaWrite for WaypointIcon { color.azalea_write(buf)?; Ok(()) } -} -impl AzaleaRead for WaypointIcon { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let style = Identifier::azalea_read(buf)?; let color = Option::<CompactRgbColor>::azalea_read(buf)?; diff --git a/azalea-protocol/src/packets/game/s_interact.rs b/azalea-protocol/src/packets/game/s_interact.rs index d368354f..bd04e09d 100644 --- a/azalea-protocol/src/packets/game/s_interact.rs +++ b/azalea-protocol/src/packets/game/s_interact.rs @@ -1,9 +1,11 @@ use std::io::{self, Cursor, Write}; -use azalea_buf::{AzBuf, AzaleaRead, AzaleaReadVar, AzaleaWrite, AzaleaWriteVar}; -use azalea_core::position::Vec3; +use azalea_buf::{AzBuf, AzBufVar}; +use azalea_core::{ + entity_id::MinecraftEntityId, + position::{Vec3, Vec3f32}, +}; use azalea_protocol_macros::ServerboundGamePacket; -use azalea_core::entity_id::MinecraftEntityId; use crate::packets::BufReadError; @@ -28,29 +30,7 @@ pub enum ActionType { }, } -impl AzaleaWrite for ActionType { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - match self { - ActionType::Interact { hand } => { - 0u32.azalea_write_var(buf)?; - hand.azalea_write(buf)?; - } - ActionType::Attack => { - 1u32.azalea_write_var(buf)?; - } - ActionType::InteractAt { location, hand } => { - 2u32.azalea_write_var(buf)?; - (location.x as f32).azalea_write(buf)?; - (location.y as f32).azalea_write(buf)?; - (location.z as f32).azalea_write(buf)?; - hand.azalea_write(buf)?; - } - } - Ok(()) - } -} - -impl AzaleaRead for ActionType { +impl AzBuf for ActionType { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let action_type = u32::azalea_read_var(buf)?; match action_type { @@ -60,16 +40,10 @@ impl AzaleaRead for ActionType { } 1 => Ok(ActionType::Attack), 2 => { - let x = f32::azalea_read(buf)?; - let y = f32::azalea_read(buf)?; - let z = f32::azalea_read(buf)?; + let pos = Vec3f32::azalea_read(buf)?; let hand = InteractionHand::azalea_read(buf)?; Ok(ActionType::InteractAt { - location: Vec3 { - x: f64::from(x), - y: f64::from(y), - z: f64::from(z), - }, + location: Vec3::from(pos), hand, }) } @@ -78,6 +52,25 @@ impl AzaleaRead for ActionType { }), } } + fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { + match self { + ActionType::Interact { hand } => { + 0u32.azalea_write_var(buf)?; + hand.azalea_write(buf)?; + } + ActionType::Attack => { + 1u32.azalea_write_var(buf)?; + } + ActionType::InteractAt { location, hand } => { + 2u32.azalea_write_var(buf)?; + (location.x as f32).azalea_write(buf)?; + (location.y as f32).azalea_write(buf)?; + (location.z as f32).azalea_write(buf)?; + hand.azalea_write(buf)?; + } + } + Ok(()) + } } #[derive(AzBuf, Clone, Copy, Debug, Default, PartialEq)] diff --git a/azalea-protocol/src/packets/game/s_player_abilities.rs b/azalea-protocol/src/packets/game/s_player_abilities.rs index 2eff36cb..59e9ab93 100644 --- a/azalea-protocol/src/packets/game/s_player_abilities.rs +++ b/azalea-protocol/src/packets/game/s_player_abilities.rs @@ -1,6 +1,6 @@ use std::io::{self, Cursor, Write}; -use azalea_buf::{AzaleaRead, AzaleaWrite}; +use azalea_buf::AzBuf; use azalea_core::bitset::FixedBitSet; use azalea_protocol_macros::ServerboundGamePacket; @@ -11,16 +11,13 @@ pub struct ServerboundPlayerAbilities { pub is_flying: bool, } -impl AzaleaRead for ServerboundPlayerAbilities { +impl AzBuf for ServerboundPlayerAbilities { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let set = FixedBitSet::<2>::azalea_read(buf)?; Ok(Self { is_flying: set.index(1), }) } -} - -impl AzaleaWrite for ServerboundPlayerAbilities { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { let mut set = FixedBitSet::<2>::new(); if self.is_flying { diff --git a/azalea-protocol/src/packets/game/s_player_input.rs b/azalea-protocol/src/packets/game/s_player_input.rs index e92d6101..46ebbcf6 100644 --- a/azalea-protocol/src/packets/game/s_player_input.rs +++ b/azalea-protocol/src/packets/game/s_player_input.rs @@ -1,7 +1,6 @@ use std::io::{self, Cursor, Write}; -use azalea_buf::BufReadError; -use azalea_buf::{AzaleaRead, AzaleaWrite}; +use azalea_buf::{AzBuf, BufReadError}; use azalea_core::bitset::FixedBitSet; use azalea_protocol_macros::ServerboundGamePacket; @@ -16,7 +15,7 @@ pub struct ServerboundPlayerInput { pub sprint: bool, } -impl AzaleaRead for ServerboundPlayerInput { +impl AzBuf for ServerboundPlayerInput { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let set = FixedBitSet::<7>::azalea_read(buf)?; Ok(Self { @@ -29,9 +28,6 @@ impl AzaleaRead for ServerboundPlayerInput { sprint: set.index(6), }) } -} - -impl AzaleaWrite for ServerboundPlayerInput { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { let mut set = FixedBitSet::<7>::new(); if self.forward { diff --git a/azalea-protocol/src/packets/game/s_seen_advancements.rs b/azalea-protocol/src/packets/game/s_seen_advancements.rs index 7e001b7f..cdb12dd4 100644 --- a/azalea-protocol/src/packets/game/s_seen_advancements.rs +++ b/azalea-protocol/src/packets/game/s_seen_advancements.rs @@ -1,8 +1,8 @@ use std::io::{self, Cursor, Write}; -use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite}; -use azalea_registry::identifier::Identifier; +use azalea_buf::AzBuf; use azalea_protocol_macros::ServerboundGamePacket; +use azalea_registry::identifier::Identifier; use crate::packets::BufReadError; @@ -18,7 +18,7 @@ pub enum Action { ClosedScreen = 1, } -impl AzaleaRead for ServerboundSeenAdvancements { +impl AzBuf for ServerboundSeenAdvancements { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let action = Action::azalea_read(buf)?; let tab = if action == Action::OpenedTab { @@ -28,9 +28,6 @@ impl AzaleaRead for ServerboundSeenAdvancements { }; Ok(Self { action, tab }) } -} - -impl AzaleaWrite for ServerboundSeenAdvancements { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { self.action.azalea_write(buf)?; if let Some(tab) = &self.tab { diff --git a/azalea-protocol/src/packets/game/s_set_command_block.rs b/azalea-protocol/src/packets/game/s_set_command_block.rs index 17701171..771e8476 100644 --- a/azalea-protocol/src/packets/game/s_set_command_block.rs +++ b/azalea-protocol/src/packets/game/s_set_command_block.rs @@ -1,11 +1,9 @@ use std::io::{self, Cursor, Write}; -use azalea_buf::{AzBuf, AzaleaRead, BufReadError}; +use azalea_buf::{AzBuf, BufReadError}; use azalea_core::{bitset::FixedBitSet, position::BlockPos}; use azalea_protocol_macros::ServerboundGamePacket; -use crate::packets::AzaleaWrite; - #[derive(Clone, Debug, PartialEq, ServerboundGamePacket)] pub struct ServerboundSetCommandBlock { pub pos: BlockPos, @@ -24,7 +22,7 @@ pub enum Mode { Redstone = 2, } -impl AzaleaRead for ServerboundSetCommandBlock { +impl AzBuf for ServerboundSetCommandBlock { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let pos = BlockPos::azalea_read(buf)?; let command = String::azalea_read(buf)?; @@ -40,9 +38,6 @@ impl AzaleaRead for ServerboundSetCommandBlock { automatic: set.index(2), }) } -} - -impl AzaleaWrite for ServerboundSetCommandBlock { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { self.pos.azalea_write(buf)?; self.command.azalea_write(buf)?; diff --git a/azalea-protocol/src/packets/game/s_set_jigsaw_block.rs b/azalea-protocol/src/packets/game/s_set_jigsaw_block.rs index a19b8a82..9bd15ceb 100644 --- a/azalea-protocol/src/packets/game/s_set_jigsaw_block.rs +++ b/azalea-protocol/src/packets/game/s_set_jigsaw_block.rs @@ -3,13 +3,11 @@ use std::{ io::{Cursor, Write}, }; -use azalea_buf::{AzBuf, AzaleaRead}; +use azalea_buf::{AzBuf, BufReadError}; use azalea_core::position::BlockPos; use azalea_protocol_macros::ServerboundGamePacket; use azalea_registry::identifier::Identifier; -use crate::packets::{AzaleaWrite, BufReadError}; - #[derive(AzBuf, Clone, Debug, PartialEq, ServerboundGamePacket)] pub struct ServerboundSetJigsawBlock { pub pos: BlockPos, @@ -29,7 +27,7 @@ pub enum JointType { Aligned, } -impl AzaleaRead for JointType { +impl AzBuf for JointType { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let name = String::azalea_read(buf)?; match name.as_str() { @@ -38,9 +36,6 @@ impl AzaleaRead for JointType { _ => Err(BufReadError::UnexpectedStringEnumVariant { id: name }), } } -} - -impl AzaleaWrite for JointType { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { match self { JointType::Rollable => "rollable".to_owned().azalea_write(buf)?, diff --git a/azalea-protocol/src/packets/game/s_set_structure_block.rs b/azalea-protocol/src/packets/game/s_set_structure_block.rs index c4387b0f..d16e520c 100644 --- a/azalea-protocol/src/packets/game/s_set_structure_block.rs +++ b/azalea-protocol/src/packets/game/s_set_structure_block.rs @@ -1,6 +1,6 @@ use std::io::{self, Cursor, Write}; -use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite}; +use azalea_buf::AzBuf; use azalea_core::{bitset::FixedBitSet, position::BlockPos}; use azalea_protocol_macros::ServerboundGamePacket; @@ -70,7 +70,7 @@ pub struct Flags { pub show_bounding_box: bool, } -impl AzaleaRead for Flags { +impl AzBuf for Flags { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let set = FixedBitSet::<3>::azalea_read(buf)?; Ok(Self { @@ -79,9 +79,6 @@ impl AzaleaRead for Flags { show_bounding_box: set.index(2), }) } -} - -impl AzaleaWrite for Flags { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { let mut set = FixedBitSet::<3>::new(); if self.ignore_entities { diff --git a/azalea-protocol/src/packets/game/s_use_item_on.rs b/azalea-protocol/src/packets/game/s_use_item_on.rs index 22d3c861..cf1866a5 100644 --- a/azalea-protocol/src/packets/game/s_use_item_on.rs +++ b/azalea-protocol/src/packets/game/s_use_item_on.rs @@ -1,10 +1,10 @@ use std::io::{self, Cursor, Write}; -use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite, BufReadError}; +use azalea_buf::{AzBuf, BufReadError}; use azalea_core::{ direction::Direction, hit_result::BlockHitResult, - position::{BlockPos, Vec3}, + position::{BlockPos, Vec3, Vec3f32}, }; use azalea_protocol_macros::ServerboundGamePacket; @@ -35,49 +35,38 @@ pub struct BlockHit { pub world_border: bool, } -impl AzaleaWrite for BlockHit { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - self.block_pos.azalea_write(buf)?; - self.direction.azalea_write(buf)?; - f32::azalea_write( - &((self.location.x - f64::from(self.block_pos.x)) as f32), - buf, - )?; - f32::azalea_write( - &((self.location.y - f64::from(self.block_pos.y)) as f32), - buf, - )?; - f32::azalea_write( - &((self.location.z - f64::from(self.block_pos.z)) as f32), - buf, - )?; - self.inside.azalea_write(buf)?; - self.world_border.azalea_write(buf)?; - Ok(()) - } -} - -impl AzaleaRead for BlockHit { +impl AzBuf for BlockHit { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let block_pos = BlockPos::azalea_read(buf)?; let direction = Direction::azalea_read(buf)?; - let cursor_x = f32::azalea_read(buf)?; - let cursor_y = f32::azalea_read(buf)?; - let cursor_z = f32::azalea_read(buf)?; + let cursor = Vec3f32::azalea_read(buf)?; let inside = bool::azalea_read(buf)?; let world_border = bool::azalea_read(buf)?; Ok(Self { block_pos, direction, location: Vec3 { - x: f64::from(block_pos.x) + f64::from(cursor_x), - y: f64::from(block_pos.y) + f64::from(cursor_y), - z: f64::from(block_pos.z) + f64::from(cursor_z), + x: f64::from(block_pos.x) + f64::from(cursor.x), + y: f64::from(block_pos.y) + f64::from(cursor.y), + z: f64::from(block_pos.z) + f64::from(cursor.z), }, inside, world_border, }) } + fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { + self.block_pos.azalea_write(buf)?; + self.direction.azalea_write(buf)?; + let cursor = Vec3 { + x: self.location.x - f64::from(self.block_pos.x), + y: self.location.y - f64::from(self.block_pos.y), + z: self.location.z - f64::from(self.block_pos.z), + }; + Vec3f32::from(cursor).azalea_write(buf)?; + self.inside.azalea_write(buf)?; + self.world_border.azalea_write(buf)?; + Ok(()) + } } impl From<&BlockHitResult> for BlockHit { diff --git a/azalea-protocol/src/packets/login/c_login_disconnect.rs b/azalea-protocol/src/packets/login/c_login_disconnect.rs index 950d5e5c..e6e6b33a 100644 --- a/azalea-protocol/src/packets/login/c_login_disconnect.rs +++ b/azalea-protocol/src/packets/login/c_login_disconnect.rs @@ -1,6 +1,6 @@ use std::io::{self, Cursor, Write}; -use azalea_buf::{AzaleaRead, AzaleaWrite, BufReadError}; +use azalea_buf::{AzBuf, BufReadError}; use azalea_chat::FormattedText; use azalea_protocol_macros::ClientboundLoginPacket; use serde::{Deserialize, Serialize}; @@ -11,7 +11,7 @@ pub struct ClientboundLoginDisconnect { pub reason: FormattedText, } -impl AzaleaRead for ClientboundLoginDisconnect { +impl AzBuf for ClientboundLoginDisconnect { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<ClientboundLoginDisconnect, BufReadError> { let disconnect_string = String::azalea_read(buf)?; trace!("Got disconnect packet with string: {disconnect_string:?}"); @@ -29,9 +29,6 @@ impl AzaleaRead for ClientboundLoginDisconnect { reason: FormattedText::deserialize(disconnect_json)?, }) } -} - -impl AzaleaWrite for ClientboundLoginDisconnect { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { let status_string = FormattedText::serialize(&self.reason, serde_json::value::Serializer) .unwrap() diff --git a/azalea-protocol/src/packets/login/s_hello.rs b/azalea-protocol/src/packets/login/s_hello.rs index a7a9f4ee..075cd99c 100644 --- a/azalea-protocol/src/packets/login/s_hello.rs +++ b/azalea-protocol/src/packets/login/s_hello.rs @@ -13,7 +13,7 @@ pub struct ServerboundHello { mod tests { use std::io::Cursor; - use azalea_buf::{AzaleaRead, AzaleaWrite}; + use azalea_buf::AzBuf; use super::*; diff --git a/azalea-protocol/src/packets/mod.rs b/azalea-protocol/src/packets/mod.rs index 9dd14311..202bc4ee 100644 --- a/azalea-protocol/src/packets/mod.rs +++ b/azalea-protocol/src/packets/mod.rs @@ -7,7 +7,7 @@ pub mod status; use std::io::{self, Cursor, Write}; -use azalea_buf::{AzaleaReadVar, AzaleaWrite, AzaleaWriteVar, BufReadError}; +use azalea_buf::{AzBuf, AzBufVar, BufReadError}; use crate::read::ReadPacketError; @@ -89,15 +89,12 @@ impl From<ClientIntention> for ConnectionProtocol { } } -impl azalea_buf::AzaleaRead for ClientIntention { +impl AzBuf for ClientIntention { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let id = i32::azalea_read_var(buf)?; id.try_into() .map_err(|_| BufReadError::UnexpectedEnumVariant { id }) } -} - -impl AzaleaWrite for ClientIntention { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { (*self as i32).azalea_write_var(buf) } diff --git a/azalea-protocol/src/packets/status/c_status_response.rs b/azalea-protocol/src/packets/status/c_status_response.rs index 933b6c2c..ef283643 100644 --- a/azalea-protocol/src/packets/status/c_status_response.rs +++ b/azalea-protocol/src/packets/status/c_status_response.rs @@ -1,6 +1,6 @@ use std::io::{self, Cursor, Write}; -use azalea_buf::{AzaleaRead, AzaleaWrite, BufReadError}; +use azalea_buf::{AzBuf, BufReadError}; use azalea_chat::FormattedText; use azalea_protocol_macros::ClientboundStatusPacket; use serde::{Deserialize, Serialize}; @@ -41,16 +41,13 @@ pub struct ClientboundStatusResponse { pub enforces_secure_chat: Option<bool>, } -impl AzaleaRead for ClientboundStatusResponse { +impl AzBuf for ClientboundStatusResponse { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<ClientboundStatusResponse, BufReadError> { let status_string = String::azalea_read(buf)?; let status_json: serde_json::Value = serde_json::from_str(status_string.as_str())?; Ok(ClientboundStatusResponse::deserialize(status_json)?) } -} - -impl AzaleaWrite for ClientboundStatusResponse { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { let status_string = ClientboundStatusResponse::serialize(self, Serializer) .unwrap() diff --git a/azalea-protocol/src/read.rs b/azalea-protocol/src/read.rs index 5ec7f3b9..9fbb7d61 100644 --- a/azalea-protocol/src/read.rs +++ b/azalea-protocol/src/read.rs @@ -9,7 +9,7 @@ use std::{ sync::LazyLock, }; -use azalea_buf::{AzaleaReadVar, BufReadError}; +use azalea_buf::{AzBufVar, BufReadError}; use azalea_crypto::Aes128CfbDec; use flate2::read::ZlibDecoder; use futures::StreamExt; @@ -406,7 +406,7 @@ where mod tests { use std::io::Cursor; - use azalea_buf::AzaleaRead as _; + use azalea_buf::AzBuf as _; use crate::{packets::game::ClientboundGamePacket, read::deserialize_packet}; diff --git a/azalea-protocol/src/write.rs b/azalea-protocol/src/write.rs index a14463eb..aaa74bd8 100644 --- a/azalea-protocol/src/write.rs +++ b/azalea-protocol/src/write.rs @@ -5,7 +5,7 @@ use std::{ io::{self, Read}, }; -use azalea_buf::AzaleaWriteVar; +use azalea_buf::AzBufVar; use azalea_crypto::Aes128CfbEnc; use flate2::{Compression, bufread::ZlibEncoder}; use thiserror::Error; diff --git a/azalea-registry/src/identifier.rs b/azalea-registry/src/identifier.rs index 4f906181..c7266bf4 100644 --- a/azalea-registry/src/identifier.rs +++ b/azalea-registry/src/identifier.rs @@ -8,7 +8,7 @@ use std::{ str::FromStr, }; -use azalea_buf::{AzaleaRead, AzaleaWrite, BufReadError}; +use azalea_buf::{AzBuf, BufReadError}; #[cfg(feature = "serde")] use serde::{Deserialize, Deserializer, Serialize, Serializer, de}; use simdnbt::{FromNbtTag, ToNbtTag, owned::NbtTag}; @@ -106,13 +106,11 @@ impl From<&str> for Identifier { } } -impl AzaleaRead for Identifier { +impl AzBuf for Identifier { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let location_string = String::azalea_read(buf)?; Ok(Identifier::new(&location_string)) } -} -impl AzaleaWrite for Identifier { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { self.to_string().azalea_write(buf) } diff --git a/azalea-registry/src/lib.rs b/azalea-registry/src/lib.rs index fa197412..fe6b85b3 100644 --- a/azalea-registry/src/lib.rs +++ b/azalea-registry/src/lib.rs @@ -16,7 +16,7 @@ use std::{ io::{self, Cursor, Write}, }; -use azalea_buf::{AzaleaRead, AzaleaReadVar, AzaleaWrite, AzaleaWriteVar, BufReadError}; +use azalea_buf::{AzBuf, AzBufVar, BufReadError}; #[cfg(feature = "serde")] use serde::Serialize; use simdnbt::{FromNbtTag, borrow::NbtTag}; @@ -55,7 +55,7 @@ pub type Block = builtin::BlockKind; #[deprecated = "renamed to `azalea_registry::data::DimensionKind`"] pub type DimensionType = data::DimensionKind; -pub trait Registry: AzaleaRead + AzaleaWrite + PartialEq + PartialOrd + Ord + Copy + Hash +pub trait Registry: AzBuf + PartialEq + PartialOrd + Ord + Copy + Hash where Self: Sized, { @@ -69,7 +69,7 @@ where #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct OptionalRegistry<T: Registry>(pub Option<T>); -impl<T: Registry> AzaleaRead for OptionalRegistry<T> { +impl<T: Registry> AzBuf for OptionalRegistry<T> { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { Ok(OptionalRegistry(match u32::azalea_read_var(buf)? { 0 => None, @@ -79,8 +79,6 @@ impl<T: Registry> AzaleaRead for OptionalRegistry<T> { ), })) } -} -impl<T: Registry> AzaleaWrite for OptionalRegistry<T> { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { match &self.0 { None => 0u32.azalea_write_var(buf), @@ -91,12 +89,12 @@ impl<T: Registry> AzaleaWrite for OptionalRegistry<T> { /// A registry that will either take an ID or a resource location. #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub enum CustomRegistry<D: Registry, C: AzaleaRead + AzaleaWrite> { +pub enum CustomRegistry<D: Registry, C: AzBuf> { Direct(D), Custom(C), } -impl<D: Registry, C: AzaleaRead + AzaleaWrite> AzaleaRead for CustomRegistry<D, C> { +impl<D: Registry, C: AzBuf> AzBuf for CustomRegistry<D, C> { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let direct_registry = OptionalRegistry::<D>::azalea_read(buf)?; if let Some(direct_registry) = direct_registry.0 { @@ -104,8 +102,6 @@ impl<D: Registry, C: AzaleaRead + AzaleaWrite> AzaleaRead for CustomRegistry<D, } Ok(CustomRegistry::Custom(C::azalea_read(buf)?)) } -} -impl<D: Registry, C: AzaleaRead + AzaleaWrite> AzaleaWrite for CustomRegistry<D, C> { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { match self { CustomRegistry::Direct(direct_registry) => { @@ -122,7 +118,7 @@ impl<D: Registry, C: AzaleaRead + AzaleaWrite> AzaleaWrite for CustomRegistry<D, } #[derive(Clone, PartialEq)] -pub enum HolderSet<D: Registry, Identifier: AzaleaRead + AzaleaWrite> { +pub enum HolderSet<D: Registry, Identifier: AzBuf> { Direct { contents: Vec<D>, }, @@ -131,7 +127,7 @@ pub enum HolderSet<D: Registry, Identifier: AzaleaRead + AzaleaWrite> { contents: Vec<Identifier>, }, } -impl<D: Registry, Identifier: AzaleaRead + AzaleaWrite> AzaleaRead for HolderSet<D, Identifier> { +impl<D: Registry, Identifier: AzBuf> AzBuf for HolderSet<D, Identifier> { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let size = i32::azalea_read_var(buf)?.wrapping_sub(1); if size == -1 { @@ -148,8 +144,6 @@ impl<D: Registry, Identifier: AzaleaRead + AzaleaWrite> AzaleaRead for HolderSet Ok(Self::Direct { contents }) } } -} -impl<D: Registry, Identifier: AzaleaRead + AzaleaWrite> AzaleaWrite for HolderSet<D, Identifier> { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { match self { Self::Direct { contents } => { @@ -166,9 +160,7 @@ impl<D: Registry, Identifier: AzaleaRead + AzaleaWrite> AzaleaWrite for HolderSe Ok(()) } } -impl<D: Registry + Debug, Identifier: AzaleaRead + AzaleaWrite + Debug> Debug - for HolderSet<D, Identifier> -{ +impl<D: Registry + Debug, Identifier: AzBuf + Debug> Debug for HolderSet<D, Identifier> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Direct { contents } => f.debug_list().entries(contents).finish(), @@ -180,13 +172,13 @@ impl<D: Registry + Debug, Identifier: AzaleaRead + AzaleaWrite + Debug> Debug } } } -impl<D: Registry, Identifier: AzaleaRead + AzaleaWrite> From<Vec<D>> for HolderSet<D, Identifier> { +impl<D: Registry, Identifier: AzBuf> From<Vec<D>> for HolderSet<D, Identifier> { fn from(contents: Vec<D>) -> Self { Self::Direct { contents } } } #[cfg(feature = "serde")] -impl<D: Registry + Serialize, Identifier: AzaleaRead + AzaleaWrite + Serialize> Serialize +impl<D: Registry + Serialize, Identifier: AzBuf + Serialize> Serialize for HolderSet<D, Identifier> { fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> @@ -205,7 +197,7 @@ impl<D: Registry + Serialize, Identifier: AzaleaRead + AzaleaWrite + Serialize> } } } -impl<D: Registry, Identifier: AzaleaRead + AzaleaWrite> Default for HolderSet<D, Identifier> { +impl<D: Registry, Identifier: AzBuf> Default for HolderSet<D, Identifier> { fn default() -> Self { Self::Direct { contents: Vec::new(), @@ -215,11 +207,11 @@ impl<D: Registry, Identifier: AzaleaRead + AzaleaWrite> Default for HolderSet<D, /// A reference to either a registry or a custom value (usually something with /// an `Identifier`). -pub enum Holder<R: Registry, Direct: AzaleaRead + AzaleaWrite> { +pub enum Holder<R: Registry, Direct: AzBuf> { Reference(R), Direct(Direct), } -impl<R: Registry, Direct: AzaleaRead + AzaleaWrite> AzaleaRead for Holder<R, Direct> { +impl<R: Registry, Direct: AzBuf> AzBuf for Holder<R, Direct> { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let id = u32::azalea_read_var(buf)?; if id == 0 { @@ -232,8 +224,6 @@ impl<R: Registry, Direct: AzaleaRead + AzaleaWrite> AzaleaRead for Holder<R, Dir Ok(Self::Reference(value)) } } -} -impl<R: Registry, Direct: AzaleaRead + AzaleaWrite> AzaleaWrite for Holder<R, Direct> { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { match self { Self::Reference(value) => (value.to_u32() + 1).azalea_write_var(buf), @@ -244,7 +234,7 @@ impl<R: Registry, Direct: AzaleaRead + AzaleaWrite> AzaleaWrite for Holder<R, Di } } } -impl<R: Registry + Debug, Direct: AzaleaRead + AzaleaWrite + Debug> Debug for Holder<R, Direct> { +impl<R: Registry + Debug, Direct: AzBuf + Debug> Debug for Holder<R, Direct> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Reference(value) => f.debug_tuple("Reference").field(value).finish(), @@ -252,7 +242,7 @@ impl<R: Registry + Debug, Direct: AzaleaRead + AzaleaWrite + Debug> Debug for Ho } } } -impl<R: Registry + Clone, Direct: AzaleaRead + AzaleaWrite + Clone> Clone for Holder<R, Direct> { +impl<R: Registry + Clone, Direct: AzBuf + Clone> Clone for Holder<R, Direct> { fn clone(&self) -> Self { match self { Self::Reference(value) => Self::Reference(*value), @@ -260,9 +250,7 @@ impl<R: Registry + Clone, Direct: AzaleaRead + AzaleaWrite + Clone> Clone for Ho } } } -impl<R: Registry + PartialEq, Direct: AzaleaRead + AzaleaWrite + PartialEq> PartialEq - for Holder<R, Direct> -{ +impl<R: Registry + PartialEq, Direct: AzBuf + PartialEq> PartialEq for Holder<R, Direct> { fn eq(&self, other: &Self) -> bool { match (self, other) { (Self::Reference(a), Self::Reference(b)) => a == b, @@ -271,15 +259,13 @@ impl<R: Registry + PartialEq, Direct: AzaleaRead + AzaleaWrite + PartialEq> Part } } } -impl<R: Registry + Default, Direct: AzaleaRead + AzaleaWrite> Default for Holder<R, Direct> { +impl<R: Registry + Default, Direct: AzBuf> Default for Holder<R, Direct> { fn default() -> Self { Self::Reference(R::default()) } } #[cfg(feature = "serde")] -impl<R: Registry + Serialize, Direct: AzaleaRead + AzaleaWrite + Serialize> Serialize - for Holder<R, Direct> -{ +impl<R: Registry + Serialize, Direct: AzBuf + Serialize> Serialize for Holder<R, Direct> { fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer, @@ -291,9 +277,7 @@ impl<R: Registry + Serialize, Direct: AzaleaRead + AzaleaWrite + Serialize> Seri } } -impl<R: Registry + FromNbtTag, Direct: AzaleaRead + AzaleaWrite + FromNbtTag> FromNbtTag - for Holder<R, Direct> -{ +impl<R: Registry + FromNbtTag, Direct: AzBuf + FromNbtTag> FromNbtTag for Holder<R, Direct> { fn from_nbt_tag(tag: NbtTag) -> Option<Self> { if let Some(reference) = R::from_nbt_tag(tag) { return Some(Self::Reference(reference)); @@ -307,9 +291,7 @@ impl<R: Registry + FromNbtTag, Direct: AzaleaRead + AzaleaWrite + FromNbtTag> Fr /// /// These can be resolved into their actual values with /// `ResolvableDataRegistry` from azalea-core. -pub trait DataRegistry: - AzaleaRead + AzaleaWrite + PartialEq + PartialOrd + Ord + Copy + Hash -{ +pub trait DataRegistry: AzBuf + PartialEq + PartialOrd + Ord + Copy + Hash { const NAME: &'static str; type Key: DataRegistryKey; diff --git a/azalea-world/src/chunk_storage.rs b/azalea-world/src/chunk_storage.rs index 3f8c4e2d..0ad96c81 100644 --- a/azalea-world/src/chunk_storage.rs +++ b/azalea-world/src/chunk_storage.rs @@ -11,7 +11,7 @@ use azalea_block::{ block_state::{BlockState, BlockStateIntegerRepr}, fluid_state::FluidState, }; -use azalea_buf::{AzaleaRead, AzaleaWrite, BufReadError}; +use azalea_buf::{AzBuf, BufReadError}; use azalea_core::{ heightmap_kind::HeightmapKind, position::{ @@ -461,14 +461,14 @@ pub fn get_block_state_from_sections( Some(section.get_block_state(chunk_section_pos)) } -impl AzaleaWrite for Chunk { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { - for section in &self.sections { - section.azalea_write(buf)?; - } - Ok(()) - } -} +// impl AzBuf for Chunk { +// fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { +// for section in &self.sections { +// section.azalea_write(buf)?; +// } +// Ok(()) +// } +// } impl Debug for PartialChunkStorage { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -482,7 +482,7 @@ impl Debug for PartialChunkStorage { } } -impl AzaleaRead for Section { +impl AzBuf for Section { fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let block_count = u16::azalea_read(buf)?; @@ -511,13 +511,10 @@ impl AzaleaRead for Section { biomes, }) } -} - -impl AzaleaWrite for Section { fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { self.block_count.azalea_write(buf)?; - self.states.azalea_write(buf)?; - self.biomes.azalea_write(buf)?; + self.states.write(buf)?; + self.biomes.write(buf)?; Ok(()) } } diff --git a/azalea-world/src/palette/container.rs b/azalea-world/src/palette/container.rs index a6c7454b..4e4e5595 100644 --- a/azalea-world/src/palette/container.rs +++ b/azalea-world/src/palette/container.rs @@ -4,7 +4,7 @@ use std::{ }; use azalea_block::BlockState; -use azalea_buf::{AzaleaRead, AzaleaWrite, BufReadError}; +use azalea_buf::{AzBuf, BufReadError}; use azalea_core::position::{ChunkSectionBiomePos, ChunkSectionBlockPos}; use azalea_registry::data::Biome; use tracing::{debug, warn}; @@ -291,10 +291,10 @@ impl<S: PalletedContainerKind> PalettedContainer<S> { } } -impl<S: PalletedContainerKind> AzaleaWrite for PalettedContainer<S> { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { +impl<S: PalletedContainerKind> PalettedContainer<S> { + pub fn write(&self, buf: &mut impl Write) -> io::Result<()> { self.bits_per_entry.azalea_write(buf)?; - self.palette.azalea_write(buf)?; + self.palette.write(buf)?; self.storage.data.azalea_write(buf)?; Ok(()) } diff --git a/azalea-world/src/palette/mod.rs b/azalea-world/src/palette/mod.rs index 4cbf690b..11b38f45 100644 --- a/azalea-world/src/palette/mod.rs +++ b/azalea-world/src/palette/mod.rs @@ -8,7 +8,7 @@ use std::{ io::{self, Cursor, Write}, }; -use azalea_buf::{AzaleaReadVar, AzaleaWrite, AzaleaWriteVar, BufReadError}; +use azalea_buf::{AzBufVar, BufReadError}; pub use container::*; /// A representation of the different types of chunk palettes Minecraft uses. @@ -34,8 +34,8 @@ impl<S: PalletedContainerKind> Palette<S> { } } -impl<S: PalletedContainerKind> AzaleaWrite for Palette<S> { - fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> { +impl<S: PalletedContainerKind> Palette<S> { + pub fn write(&self, buf: &mut impl Write) -> io::Result<()> { match self { Palette::SingleValue(value) => { (*value).into().azalea_write_var(buf)?; diff --git a/codegen/README.md b/codegen/README.md index 6ff95348..3e259349 100644 --- a/codegen/README.md +++ b/codegen/README.md @@ -30,7 +30,7 @@ First, run `python migrate.py [new version]`. This will run a script that automa If you're lucky, that's all you're going to have to do. Look at the diff (`git diff`) and type-check the code (`cargo check`) to make sure everything is right. In the diff, specifically look for new comments that have "TODO". -If a packet is incorrect, you'll want to find it in the Minecraft source. The name of the struct should be the same or similar as the class in the vanilla source. Now, you'll have to manually write the struct for the packet. If the packet existed in the version before and it's just being updated, you can compare against that to see what was updated. Note that if a packet is particularly complicated, you may have to implement AzaleaRead and AzaleaWrite, but most of the time the `#[derive(AzBuf)]` macro will be able to generate the impls correctly. Look at other existing packets as reference if you're confused. +If a packet is incorrect, you'll want to find it in the Minecraft source. The name of the struct should be the same or similar as the class in the vanilla source. Now, you'll have to manually write the struct for the packet. If the packet existed in the version before and it's just being updated, you can compare against that to see what was updated. Note that if a packet is particularly complicated, you may have to implement `AzBuf`, but most of the time the `#[derive(AzBuf)]` macro will be able to generate the impls correctly. Look at other existing packets as reference if you're confused. Finally, test by making a bot join a world. Specifically, you'll want to test the things that were updated in the version. Setting the RUST_LOG environment variable to `debug` or `trace` may help you find the source of crashes (trace shows the first few hundred bytes for every packet received so it's typically more useful, but it may log more than you want). |
