From e5bd06efdf14f80111ec0e01e6a40bdf7d76a23a Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Fri, 1 May 2026 12:04:13 +0900 Subject: [PATCH 01/67] packet accept_teleportation --- haya_protocol/src/serverbound.rs | 77 ++++++++++++++++++++++++++- haya_protocol/src/serverbound/game.rs | 5 ++ 2 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 haya_protocol/src/serverbound/game.rs diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index e10ee3bb..fa65bddd 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -1,10 +1,12 @@ use minecraft_data::{ - serverbound__configuration, serverbound__handshake, serverbound__login, serverbound__status, + serverbound__configuration, serverbound__handshake, serverbound__login, serverbound__play, + serverbound__status, }; pub mod common; pub mod configuration; pub mod cookie; +pub mod game; pub mod handshake; pub mod login; pub mod ping; @@ -37,6 +39,8 @@ macro_rules! packets { self.$variant(e); } )+ + #[allow(unreachable_patterns)] + _ => todo!(), } Ok(()) } @@ -84,3 +88,74 @@ packets! { custom_click_action = common::CustomClickAction<'_>, accept_code_of_conduct = configuration::AcceptCodeOfConduct, } +packets! { + serverbound__play, + GameHandler, + handle, + accept_teleportation = game::AcceptTeleportation, + // block_entity_tag_query, + // bundle_item_selected, + // change_difficulty, + // change_game_mode, + // chat_ack, + // chat_command, + // chat_command_signed, + // chat, + // chat_session_update, + // chunk_batch_received, + // client_command, + // client_tick_end, + // client_information, + // command_suggestion, + // configuration_acknowledged, + // container_button_click, + // container_click, + // container_close, + // container_slot_state_changed, + // cookie_response, + // custom_payload, + // debug_subscription_request, + // edit_book, + // entity_tag_query, + // interact, + // jigsaw_generate, + // keep_alive, + // lock_difficulty, + // move_player_pos, + // move_player_pos_rot, + // move_player_rot, + // move_player_status_only, + // move_vehicle, + // paddle_boat, + // pick_item_from_block, + // pick_item_from_entity, + // ping_request, + // place_recipe, + // player_abilities, + // player_action, + // player_command, + // player_input, + // player_loaded, + // pong, + // recipe_book_change_settings, + // recipe_book_seen_recipe, + // rename_item, + // resource_pack, + // seen_advancements, + // select_trade, + // set_beacon, + // set_carried_item, + // set_command_block, + // set_command_minecart, + // set_creative_mode_slot, + // set_jigsaw_block, + // set_structure_block, + // set_test_block, + // sign_update, + // swing, + // teleport_to_entity, + // test_instance_block_action, + // use_item_on, + // use_item, + // custom_click_action, +} diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs new file mode 100644 index 00000000..6c40bd0c --- /dev/null +++ b/haya_protocol/src/serverbound/game.rs @@ -0,0 +1,5 @@ +#[derive(Clone, Serialize, Deserialize)] +pub struct AcceptTeleportation { + #[mser(varint)] + id: u32, +} From 696199ffa94f5e30a67ec86872307cf227421a4b Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Fri, 1 May 2026 16:50:47 +0900 Subject: [PATCH 02/67] packet block_entity_tag_query --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index fa65bddd..3e7de71d 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -93,7 +93,7 @@ packets! { GameHandler, handle, accept_teleportation = game::AcceptTeleportation, - // block_entity_tag_query, + block_entity_tag_query = game::BlockEntityTagQuery, // bundle_item_selected, // change_difficulty, // change_game_mode, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 6c40bd0c..1d6f145c 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -1,5 +1,14 @@ +use haya_math::BlockPosPacked; + #[derive(Clone, Serialize, Deserialize)] pub struct AcceptTeleportation { #[mser(varint)] id: u32, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct BlockEntityTagQuery { + #[mser(varint)] + pub transaction_id: u32, + pub pos: BlockPosPacked, +} From a0ec286bd8d1fb405a607013e654486d3fbcfeb0 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sat, 2 May 2026 00:36:38 +0900 Subject: [PATCH 03/67] packet bundle_item_selected --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 13 +++++ haya_ser_macro/src/deserialize.rs | 69 +++++++++++++++++++-------- haya_ser_macro/src/lib.rs | 15 ++++-- 4 files changed, 72 insertions(+), 27 deletions(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 3e7de71d..3ef4bb9b 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -94,7 +94,7 @@ packets! { handle, accept_teleportation = game::AcceptTeleportation, block_entity_tag_query = game::BlockEntityTagQuery, - // bundle_item_selected, + bundle_item_selected = game::BundleItemSelected, // change_difficulty, // change_game_mode, // chat_ack, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 1d6f145c..7c425dee 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -12,3 +12,16 @@ pub struct BlockEntityTagQuery { pub transaction_id: u32, pub pos: BlockPosPacked, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct BundleItemSelected { + #[mser(varint)] + pub slot_id: u32, + #[mser(varint, filter = valicate_bundle_item_selected)] + pub selected_item_index: u32, +} + +fn valicate_bundle_item_selected(x: &u32) -> bool { + let x = *x as i32; + x >= 0 || x == -1 +} diff --git a/haya_ser_macro/src/deserialize.rs b/haya_ser_macro/src/deserialize.rs index 53ef974c..c0d242a3 100644 --- a/haya_ser_macro/src/deserialize.rs +++ b/haya_ser_macro/src/deserialize.rs @@ -6,6 +6,7 @@ use quote::{ToTokens, TokenStreamExt, quote}; pub fn deserialize_struct( input: syn::DeriveInput, cratename: syn::Path, + attrs: Attrs, ) -> syn::Result { let name = &input.ident; let generics = &input.generics; @@ -26,14 +27,27 @@ pub fn deserialize_struct( let read = fields .iter() .map(|(field, attrs, m)| read_field(&cratename, field, attrs, m)); + let read = quote!(Self { + #(#read,)* + }); + let read = if let Some(filter) = attrs.filter { + quote! { + let __v = #read; + if #filter(&__v) { + ::core::result::Result::Ok(__v) + } else { + ::core::result::Result::Err(::#cratename::Error) + } + } + } else { + quote!(::core::result::Result::Ok(#read)) + }; Ok(quote! { #[automatically_derived] impl <'__a #impl_generics ::#cratename::Read<'__a> for #name #tok { #[inline] fn read(__r: &mut ::#cratename::Reader<'__a>) -> ::core::result::Result { - ::core::result::Result::Ok(Self { - #(#read,)* - }) + #read } } }) @@ -98,9 +112,9 @@ pub fn deserialize_enum( } read = Some(quote! { - ::core::result::Result::Ok(match <#header as ::#cratename::Read>::read(__r)? { + match <#header as ::#cratename::Read>::read(__r)? { #(#match_arms,)* - }) + } }); } @@ -113,6 +127,19 @@ pub fn deserialize_enum( )); } }; + let read = if let Some(filter) = attrs.filter { + quote! { + let __v = #read; + if #filter(&__v) { + ::core::result::Result::Ok(__v) + } else { + ::core::result::Result::Err(::#cratename::Error) + } + } + } else { + quote!(::core::result::Result::Ok(#read)) + }; + let generics = &input.generics; let has_lifetimes = generics.lifetimes().next().is_some(); @@ -173,41 +200,41 @@ fn repr_enum( lit: syn::LitInt, ) -> TokenStream { if !varint { - quote! { + quote! {{ let __x = <#path as ::#cratename::Read>::read(__r)?; if __x < #lit { - unsafe { ::core::result::Result::Ok(::core::mem::transmute::<#path, Self>(__x as #path) ) } + unsafe { ::core::mem::transmute::<#path, Self>(__x as #path) } } else { - unsafe { ::core::result::Result::Ok(::core::mem::transmute::<#path, Self>(0) ) } + unsafe { ::core::mem::transmute::<#path, Self>(0) } } - } + }} } else if path == "u64" { - quote! { + quote! {{ let __x = <::#cratename::V64 as ::#cratename::Read>::read(__r)?.0; if __x < #lit { - unsafe { ::core::result::Result::Ok(::core::mem::transmute::(__x) ) } + unsafe { ::core::mem::transmute::(__x) } } else { - unsafe { ::core::result::Result::Ok(::core::mem::transmute::(0) ) } + unsafe { ::core::mem::transmute::(0) } } - } + }} } else if len > V21MAX { - quote! { + quote! {{ let __x = <::#cratename::V32 as ::#cratename::Read>::read(__r)?.0; if __x < #lit { - unsafe { ::core::result::Result::Ok(::core::mem::transmute::(__x) ) } + unsafe { ::core::mem::transmute::(__x) } } else { - unsafe { ::core::result::Result::Ok(::core::mem::transmute::(0) ) } + unsafe { ::core::mem::transmute::(0) } } - } + }} } else { - quote! { + quote! {{ let __x = <::#cratename::V21 as ::#cratename::Read>::read(__r)?.0; if __x < #lit { - unsafe { ::core::result::Result::Ok(::core::mem::transmute::<#path, Self>(__x as #path) ) } + unsafe { ::core::mem::transmute::<#path, Self>(__x as #path) } } else { - unsafe { ::core::result::Result::Ok(::core::mem::transmute::<#path, Self>(0) ) } + unsafe { ::core::mem::transmute::<#path, Self>(0) } } - } + }} } } diff --git a/haya_ser_macro/src/lib.rs b/haya_ser_macro/src/lib.rs index 6cd77489..1a8cfe97 100644 --- a/haya_ser_macro/src/lib.rs +++ b/haya_ser_macro/src/lib.rs @@ -28,6 +28,7 @@ struct Attrs { varint: bool, header: Option, camel_case: bool, + filter: Option, } impl syn::parse::Parse for Attrs { @@ -45,6 +46,10 @@ impl syn::parse::Parse for Attrs { } else if lookahead.peek(kw::camel_case) { let _: kw::camel_case = input.parse()?; attr.camel_case = true; + } else if lookahead.peek(kw::filter) { + let _: kw::filter = input.parse()?; + let _: syn::Token![=] = input.parse()?; + attr.filter = Some(input.parse::()?); } else { return Err(lookahead.error()); } @@ -100,7 +105,7 @@ pub fn serialize(input: TokenStream) -> TokenStream { #[proc_macro_derive(Deserialize, attributes(mser))] pub fn deserialize(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as syn::DeriveInput); - let (attr, cratename) = match crate_name(&input) { + let (attrs, cratename) = match crate_name(&input) { Ok(cratename) => cratename, Err(err) => { return err.to_compile_error().into(); @@ -108,8 +113,8 @@ pub fn deserialize(input: TokenStream) -> TokenStream { }; let x = match input.data { - syn::Data::Struct(_) => deserialize::deserialize_struct(input, cratename), - syn::Data::Enum(_) => deserialize::deserialize_enum(input, cratename, attr), + syn::Data::Struct(_) => deserialize::deserialize_struct(input, cratename, attrs), + syn::Data::Enum(_) => deserialize::deserialize_enum(input, cratename, attrs), syn::Data::Union(_) => Err(syn::Error::new_spanned(input, "unions are not supported")), }; match x { @@ -119,8 +124,8 @@ pub fn deserialize(input: TokenStream) -> TokenStream { } struct FieldAttrs { - pub filter: Option, - pub varint: bool, + filter: Option, + varint: bool, } impl syn::parse::Parse for FieldAttrs { From 9875f910caebdab98f0cf2e3a50186bf171493b2 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sat, 2 May 2026 11:36:43 +0900 Subject: [PATCH 04/67] packet change_difficulty --- haya_collection/src/lib.rs | 34 ++---------------- haya_protocol/src/chat.rs | 4 +-- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 6 ++++ haya_ser/src/lib.rs | 50 +++++++++++++++++++-------- 5 files changed, 48 insertions(+), 48 deletions(-) diff --git a/haya_collection/src/lib.rs b/haya_collection/src/lib.rs index 9e29e40f..2d9e3f31 100644 --- a/haya_collection/src/lib.rs +++ b/haya_collection/src/lib.rs @@ -4,7 +4,7 @@ extern crate alloc; use alloc::boxed::Box; use alloc::vec::Vec; -use mser::{Error, Read, Reader, V21, Write, Writer}; +use mser::{Error, Read, Reader, V21, Write, Writer, read_v21_len}; pub enum List<'a, T: 'a, const MAX: usize = { usize::MAX }> { Borrowed(&'a [T]), @@ -95,10 +95,7 @@ pub fn capacity_fix(len: usize) -> usize { impl<'a, T: Read<'a>, const MAX: usize> Read<'a> for List<'a, T, MAX> { fn read(buf: &mut Reader<'a>) -> Result { - let len = V21::read(buf)?.0 as usize; - if len > MAX { - return Err(Error); - } + let len = read_v21_len(buf, MAX)?; let mut vec = Vec::with_capacity(capacity_fix(len)); for _ in 0..len { vec.push(T::read(buf)?); @@ -135,10 +132,7 @@ impl<'a, K: Write + 'a, V: Write + 'a, const MAX: usize> Write for Map<'a, K, V, impl<'a, K: Read<'a>, V: Read<'a>, const MAX: usize> Read<'a> for Map<'a, K, V, MAX> { fn read(buf: &mut Reader<'a>) -> Result { - let len = V21::read(buf)?.0 as usize; - if len > MAX { - return Err(Error); - } + let len = read_v21_len(buf, MAX)?; let mut vec = Vec::with_capacity(capacity_fix(len)); for _ in 0..len { let k = K::read(buf)?; @@ -179,25 +173,3 @@ impl<'a, T: Read<'a>> Read<'a> for Cow<'a, T> { Ok(Self::Owned(Box::new(T::read(buf)?))) } } - -#[derive(Debug, Clone, Copy)] -pub struct FixedByteArray<'a, const L: usize>(pub &'a [u8; L]); - -impl<'a, const L: usize> Read<'a> for FixedByteArray<'a, L> { - fn read(buf: &mut Reader<'a>) -> Result { - match buf.read_array() { - Ok(x) => Ok(Self(x)), - Err(e) => Err(e), - } - } -} - -impl<'a, const L: usize> Write for FixedByteArray<'a, L> { - unsafe fn write(&self, w: &mut Writer) { - unsafe { w.write(self.0) } - } - - fn len_s(&self) -> usize { - self.0.len() - } -} diff --git a/haya_protocol/src/chat.rs b/haya_protocol/src/chat.rs index 6e6b7807..7f29b466 100644 --- a/haya_protocol/src/chat.rs +++ b/haya_protocol/src/chat.rs @@ -1,7 +1,7 @@ use crate::registry::ChatTypeRef; use crate::{BitSet, Component, Holder, Style}; -use haya_collection::{FixedByteArray, List}; -use mser::{ByteArray, Read, Utf8, V32, Write}; +use haya_collection::List; +use mser::{ByteArray, FixedByteArray, Read, Utf8, V32, Write}; use uuid::Uuid; #[derive(Clone, Copy, Serialize, Deserialize)] diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 3ef4bb9b..9d886e98 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -95,7 +95,7 @@ packets! { accept_teleportation = game::AcceptTeleportation, block_entity_tag_query = game::BlockEntityTagQuery, bundle_item_selected = game::BundleItemSelected, - // change_difficulty, + change_difficulty = game::ChangeDifficulty, // change_game_mode, // chat_ack, // chat_command, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 7c425dee..1fbc9400 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -1,3 +1,4 @@ +use crate::Difficulty; use haya_math::BlockPosPacked; #[derive(Clone, Serialize, Deserialize)] @@ -25,3 +26,8 @@ fn valicate_bundle_item_selected(x: &u32) -> bool { let x = *x as i32; x >= 0 || x == -1 } + +#[derive(Clone, Serialize, Deserialize)] +pub struct ChangeDifficulty { + pub difficulty: Difficulty, +} diff --git a/haya_ser/src/lib.rs b/haya_ser/src/lib.rs index 05b64763..adf6c3ea 100644 --- a/haya_ser/src/lib.rs +++ b/haya_ser/src/lib.rs @@ -90,10 +90,7 @@ impl<'a, const MAX: usize> Write for ByteArray<'a, MAX> { impl<'a, const MAX: usize> Read<'a> for ByteArray<'a, MAX> { fn read(buf: &mut Reader<'a>) -> Result { - let len = V21::read(buf)?.0 as usize; - if len > MAX { - return Err(Error); - } + let len = read_v21_len(buf, MAX)?; Ok(Self(buf.read_slice(len)?)) } } @@ -101,10 +98,6 @@ impl<'a, const MAX: usize> Read<'a> for ByteArray<'a, MAX> { #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct Utf8<'a, const MAX: usize = 32767>(pub &'a str); -impl<'a, const MAX: usize> Utf8<'a, MAX> { - const MAX_BYTES: usize = MAX.checked_mul(3).unwrap(); -} - impl<'a, const MAX: usize> Write for Utf8<'a, MAX> { #[inline] unsafe fn write(&self, w: &mut Writer) { @@ -123,17 +116,14 @@ impl<'a, const MAX: usize> Write for Utf8<'a, MAX> { impl<'a, const MAX: usize> Read<'a> for Utf8<'a, MAX> { #[inline] fn read(buf: &mut Reader<'a>) -> Result { - let len = V21::read(buf)?.0 as usize; - if len > Self::MAX_BYTES { - return Err(Error); - } + let len = read_v21_len(buf, MAX.saturating_mul(3))?; let bytes = buf.read_slice(len)?; let s = match core::str::from_utf8(bytes) { Ok(x) => x, Err(_) => return Err(Error), }; - if s.chars().map(|x| x.len_utf16()).sum::() <= MAX { - Ok(Utf8(s)) + if s.chars().map(char::len_utf16).sum::() <= MAX { + Ok(Self(s)) } else { Err(Error) } @@ -202,3 +192,35 @@ impl<'a, const MAX: usize> Write for Rest<'a, MAX> { self.0.len() } } + +#[inline(always)] +pub fn read_v21_len(buf: &mut Reader<'_>, max: usize) -> Result { + let len = V21::read(buf)?.0 as usize; + if len > max { + cold_path(); + return Err(Error); + } + Ok(len) +} + +#[derive(Debug, Clone, Copy)] +pub struct FixedByteArray<'a, const L: usize>(pub &'a [u8; L]); + +impl<'a, const L: usize> Read<'a> for FixedByteArray<'a, L> { + fn read(buf: &mut Reader<'a>) -> Result { + match buf.read_array() { + Ok(x) => Ok(Self(x)), + Err(e) => Err(e), + } + } +} + +impl<'a, const L: usize> Write for FixedByteArray<'a, L> { + unsafe fn write(&self, w: &mut Writer) { + unsafe { w.write(self.0) } + } + + fn len_s(&self) -> usize { + self.0.len() + } +} From 807acf706c2525854ec7755366071f0752fc2d32 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sat, 2 May 2026 12:52:18 +0900 Subject: [PATCH 05/67] packet change_game_mode --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 9d886e98..59e112a9 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -96,7 +96,7 @@ packets! { block_entity_tag_query = game::BlockEntityTagQuery, bundle_item_selected = game::BundleItemSelected, change_difficulty = game::ChangeDifficulty, - // change_game_mode, + change_game_mode = game::ChangeGameMode, // chat_ack, // chat_command, // chat_command_signed, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 1fbc9400..e3f16432 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -1,4 +1,4 @@ -use crate::Difficulty; +use crate::{Difficulty, GameType}; use haya_math::BlockPosPacked; #[derive(Clone, Serialize, Deserialize)] @@ -31,3 +31,8 @@ fn valicate_bundle_item_selected(x: &u32) -> bool { pub struct ChangeDifficulty { pub difficulty: Difficulty, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct ChangeGameMode { + pub mode: GameType, +} From 27080d06bbc553fbfa1460f6777fbe3a5009cf80 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sat, 2 May 2026 13:25:19 +0900 Subject: [PATCH 06/67] packet chat_ack --- haya_nbt/src/compound.rs | 47 ++++++++------------------- haya_nbt/src/lib.rs | 5 ++- haya_nbt/src/string.rs | 26 +++++++++------ haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 5 +++ 5 files changed, 39 insertions(+), 46 deletions(-) diff --git a/haya_nbt/src/compound.rs b/haya_nbt/src/compound.rs index 8e8795dc..967cee5d 100644 --- a/haya_nbt/src/compound.rs +++ b/haya_nbt/src/compound.rs @@ -7,42 +7,21 @@ use haya_mutf8::{as_mutf8_ascii, decode_mutf8_len}; use haya_str::HayaStr; use mser::{Error, Read, Reader, Write, Writer}; -enum CowVec { - Thin(HayaStr), - Heap(Vec), -} - impl<'a> Read<'a> for Name { fn read(buf: &mut Reader<'a>) -> Result { let len = u16::read(buf)? as usize; let data = buf.read_slice(len)?; if let Some(x) = as_mutf8_ascii(data) { - Ok(Self::new(x)) + unsafe { Ok(Self::new(x)) } } else { let len = decode_mutf8_len(data)?; - let mut ptr = if len <= haya_str::MAX { - CowVec::Thin(HayaStr::new()) - } else { - CowVec::Heap(Vec::with_capacity(len)) - }; + let mut vec = Vec::with_capacity(len); unsafe { - mser::write_unchecked( - match &mut ptr { - CowVec::Thin(s) => s.as_mut_ptr(), - CowVec::Heap(x) => x.as_mut_ptr(), - }, - &(DecodeMutf8(data, len)), - ); - match ptr { - CowVec::Thin(mut s) => { - s.set_len(len); - Ok(Self::Thin(s)) - } - CowVec::Heap(mut x) => { - x.set_len(len); - Ok(Self::Heap(String::from_utf8_unchecked(x).into_boxed_str())) - } - } + mser::write_unchecked(vec.as_mut_ptr(), &(DecodeMutf8(data, len))); + vec.set_len(len); + Ok(Self(crate::Inner::Heap( + String::from_utf8_unchecked(vec).into_boxed_str(), + ))) } } } @@ -50,9 +29,9 @@ impl<'a> Read<'a> for Name { impl AsRef for Name { fn as_ref(&self) -> &str { - match self { - Self::Thin(x) => x, - Self::Heap(x) => x, + match &self.0 { + crate::Inner::Thin(x) => x, + crate::Inner::Heap(x) => x, } } } @@ -66,10 +45,10 @@ impl core::ops::Deref for Name { } impl Name { - pub fn new(s: &str) -> Self { + pub(crate) unsafe fn new(s: &str) -> Self { match HayaStr::copy_from(s) { - Ok(x) => Self::Thin(x), - Err(_) => Self::Heap(s.to_owned().into_boxed_str()), + Ok(x) => Self(crate::Inner::Thin(x)), + Err(_) => Self(crate::Inner::Heap(s.to_owned().into_boxed_str())), } } } diff --git a/haya_nbt/src/lib.rs b/haya_nbt/src/lib.rs index 9cdd911a..36a52e63 100644 --- a/haya_nbt/src/lib.rs +++ b/haya_nbt/src/lib.rs @@ -53,7 +53,10 @@ pub struct Compound(Vec<(Name, Tag)>); pub struct CompoundStringify(pub Compound); #[derive(Clone, Debug)] -pub enum Name { +pub struct Name(Inner); + +#[derive(Clone, Debug)] +enum Inner { Thin(HayaStr), Heap(Box), } diff --git a/haya_nbt/src/string.rs b/haya_nbt/src/string.rs index 0a3dbe13..6094776f 100644 --- a/haya_nbt/src/string.rs +++ b/haya_nbt/src/string.rs @@ -1,4 +1,4 @@ -use crate::{Error, Name, RawStringTag, Read, RefStringTag, StringTag, Write, Writer}; +use crate::{Error, Inner, Name, RawStringTag, Read, RefStringTag, StringTag, Write, Writer}; use alloc::borrow::ToOwned; use alloc::vec::Vec; use haya_mutf8::{as_mutf8_ascii, decode_mutf8, decode_mutf8_len, encode_mutf8, encode_mutf8_len}; @@ -129,21 +129,27 @@ impl Write for Name { #[inline] unsafe fn write(&self, w: &mut Writer) { unsafe { - if let Some(x) = RawStringTag::new(self.as_bytes()) { - x.write(w); - } else { - (encode_mutf8_len(self) as u16).write(w); - encode_mutf8(self, w); + match &self.0 { + Inner::Thin(direct) => RawStringTag::new_unchecked(direct).write(w), + Inner::Heap(x) => match RawStringTag::new(x.as_bytes()) { + Some(x) => x.write(w), + None => { + (encode_mutf8_len(self) as u16).write(w); + encode_mutf8(self, w); + } + }, } } } #[inline] fn len_s(&self) -> usize { - if let Some(x) = RawStringTag::new(self.as_bytes()) { - x.len_s() - } else { - encode_mutf8_len(self) + 2 + match &self.0 { + Inner::Thin(direct) => RawStringTag::new_unchecked(direct).len_s(), + Inner::Heap(x) => match RawStringTag::new(x.as_bytes()) { + Some(x) => x.len_s(), + None => encode_mutf8_len(self) + 2, + }, } } } diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 59e112a9..5ca2c6e3 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -97,7 +97,7 @@ packets! { bundle_item_selected = game::BundleItemSelected, change_difficulty = game::ChangeDifficulty, change_game_mode = game::ChangeGameMode, - // chat_ack, + chat_ack = game::ChatAck, // chat_command, // chat_command_signed, // chat, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index e3f16432..8c5bab4f 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -36,3 +36,8 @@ pub struct ChangeDifficulty { pub struct ChangeGameMode { pub mode: GameType, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct ChatAck { + pub offset: u32, +} From a41923af60b3beb4ff314a065b30254beb0b8981 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sat, 2 May 2026 13:26:19 +0900 Subject: [PATCH 07/67] packet chat_command --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 5ca2c6e3..6a43f3a6 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -98,7 +98,7 @@ packets! { change_difficulty = game::ChangeDifficulty, change_game_mode = game::ChangeGameMode, chat_ack = game::ChatAck, - // chat_command, + chat_command = game::ChatCommand<'_>, // chat_command_signed, // chat, // chat_session_update, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 8c5bab4f..03d88941 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -1,5 +1,6 @@ use crate::{Difficulty, GameType}; use haya_math::BlockPosPacked; +use mser::Utf8; #[derive(Clone, Serialize, Deserialize)] pub struct AcceptTeleportation { @@ -41,3 +42,8 @@ pub struct ChangeGameMode { pub struct ChatAck { pub offset: u32, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct ChatCommand<'a> { + pub command: Utf8<'a>, +} From 714839123f3ba3db1637f209e1223700c3b7e2df Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sat, 2 May 2026 14:50:36 +0900 Subject: [PATCH 08/67] packet chat_command_signed --- haya_protocol/src/advancement.rs | 4 ++-- haya_protocol/src/chat.rs | 14 +++++++++++--- haya_protocol/src/command.rs | 10 ++++++++++ haya_protocol/src/lib.rs | 3 +++ haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 13 ++++++++++++- 6 files changed, 39 insertions(+), 7 deletions(-) diff --git a/haya_protocol/src/advancement.rs b/haya_protocol/src/advancement.rs index 34a45eba..bd3d37a8 100644 --- a/haya_protocol/src/advancement.rs +++ b/haya_protocol/src/advancement.rs @@ -1,5 +1,5 @@ use crate::item::{ItemStack, TypedDataComponent}; -use crate::{Component, HolderSet, ResourceTexture}; +use crate::{Component, HolderSet, MilliSeconds, ResourceTexture}; use haya_collection::{List, Map}; use haya_ident::Ident; use haya_nbt::Tag; @@ -183,5 +183,5 @@ pub struct AdvancementProgress<'a> { #[derive(Clone, Serialize, Deserialize)] pub struct CriterionProgress { - pub obtained: Option, + pub obtained: Option, } diff --git a/haya_protocol/src/chat.rs b/haya_protocol/src/chat.rs index 7f29b466..6d1810dd 100644 --- a/haya_protocol/src/chat.rs +++ b/haya_protocol/src/chat.rs @@ -1,5 +1,5 @@ use crate::registry::ChatTypeRef; -use crate::{BitSet, Component, Holder, Style}; +use crate::{BitSet, Component, Holder, MilliSeconds, Style}; use haya_collection::List; use mser::{ByteArray, FixedByteArray, Read, Utf8, V32, Write}; use uuid::Uuid; @@ -91,7 +91,7 @@ impl Parameter { #[derive(Clone, Serialize, Deserialize)] pub struct SignedMessageBodyPacked<'a> { pub content: Utf8<'a, 256>, - pub timestamp: u64, + pub timestamp: MilliSeconds, pub salt: u64, pub last_seen: LastSeenMessagesPacked<'a>, } @@ -136,7 +136,15 @@ pub struct RemoteChatSession<'a> { #[derive(Clone, Serialize, Deserialize)] pub struct ProfilePublicKey<'a> { - pub expires_at: u64, + pub expires_at: MilliSeconds, pub key: ByteArray<'a, 512>, pub key_signature: ByteArray<'a, 4096>, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct LastSeenMessagesUpdate<'a> { + #[mser(varint)] + pub offset: u32, + pub acknowledged: FixedByteArray<'a, 3>, + pub checksum: u8, +} diff --git a/haya_protocol/src/command.rs b/haya_protocol/src/command.rs index 61d21010..bb05087c 100644 --- a/haya_protocol/src/command.rs +++ b/haya_protocol/src/command.rs @@ -1,3 +1,4 @@ +use crate::chat::MessageSignature; use haya_collection::List; use haya_ident::{Ident, ResourceKey}; use minecraft_data::command_argument_type; @@ -709,3 +710,12 @@ impl<'a> Read<'a> for CommandNode<'a> { }) } } + +#[derive(Clone, Serialize, Deserialize)] +pub struct ArgumentSignatures<'a>(List<'a, ArgumentSignature<'a>, 8>); + +#[derive(Clone, Serialize, Deserialize)] +pub struct ArgumentSignature<'a> { + pub name: Utf8<'a, 16>, + pub signature: MessageSignature<'a>, +} diff --git a/haya_protocol/src/lib.rs b/haya_protocol/src/lib.rs index f59c4d83..763d5fa8 100644 --- a/haya_protocol/src/lib.rs +++ b/haya_protocol/src/lib.rs @@ -840,6 +840,9 @@ pub struct RgbColor { pub b: u8, } +#[derive(Clone, Copy, Serialize, Deserialize)] +pub struct MilliSeconds(pub u64); + #[cfg(test)] mod tests { use super::*; diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 6a43f3a6..73997df7 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -99,7 +99,7 @@ packets! { change_game_mode = game::ChangeGameMode, chat_ack = game::ChatAck, chat_command = game::ChatCommand<'_>, - // chat_command_signed, + chat_command_signed = game::ChatCommandSigned<'_>, // chat, // chat_session_update, // chunk_batch_received, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 03d88941..b231c4f9 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -1,4 +1,6 @@ -use crate::{Difficulty, GameType}; +use crate::chat::LastSeenMessagesUpdate; +use crate::command::ArgumentSignatures; +use crate::{Difficulty, GameType, MilliSeconds}; use haya_math::BlockPosPacked; use mser::Utf8; @@ -47,3 +49,12 @@ pub struct ChatAck { pub struct ChatCommand<'a> { pub command: Utf8<'a>, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct ChatCommandSigned<'a> { + pub command: Utf8<'a>, + pub time_stamp: MilliSeconds, + pub salt: u64, + pub argument_signatures: ArgumentSignatures<'a>, + pub last_seen_messages: LastSeenMessagesUpdate<'a>, +} From 8762881173865f0cd41007038655cf8233b7506d Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 10:27:44 +0900 Subject: [PATCH 09/67] packet chat --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 73997df7..d5508462 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -100,7 +100,7 @@ packets! { chat_ack = game::ChatAck, chat_command = game::ChatCommand<'_>, chat_command_signed = game::ChatCommandSigned<'_>, - // chat, + chat = game::Chat<'_>, // chat_session_update, // chunk_batch_received, // client_command, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index b231c4f9..f6f518f8 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -1,4 +1,4 @@ -use crate::chat::LastSeenMessagesUpdate; +use crate::chat::{LastSeenMessagesUpdate, MessageSignature, MessageSignaturePacked}; use crate::command::ArgumentSignatures; use crate::{Difficulty, GameType, MilliSeconds}; use haya_math::BlockPosPacked; @@ -58,3 +58,12 @@ pub struct ChatCommandSigned<'a> { pub argument_signatures: ArgumentSignatures<'a>, pub last_seen_messages: LastSeenMessagesUpdate<'a>, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct Chat<'a> { + pub message: Utf8<'a, 256>, + pub time_stamp: MilliSeconds, + pub salt: u64, + pub signature: Option>, + pub last_seen_messages: LastSeenMessagesUpdate<'a>, +} From 654fe7eb95e55bff7b072620c26bf2672d4ee7c6 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 10:38:26 +0900 Subject: [PATCH 10/67] packet chat_session_update --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index d5508462..9346c402 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -101,7 +101,7 @@ packets! { chat_command = game::ChatCommand<'_>, chat_command_signed = game::ChatCommandSigned<'_>, chat = game::Chat<'_>, - // chat_session_update, + chat_session_update = game::ChatSessionUpdate<'_>, // chunk_batch_received, // client_command, // client_tick_end, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index f6f518f8..50ab7e34 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -1,4 +1,6 @@ -use crate::chat::{LastSeenMessagesUpdate, MessageSignature, MessageSignaturePacked}; +use crate::chat::{ + LastSeenMessagesUpdate, MessageSignature, MessageSignaturePacked, RemoteChatSession, +}; use crate::command::ArgumentSignatures; use crate::{Difficulty, GameType, MilliSeconds}; use haya_math::BlockPosPacked; @@ -67,3 +69,8 @@ pub struct Chat<'a> { pub signature: Option>, pub last_seen_messages: LastSeenMessagesUpdate<'a>, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct ChatSessionUpdate<'a> { + pub chat_session: RemoteChatSession<'a>, +} From e035163b1c4cd5a744769e7082237f0d57118127 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 12:00:56 +0900 Subject: [PATCH 11/67] packet chunk_batch_received --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 9346c402..718c2a03 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -102,7 +102,7 @@ packets! { chat_command_signed = game::ChatCommandSigned<'_>, chat = game::Chat<'_>, chat_session_update = game::ChatSessionUpdate<'_>, - // chunk_batch_received, + chunk_batch_received = game::ChunkBatchReceived, // client_command, // client_tick_end, // client_information, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 50ab7e34..4ca848d5 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -74,3 +74,8 @@ pub struct Chat<'a> { pub struct ChatSessionUpdate<'a> { pub chat_session: RemoteChatSession<'a>, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct ChunkBatchReceived { + pub desired_chunks_per_tick: f32, +} From a860465cb347fa9d07cd25a8e89befe5f6985857 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 12:02:36 +0900 Subject: [PATCH 12/67] packet client_command --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 718c2a03..c5587453 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -103,7 +103,7 @@ packets! { chat = game::Chat<'_>, chat_session_update = game::ChatSessionUpdate<'_>, chunk_batch_received = game::ChunkBatchReceived, - // client_command, + client_command = game::ClientCommand, // client_tick_end, // client_information, // command_suggestion, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 4ca848d5..47eb2341 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -79,3 +79,16 @@ pub struct ChatSessionUpdate<'a> { pub struct ChunkBatchReceived { pub desired_chunks_per_tick: f32, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct ClientCommand { + pub action: ClientCommandAction, +} + +#[derive(Clone, Copy, Serialize, Deserialize)] +#[repr(u8)] +#[mser(varint)] +pub enum ClientCommandAction { + PerformRespawn, + RequestStats, +} From 6bc072beb9ef3afe0588356f2d1c9ec7a3e0299d Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 12:03:22 +0900 Subject: [PATCH 13/67] packet client_tick_end --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index c5587453..0c4502a6 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -104,7 +104,7 @@ packets! { chat_session_update = game::ChatSessionUpdate<'_>, chunk_batch_received = game::ChunkBatchReceived, client_command = game::ClientCommand, - // client_tick_end, + client_tick_end = game::ClientTickEnd, // client_information, // command_suggestion, // configuration_acknowledged, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 47eb2341..b1fa9dc3 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -92,3 +92,6 @@ pub enum ClientCommandAction { PerformRespawn, RequestStats, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct ClientTickEnd {} From 508846fa86ce0e399310941f669769a2ac68a492 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 12:05:12 +0900 Subject: [PATCH 14/67] packet client_information --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 0c4502a6..8fb6253b 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -105,7 +105,7 @@ packets! { chunk_batch_received = game::ChunkBatchReceived, client_command = game::ClientCommand, client_tick_end = game::ClientTickEnd, - // client_information, + client_information = game::ClientInformation<'_>, // command_suggestion, // configuration_acknowledged, // container_button_click, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index b1fa9dc3..e5c38dc5 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -95,3 +95,8 @@ pub enum ClientCommandAction { #[derive(Clone, Serialize, Deserialize)] pub struct ClientTickEnd {} + +#[derive(Clone, Serialize, Deserialize)] +pub struct ClientInformation<'a> { + pub information: crate::ClientInformation<'a>, +} From 2cdcdd6bf12358f651c87a901cc5fdd9ff286a75 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 12:06:43 +0900 Subject: [PATCH 15/67] packet command_suggestion --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 8fb6253b..7de26a16 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -106,7 +106,7 @@ packets! { client_command = game::ClientCommand, client_tick_end = game::ClientTickEnd, client_information = game::ClientInformation<'_>, - // command_suggestion, + command_suggestion = game::CommandSuggestion<'_>, // configuration_acknowledged, // container_button_click, // container_click, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index e5c38dc5..66eda716 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -100,3 +100,10 @@ pub struct ClientTickEnd {} pub struct ClientInformation<'a> { pub information: crate::ClientInformation<'a>, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct CommandSuggestion<'a> { + #[mser(varint)] + pub id: u32, + pub command: Utf8<'a, 32500>, +} From e8d40c88da198f2fbf6c7bbd6521d207761f866f Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 12:07:29 +0900 Subject: [PATCH 16/67] packet configuration_acknowledged --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 7de26a16..900b9677 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -107,7 +107,7 @@ packets! { client_tick_end = game::ClientTickEnd, client_information = game::ClientInformation<'_>, command_suggestion = game::CommandSuggestion<'_>, - // configuration_acknowledged, + configuration_acknowledged = game::ConfigurationAcknowledged, // container_button_click, // container_click, // container_close, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 66eda716..af476413 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -107,3 +107,6 @@ pub struct CommandSuggestion<'a> { pub id: u32, pub command: Utf8<'a, 32500>, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct ConfigurationAcknowledged {} From bccf7114d23609f914cac76a2c7fa507dad8cf60 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 12:09:57 +0900 Subject: [PATCH 17/67] packet container_button_click --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 900b9677..3c19bd4a 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -108,7 +108,7 @@ packets! { client_information = game::ClientInformation<'_>, command_suggestion = game::CommandSuggestion<'_>, configuration_acknowledged = game::ConfigurationAcknowledged, - // container_button_click, + container_button_click = game::ContainerButtonClick, // container_click, // container_close, // container_slot_state_changed, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index af476413..716f429d 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -2,7 +2,7 @@ use crate::chat::{ LastSeenMessagesUpdate, MessageSignature, MessageSignaturePacked, RemoteChatSession, }; use crate::command::ArgumentSignatures; -use crate::{Difficulty, GameType, MilliSeconds}; +use crate::{ContainerId, Difficulty, GameType, MilliSeconds}; use haya_math::BlockPosPacked; use mser::Utf8; @@ -110,3 +110,10 @@ pub struct CommandSuggestion<'a> { #[derive(Clone, Serialize, Deserialize)] pub struct ConfigurationAcknowledged {} + +#[derive(Clone, Serialize, Deserialize)] +pub struct ContainerButtonClick { + pub container_id: ContainerId, + #[mser(varint)] + pub button_id: u32, +} From 0901a89982ae56a3359171a1caa407fbfccb7c3d Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 12:53:54 +0900 Subject: [PATCH 18/67] packet container_click --- haya_protocol/src/advancement.rs | 2 +- haya_protocol/src/block.rs | 2 +- haya_protocol/src/clientbound/game.rs | 2 +- haya_protocol/src/crafting.rs | 2 +- haya_protocol/src/entity_data.rs | 2 +- haya_protocol/src/{item.rs => item_stack.rs} | 60 +++---------------- haya_protocol/src/item_stack/consumable.rs | 47 +++++++++++++++ .../{item => item_stack}/consume_effect.rs | 0 .../firework_explosion.rs | 0 .../item_attribute_modifiers.rs | 0 .../{item => item_stack}/item_enchantments.rs | 0 .../{item => item_stack}/kinetic_weapon.rs | 0 .../suspicious_stew_effects.rs | 0 .../src/{item => item_stack}/tool.rs | 0 haya_protocol/src/lib.rs | 33 +++++++++- haya_protocol/src/particle.rs | 2 +- haya_protocol/src/registry.rs | 2 +- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 19 ++++-- haya_protocol/src/trading.rs | 2 +- 20 files changed, 111 insertions(+), 66 deletions(-) rename haya_protocol/src/{item.rs => item_stack.rs} (92%) create mode 100644 haya_protocol/src/item_stack/consumable.rs rename haya_protocol/src/{item => item_stack}/consume_effect.rs (100%) rename haya_protocol/src/{item => item_stack}/firework_explosion.rs (100%) rename haya_protocol/src/{item => item_stack}/item_attribute_modifiers.rs (100%) rename haya_protocol/src/{item => item_stack}/item_enchantments.rs (100%) rename haya_protocol/src/{item => item_stack}/kinetic_weapon.rs (100%) rename haya_protocol/src/{item => item_stack}/suspicious_stew_effects.rs (100%) rename haya_protocol/src/{item => item_stack}/tool.rs (100%) diff --git a/haya_protocol/src/advancement.rs b/haya_protocol/src/advancement.rs index bd3d37a8..e25c7192 100644 --- a/haya_protocol/src/advancement.rs +++ b/haya_protocol/src/advancement.rs @@ -1,4 +1,4 @@ -use crate::item::{ItemStack, TypedDataComponent}; +use crate::item_stack::{ItemStack, TypedDataComponent}; use crate::{Component, HolderSet, MilliSeconds, ResourceTexture}; use haya_collection::{List, Map}; use haya_ident::Ident; diff --git a/haya_protocol/src/block.rs b/haya_protocol/src/block.rs index e5855722..b020e182 100644 --- a/haya_protocol/src/block.rs +++ b/haya_protocol/src/block.rs @@ -1,4 +1,4 @@ -use crate::item::TypedEntityDataEntity; +use crate::item_stack::TypedEntityDataEntity; use crate::registry::BannerPatternRef; use crate::{DyeColor, Holder}; use haya_collection::List; diff --git a/haya_protocol/src/clientbound/game.rs b/haya_protocol/src/clientbound/game.rs index d8616778..961bfe53 100644 --- a/haya_protocol/src/clientbound/game.rs +++ b/haya_protocol/src/clientbound/game.rs @@ -10,7 +10,7 @@ use crate::crafting::{ }; use crate::debug::{DebugSubscriptionEvent, DebugSubscriptionUpdate, RemoteDebugSampleType}; use crate::entity_data::EntityDataSerializer; -use crate::item::OptionalItemStack; +use crate::item_stack::OptionalItemStack; use crate::map::{MapDecoration, MapId, MapPatch}; use crate::minecart::MinecartStep; use crate::particle::{ExplosionParticleInfo, Particle}; diff --git a/haya_protocol/src/crafting.rs b/haya_protocol/src/crafting.rs index 4f823e4a..06e0f70e 100644 --- a/haya_protocol/src/crafting.rs +++ b/haya_protocol/src/crafting.rs @@ -1,4 +1,4 @@ -use crate::item::ItemStack; +use crate::item_stack::ItemStack; use crate::registry::TrimPatternRef; use crate::trim::TrimPattern; use crate::{Holder, HolderSet, OptionalV32}; diff --git a/haya_protocol/src/entity_data.rs b/haya_protocol/src/entity_data.rs index 2047a745..714f644e 100644 --- a/haya_protocol/src/entity_data.rs +++ b/haya_protocol/src/entity_data.rs @@ -2,7 +2,7 @@ use crate::entity::{ ArmadilloState, CopperGolemState, EntityReference, PaintingVariant, Pose, SnifferState, VillagerData, }; -use crate::item::OptionalItemStack; +use crate::item_stack::OptionalItemStack; use crate::profile::ResolvableProfile; use crate::registry::{ CatVariantRef, ChickenVariantRef, CowVariantRef, FrogVariantRef, PaintingVariantRef, diff --git a/haya_protocol/src/item.rs b/haya_protocol/src/item_stack.rs similarity index 92% rename from haya_protocol/src/item.rs rename to haya_protocol/src/item_stack.rs index b474829f..80cd1285 100644 --- a/haya_protocol/src/item.rs +++ b/haya_protocol/src/item_stack.rs @@ -1,3 +1,4 @@ +pub mod consumable; pub mod consume_effect; pub mod firework_explosion; pub mod item_attribute_modifiers; @@ -6,6 +7,14 @@ pub mod kinetic_weapon; pub mod suspicious_stew_effects; pub mod tool; +use self::consumable::Consumable; +use self::consume_effect::ConsumeEffect; +use self::firework_explosion::FireworkExplosion; +use self::item_attribute_modifiers::ItemAttributeModifiers; +use self::item_enchantments::ItemEnchantments; +use self::kinetic_weapon::KineticWeapon; +use self::suspicious_stew_effects::SuspiciousStewEffects; +use self::tool::Tool; use crate::advancement::BlockPredicate; use crate::block::{BannerPatternLayers, BeehiveOccupant}; use crate::effect::MobEffect; @@ -14,13 +23,6 @@ use crate::entity::{ ParrotVariant, RabbitVariant, SalmonVariant, TropicalFishPattern, }; use crate::food::FoodProperties; -use crate::item::consume_effect::ConsumeEffect; -use crate::item::firework_explosion::FireworkExplosion; -use crate::item::item_attribute_modifiers::ItemAttributeModifiers; -use crate::item::item_enchantments::ItemEnchantments; -use crate::item::kinetic_weapon::KineticWeapon; -use crate::item::suspicious_stew_effects::SuspiciousStewEffects; -use crate::item::tool::Tool; use crate::map::MapId; use crate::profile::ResolvableProfile; use crate::registry::{ @@ -173,50 +175,6 @@ pub struct TooltipDisplay<'a> { pub hidden_components: List<'a, TypedDataComponent<'a>>, } -#[derive(Clone, Serialize, Deserialize)] -pub struct Consumable<'a> { - pub consume_seconds: f32, - pub animation: ItemUseAnimation, - pub sound: Holder, sound_event>, -} - -#[derive(Clone, Copy, Serialize, Deserialize)] -#[mser(varint)] -#[repr(u8)] -pub enum ItemUseAnimation { - None, - Eat, - Drink, - Block, - Bow, - Trident, - Crossbow, - Spyglass, - TootHorn, - Brush, - Bundle, - Spear, -} - -impl ItemUseAnimation { - pub const fn name(self) -> &'static str { - match self { - Self::None => "none", - Self::Eat => "eat", - Self::Drink => "drink", - Self::Block => "block", - Self::Bow => "bow", - Self::Trident => "trident", - Self::Crossbow => "crossbow", - Self::Spyglass => "spyglass", - Self::TootHorn => "toot_horn", - Self::Brush => "brush", - Self::Bundle => "bundle", - Self::Spear => "spear", - } - } -} - #[derive(Clone, Serialize, Deserialize)] pub struct UseRemainder<'a> { pub convert_into: OptionalItemStack<'a>, diff --git a/haya_protocol/src/item_stack/consumable.rs b/haya_protocol/src/item_stack/consumable.rs new file mode 100644 index 00000000..0648eb64 --- /dev/null +++ b/haya_protocol/src/item_stack/consumable.rs @@ -0,0 +1,47 @@ +use crate::Holder; +use crate::sound::SoundEvent; +use minecraft_data::sound_event; + +#[derive(Clone, Serialize, Deserialize)] +pub struct Consumable<'a> { + pub consume_seconds: f32, + pub animation: ItemUseAnimation, + pub sound: Holder, sound_event>, +} + +#[derive(Clone, Copy, Serialize, Deserialize)] +#[mser(varint)] +#[repr(u8)] +pub enum ItemUseAnimation { + None, + Eat, + Drink, + Block, + Bow, + Trident, + Crossbow, + Spyglass, + TootHorn, + Brush, + Bundle, + Spear, +} + +impl ItemUseAnimation { + pub const fn name(self) -> &'static str { + match self { + Self::None => "none", + Self::Eat => "eat", + Self::Drink => "drink", + Self::Block => "block", + Self::Bow => "bow", + Self::Trident => "trident", + Self::Crossbow => "crossbow", + Self::Spyglass => "spyglass", + Self::TootHorn => "toot_horn", + Self::Brush => "brush", + Self::Bundle => "bundle", + Self::Spear => "spear", + } + } +} diff --git a/haya_protocol/src/item/consume_effect.rs b/haya_protocol/src/item_stack/consume_effect.rs similarity index 100% rename from haya_protocol/src/item/consume_effect.rs rename to haya_protocol/src/item_stack/consume_effect.rs diff --git a/haya_protocol/src/item/firework_explosion.rs b/haya_protocol/src/item_stack/firework_explosion.rs similarity index 100% rename from haya_protocol/src/item/firework_explosion.rs rename to haya_protocol/src/item_stack/firework_explosion.rs diff --git a/haya_protocol/src/item/item_attribute_modifiers.rs b/haya_protocol/src/item_stack/item_attribute_modifiers.rs similarity index 100% rename from haya_protocol/src/item/item_attribute_modifiers.rs rename to haya_protocol/src/item_stack/item_attribute_modifiers.rs diff --git a/haya_protocol/src/item/item_enchantments.rs b/haya_protocol/src/item_stack/item_enchantments.rs similarity index 100% rename from haya_protocol/src/item/item_enchantments.rs rename to haya_protocol/src/item_stack/item_enchantments.rs diff --git a/haya_protocol/src/item/kinetic_weapon.rs b/haya_protocol/src/item_stack/kinetic_weapon.rs similarity index 100% rename from haya_protocol/src/item/kinetic_weapon.rs rename to haya_protocol/src/item_stack/kinetic_weapon.rs diff --git a/haya_protocol/src/item/suspicious_stew_effects.rs b/haya_protocol/src/item_stack/suspicious_stew_effects.rs similarity index 100% rename from haya_protocol/src/item/suspicious_stew_effects.rs rename to haya_protocol/src/item_stack/suspicious_stew_effects.rs diff --git a/haya_protocol/src/item/tool.rs b/haya_protocol/src/item_stack/tool.rs similarity index 100% rename from haya_protocol/src/item/tool.rs rename to haya_protocol/src/item_stack/tool.rs diff --git a/haya_protocol/src/lib.rs b/haya_protocol/src/lib.rs index 763d5fa8..3cf119f5 100644 --- a/haya_protocol/src/lib.rs +++ b/haya_protocol/src/lib.rs @@ -1,10 +1,11 @@ #![no_std] use alloc::vec::Vec; -use haya_collection::{List, capacity_fix}; +use haya_collection::{List, Map, capacity_fix}; use haya_ident::{Ident, ResourceKey}; use haya_math::BlockPosPacked; use haya_nbt::Tag; +use minecraft_data::data_component_type; use mser::{Either, Error, Read, Reader, Utf8, V21, V32, Write, Writer}; pub mod advancement; @@ -20,7 +21,7 @@ pub mod entity; pub mod entity_data; pub mod food; pub mod game_event; -pub mod item; +pub mod item_stack; pub mod level_event; pub mod map; pub mod minecart; @@ -843,6 +844,34 @@ pub struct RgbColor { #[derive(Clone, Copy, Serialize, Deserialize)] pub struct MilliSeconds(pub u64); +#[derive(Clone, Copy, Serialize, Deserialize)] +#[repr(u8)] +#[mser(varint)] +pub enum ClickType { + Pickup, + QuickMove, + Swap, + Clone, + Throw, + QuickCraft, + PickupAll, +} + +// CRC32C +#[derive(Clone, Serialize, Deserialize)] +pub struct HashedPatchMap<'a> { + pub added_components: Map<'a, data_component_type, u32, 256>, + pub removed_components: List<'a, data_component_type, 256>, +} + +#[derive(Clone, Serialize, Deserialize)] +pub struct HashedStack<'a> { + pub item: minecraft_data::item, + #[mser(varint)] + pub count: u32, + pub components: HashedPatchMap<'a>, +} + #[cfg(test)] mod tests { use super::*; diff --git a/haya_protocol/src/particle.rs b/haya_protocol/src/particle.rs index 8b081f95..88c997f6 100644 --- a/haya_protocol/src/particle.rs +++ b/haya_protocol/src/particle.rs @@ -1,5 +1,5 @@ use crate::game_event::PositionSource; -use crate::item::ItemStack; +use crate::item_stack::ItemStack; use haya_math::Vec3; use minecraft_data::{block_state, particle_type}; diff --git a/haya_protocol/src/registry.rs b/haya_protocol/src/registry.rs index a0b939ab..8ebd872f 100644 --- a/haya_protocol/src/registry.rs +++ b/haya_protocol/src/registry.rs @@ -1,7 +1,7 @@ use crate::block::BannerPattern; use crate::chat::ChatType; use crate::entity::PaintingVariant; -use crate::item::{Instrument, JukeboxSong}; +use crate::item_stack::{Instrument, JukeboxSong}; use crate::sound::SoundEvent; use crate::trim::{TrimMaterial, TrimPattern}; use crate::{Dialog, Holder}; diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 3c19bd4a..b5585a9e 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -109,7 +109,7 @@ packets! { command_suggestion = game::CommandSuggestion<'_>, configuration_acknowledged = game::ConfigurationAcknowledged, container_button_click = game::ContainerButtonClick, - // container_click, + container_click = game::ContainerClick<'_>, // container_close, // container_slot_state_changed, // cookie_response, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 716f429d..f5e3a42a 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -1,8 +1,7 @@ -use crate::chat::{ - LastSeenMessagesUpdate, MessageSignature, MessageSignaturePacked, RemoteChatSession, -}; +use crate::chat::{LastSeenMessagesUpdate, MessageSignature, RemoteChatSession}; use crate::command::ArgumentSignatures; -use crate::{ContainerId, Difficulty, GameType, MilliSeconds}; +use crate::{ClickType, ContainerId, Difficulty, GameType, HashedStack, MilliSeconds}; +use haya_collection::Map; use haya_math::BlockPosPacked; use mser::Utf8; @@ -117,3 +116,15 @@ pub struct ContainerButtonClick { #[mser(varint)] pub button_id: u32, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct ContainerClick<'a> { + pub container_id: ContainerId, + #[mser(varint)] + pub state_id: u32, + pub slot_num: u16, + pub button_num: u8, + pub click_type: ClickType, + pub changed_slots: Map<'a, u16, Option>, 128>, + pub carried_item: Option>, +} diff --git a/haya_protocol/src/trading.rs b/haya_protocol/src/trading.rs index 323a7d7c..3e5961f2 100644 --- a/haya_protocol/src/trading.rs +++ b/haya_protocol/src/trading.rs @@ -1,4 +1,4 @@ -use crate::item::{DataComponentExactPredicate, ItemStack}; +use crate::item_stack::{DataComponentExactPredicate, ItemStack}; use minecraft_data::item; #[derive(Clone, Serialize, Deserialize)] From e37d6fdc573b51d2ebf553cb5466b174a564224b Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 12:56:40 +0900 Subject: [PATCH 19/67] packet container_close --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index b5585a9e..3584c53c 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -110,7 +110,7 @@ packets! { configuration_acknowledged = game::ConfigurationAcknowledged, container_button_click = game::ContainerButtonClick, container_click = game::ContainerClick<'_>, - // container_close, + container_close = game::ContainerClose, // container_slot_state_changed, // cookie_response, // custom_payload, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index f5e3a42a..6c1b6648 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -128,3 +128,8 @@ pub struct ContainerClick<'a> { pub changed_slots: Map<'a, u16, Option>, 128>, pub carried_item: Option>, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct ContainerClose { + pub container_id: ContainerId, +} From baa0ec04b155f16b817968733d59ca0bc8a8fe9e Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 12:59:13 +0900 Subject: [PATCH 20/67] packet container_slot_state_changed --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 3584c53c..adc26671 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -111,7 +111,7 @@ packets! { container_button_click = game::ContainerButtonClick, container_click = game::ContainerClick<'_>, container_close = game::ContainerClose, - // container_slot_state_changed, + container_slot_state_changed = game::ContainerSlotStateChanged, // cookie_response, // custom_payload, // debug_subscription_request, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 6c1b6648..5411d6f0 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -133,3 +133,11 @@ pub struct ContainerClick<'a> { pub struct ContainerClose { pub container_id: ContainerId, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct ContainerSlotStateChanged { + #[mser(varint)] + pub slot_id: u32, + pub container_id: ContainerId, + pub new_state: bool, +} From 5a10b7457568ebf64bad309919c767f93c3702a4 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 18:11:28 +0900 Subject: [PATCH 21/67] packet cookie_response --- haya_protocol/src/serverbound.rs | 4 ++-- haya_protocol/src/serverbound/cookie.rs | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index adc26671..1396a036 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -71,7 +71,7 @@ packets! { key = login::Key<'_>, custom_query_answer = login::CustomQueryAnswer<'_>, login_acknowledged = login::LoginAcknowledged, - cookie_response = cookie::CookieResponse<'_>, + cookie_response = cookie::LoginCookieResponse<'_>, } packets! { serverbound__configuration, @@ -112,7 +112,7 @@ packets! { container_click = game::ContainerClick<'_>, container_close = game::ContainerClose, container_slot_state_changed = game::ContainerSlotStateChanged, - // cookie_response, + cookie_response = cookie::GameCookieResponse<'_>, // custom_payload, // debug_subscription_request, // edit_book, diff --git a/haya_protocol/src/serverbound/cookie.rs b/haya_protocol/src/serverbound/cookie.rs index 70cf5093..39ea9bd0 100644 --- a/haya_protocol/src/serverbound/cookie.rs +++ b/haya_protocol/src/serverbound/cookie.rs @@ -7,6 +7,9 @@ pub struct LoginCookieResponse<'a>(pub CookieResponse<'a>); #[derive(Clone, Serialize, Deserialize)] pub struct ConfigurationCookieResponse<'a>(pub CookieResponse<'a>); +#[derive(Clone, Serialize, Deserialize)] +pub struct GameCookieResponse<'a>(pub CookieResponse<'a>); + #[derive(Clone, Serialize, Deserialize)] pub struct CookieResponse<'a> { pub key: Ident<'a>, From ed704bcdd3f7712d09d22bfa848fb20805c62a34 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 18:14:00 +0900 Subject: [PATCH 22/67] packet custom_payload --- haya_protocol/src/serverbound.rs | 4 ++-- haya_protocol/src/serverbound/common.rs | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 1396a036..c4aa217c 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -79,7 +79,7 @@ packets! { handle, client_information = common::ConfigurationClientInformation<'_>, cookie_response = cookie::ConfigurationCookieResponse<'_>, - custom_payload = common::CustomPayload<'_>, + custom_payload = common::ConfigurationCustomPayload<'_>, finish_configuration = configuration::FinishConfiguration, keep_alive = common::KeepAlive, pong = common::Pong, @@ -113,7 +113,7 @@ packets! { container_close = game::ContainerClose, container_slot_state_changed = game::ContainerSlotStateChanged, cookie_response = cookie::GameCookieResponse<'_>, - // custom_payload, + custom_payload = common::GameCustomPayload<'_>, // debug_subscription_request, // edit_book, // entity_tag_query, diff --git a/haya_protocol/src/serverbound/common.rs b/haya_protocol/src/serverbound/common.rs index b1b37253..1bf19178 100644 --- a/haya_protocol/src/serverbound/common.rs +++ b/haya_protocol/src/serverbound/common.rs @@ -7,6 +7,12 @@ use uuid::Uuid; #[derive(Clone, Serialize, Deserialize)] pub struct ConfigurationClientInformation<'a>(pub ClientInformation<'a>); +#[derive(Clone, Serialize, Deserialize)] +pub struct ConfigurationCustomPayload<'a>(pub CustomPayload<'a>); + +#[derive(Clone, Serialize, Deserialize)] +pub struct GameCustomPayload<'a>(pub CustomPayload<'a>); + #[derive(Clone, Serialize, Deserialize)] pub struct CustomPayload<'a> { pub id: Ident<'a>, From fc0ae5b730c1aecf444bc4531a36dc4dc57ef818 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 18:16:46 +0900 Subject: [PATCH 23/67] packet debug_subscription_request --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index c4aa217c..2fb4b433 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -114,7 +114,7 @@ packets! { container_slot_state_changed = game::ContainerSlotStateChanged, cookie_response = cookie::GameCookieResponse<'_>, custom_payload = common::GameCustomPayload<'_>, - // debug_subscription_request, + debug_subscription_request = game::DebugSubscriptionRequest<'_>, // edit_book, // entity_tag_query, // interact, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 5411d6f0..0cc1f127 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -1,8 +1,9 @@ use crate::chat::{LastSeenMessagesUpdate, MessageSignature, RemoteChatSession}; use crate::command::ArgumentSignatures; use crate::{ClickType, ContainerId, Difficulty, GameType, HashedStack, MilliSeconds}; -use haya_collection::Map; +use haya_collection::{List, Map}; use haya_math::BlockPosPacked; +use minecraft_data::debug_subscription; use mser::Utf8; #[derive(Clone, Serialize, Deserialize)] @@ -141,3 +142,8 @@ pub struct ContainerSlotStateChanged { pub container_id: ContainerId, pub new_state: bool, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct DebugSubscriptionRequest<'a> { + pub subscriptions: List<'a, debug_subscription>, +} From 274e8208fff9fa8650ebcd10a3d7ab432556adff Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 18:50:00 +0900 Subject: [PATCH 24/67] packet edit_book --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 2fb4b433..17bfa4a5 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -115,7 +115,7 @@ packets! { cookie_response = cookie::GameCookieResponse<'_>, custom_payload = common::GameCustomPayload<'_>, debug_subscription_request = game::DebugSubscriptionRequest<'_>, - // edit_book, + edit_book = game::EditBook<'_>, // entity_tag_query, // interact, // jigsaw_generate, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 0cc1f127..6dbd246b 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -147,3 +147,11 @@ pub struct ContainerSlotStateChanged { pub struct DebugSubscriptionRequest<'a> { pub subscriptions: List<'a, debug_subscription>, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct EditBook<'a> { + #[mser(varint)] + pub slot: u32, + pub pages: List<'a, Utf8<'a, 1024>, 100>, + pub title: Option>, +} From 90262549334a1bec0db8ae6040efd17fbe65b7ec Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 18:52:46 +0900 Subject: [PATCH 25/67] packet entity_tag_query --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 17bfa4a5..f2da6c1a 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -116,7 +116,7 @@ packets! { custom_payload = common::GameCustomPayload<'_>, debug_subscription_request = game::DebugSubscriptionRequest<'_>, edit_book = game::EditBook<'_>, - // entity_tag_query, + entity_tag_query = game::EntityTagQuery, // interact, // jigsaw_generate, // keep_alive, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 6dbd246b..b72cd148 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -155,3 +155,11 @@ pub struct EditBook<'a> { pub pages: List<'a, Utf8<'a, 1024>, 100>, pub title: Option>, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct EntityTagQuery { + #[mser(varint)] + pub transaction_id: u32, + #[mser(varint)] + pub entity_id: u32, +} From b73c12c136298e0cb9457ff4bca233e25e2982d6 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 18:58:42 +0900 Subject: [PATCH 26/67] packet interact --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 36 +++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index f2da6c1a..b731f4be 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -117,7 +117,7 @@ packets! { debug_subscription_request = game::DebugSubscriptionRequest<'_>, edit_book = game::EditBook<'_>, entity_tag_query = game::EntityTagQuery, - // interact, + interact = game::Interact, // jigsaw_generate, // keep_alive, // lock_difficulty, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index b72cd148..311f8eb7 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -1,8 +1,10 @@ use crate::chat::{LastSeenMessagesUpdate, MessageSignature, RemoteChatSession}; use crate::command::ArgumentSignatures; -use crate::{ClickType, ContainerId, Difficulty, GameType, HashedStack, MilliSeconds}; +use crate::{ + ClickType, ContainerId, Difficulty, GameType, HashedStack, InteractionHand, MilliSeconds, +}; use haya_collection::{List, Map}; -use haya_math::BlockPosPacked; +use haya_math::{BlockPosPacked, FVec3}; use minecraft_data::debug_subscription; use mser::Utf8; @@ -163,3 +165,33 @@ pub struct EntityTagQuery { #[mser(varint)] pub entity_id: u32, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct Interact { + #[mser(varint)] + pub entity_id: u32, + pub action: InteractAction, + pub using_secondary_action: bool, +} + +#[derive(Clone, Serialize, Deserialize)] +#[mser(header = InteractActionType, camel_case)] +pub enum InteractAction { + Interact { + hand: InteractionHand, + }, + Attack, + InteractAt { + location: FVec3, + hand: InteractionHand, + }, +} + +#[derive(Clone, Copy, Serialize, Deserialize)] +#[repr(u8)] +#[mser(varint)] +pub enum InteractActionType { + Interact, + Attack, + InteractAt, +} From 282307b6e83dc3944c5dcd274c0fc5e0afcef148 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 19:43:49 +0900 Subject: [PATCH 27/67] packet jigsaw_generate --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index b731f4be..bc1f16e8 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -118,7 +118,7 @@ packets! { edit_book = game::EditBook<'_>, entity_tag_query = game::EntityTagQuery, interact = game::Interact, - // jigsaw_generate, + jigsaw_generate = game::JigsawGenerate, // keep_alive, // lock_difficulty, // move_player_pos, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 311f8eb7..23621341 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -195,3 +195,11 @@ pub enum InteractActionType { Attack, InteractAt, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct JigsawGenerate { + pub pos: BlockPosPacked, + #[mser(varint)] + pub levels: u32, + pub keep_jigsaws: bool, +} From 4a56da7ee81e9fd5bf2d0c7ec730d3ef608245ff Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 19:45:23 +0900 Subject: [PATCH 28/67] packet keep_alive --- haya_protocol/src/serverbound.rs | 4 ++-- haya_protocol/src/serverbound/common.rs | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index bc1f16e8..788d05d2 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -81,7 +81,7 @@ packets! { cookie_response = cookie::ConfigurationCookieResponse<'_>, custom_payload = common::ConfigurationCustomPayload<'_>, finish_configuration = configuration::FinishConfiguration, - keep_alive = common::KeepAlive, + keep_alive = common::ConfigurationKeepAlive, pong = common::Pong, resource_pack = common::ResourcePack, select_known_packs = configuration::SelectKnownPacks<'_>, @@ -119,7 +119,7 @@ packets! { entity_tag_query = game::EntityTagQuery, interact = game::Interact, jigsaw_generate = game::JigsawGenerate, - // keep_alive, + keep_alive = common::GameKeepAlive, // lock_difficulty, // move_player_pos, // move_player_pos_rot, diff --git a/haya_protocol/src/serverbound/common.rs b/haya_protocol/src/serverbound/common.rs index 1bf19178..421a6df1 100644 --- a/haya_protocol/src/serverbound/common.rs +++ b/haya_protocol/src/serverbound/common.rs @@ -19,6 +19,12 @@ pub struct CustomPayload<'a> { pub payload: Rest<'a, 32767>, } +#[derive(Clone, Serialize, Deserialize)] +pub struct ConfigurationKeepAlive(pub KeepAlive); + +#[derive(Clone, Serialize, Deserialize)] +pub struct GameKeepAlive(pub KeepAlive); + #[derive(Clone, Serialize, Deserialize)] pub struct KeepAlive { pub id: u64, From 6c5b4168bdefaad939bde24c2b6f7b0376237f47 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 20:22:52 +0900 Subject: [PATCH 29/67] packet lock_difficulty --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 788d05d2..a7a716b9 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -120,7 +120,7 @@ packets! { interact = game::Interact, jigsaw_generate = game::JigsawGenerate, keep_alive = common::GameKeepAlive, - // lock_difficulty, + lock_difficulty = game::LockDifficulty, // move_player_pos, // move_player_pos_rot, // move_player_rot, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 23621341..7b69d9a6 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -203,3 +203,8 @@ pub struct JigsawGenerate { pub levels: u32, pub keep_jigsaws: bool, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct LockDifficulty { + pub locked: bool, +} From 0ed48b8da8163da4faebfd9b45642774e0259dfd Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 20:26:50 +0900 Subject: [PATCH 30/67] packet move_player_pos --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index a7a716b9..affe285b 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -121,7 +121,7 @@ packets! { jigsaw_generate = game::JigsawGenerate, keep_alive = common::GameKeepAlive, lock_difficulty = game::LockDifficulty, - // move_player_pos, + move_player_pos = game::MovePlayerPos, // move_player_pos_rot, // move_player_rot, // move_player_status_only, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 7b69d9a6..c891b0ec 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -4,7 +4,7 @@ use crate::{ ClickType, ContainerId, Difficulty, GameType, HashedStack, InteractionHand, MilliSeconds, }; use haya_collection::{List, Map}; -use haya_math::{BlockPosPacked, FVec3}; +use haya_math::{BlockPosPacked, FVec3, Vec3}; use minecraft_data::debug_subscription; use mser::Utf8; @@ -208,3 +208,17 @@ pub struct JigsawGenerate { pub struct LockDifficulty { pub locked: bool, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct MovePlayerPos { + pub pos: Vec3, + pub flags: MovePlayerPosFlags, +} + +#[derive(Clone, Serialize, Deserialize)] +pub struct MovePlayerPosFlags(pub u8); + +impl MovePlayerPosFlags { + pub const ON_GROUND: u8 = 1; + pub const HORIZONTAL_COLLISION: u8 = 2; +} From 4ca1de5f9fb223fd6a22012dd82963271133260b Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 20:28:27 +0900 Subject: [PATCH 31/67] packet move_player_pos_rot --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index affe285b..ca93c3b8 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -122,7 +122,7 @@ packets! { keep_alive = common::GameKeepAlive, lock_difficulty = game::LockDifficulty, move_player_pos = game::MovePlayerPos, - // move_player_pos_rot, + move_player_pos_rot = game::MovePlayerPosRot, // move_player_rot, // move_player_status_only, // move_vehicle, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index c891b0ec..adf8ab49 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -212,13 +212,21 @@ pub struct LockDifficulty { #[derive(Clone, Serialize, Deserialize)] pub struct MovePlayerPos { pub pos: Vec3, - pub flags: MovePlayerPosFlags, + pub flags: MovePlayerFlags, } #[derive(Clone, Serialize, Deserialize)] -pub struct MovePlayerPosFlags(pub u8); +pub struct MovePlayerFlags(pub u8); -impl MovePlayerPosFlags { +impl MovePlayerFlags { pub const ON_GROUND: u8 = 1; pub const HORIZONTAL_COLLISION: u8 = 2; } + +#[derive(Clone, Serialize, Deserialize)] +pub struct MovePlayerPosRot { + pub pos: Vec3, + pub y_rot: f32, + pub x_rot: f32, + pub flags: MovePlayerFlags, +} From 1fe1b999ae5f1805581120f95c925cb92a2ad18f Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 20:29:38 +0900 Subject: [PATCH 32/67] packet move_player_rot --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index ca93c3b8..81f328bc 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -123,7 +123,7 @@ packets! { lock_difficulty = game::LockDifficulty, move_player_pos = game::MovePlayerPos, move_player_pos_rot = game::MovePlayerPosRot, - // move_player_rot, + move_player_rot = game::MovePlayerRot, // move_player_status_only, // move_vehicle, // paddle_boat, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index adf8ab49..bb936749 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -230,3 +230,10 @@ pub struct MovePlayerPosRot { pub x_rot: f32, pub flags: MovePlayerFlags, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct MovePlayerRot { + pub y_rot: f32, + pub x_rot: f32, + pub flags: MovePlayerFlags, +} From b44df3451c1ee07bef449efbba77b92b39fc7dd2 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 20:30:40 +0900 Subject: [PATCH 33/67] packet move_player_status_only --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 81f328bc..806c7547 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -124,7 +124,7 @@ packets! { move_player_pos = game::MovePlayerPos, move_player_pos_rot = game::MovePlayerPosRot, move_player_rot = game::MovePlayerRot, - // move_player_status_only, + move_player_status_only = game::MovePlayerStatusOnly, // move_vehicle, // paddle_boat, // pick_item_from_block, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index bb936749..ee68fcff 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -237,3 +237,8 @@ pub struct MovePlayerRot { pub x_rot: f32, pub flags: MovePlayerFlags, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct MovePlayerStatusOnly { + pub flags: MovePlayerFlags, +} From 244b404aac50af297a5659a130dc6c1108aa9bc6 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 20:32:00 +0900 Subject: [PATCH 34/67] packet move_vehicle --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 806c7547..eec489db 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -125,7 +125,7 @@ packets! { move_player_pos_rot = game::MovePlayerPosRot, move_player_rot = game::MovePlayerRot, move_player_status_only = game::MovePlayerStatusOnly, - // move_vehicle, + move_vehicle = game::MoveVehicle, // paddle_boat, // pick_item_from_block, // pick_item_from_entity, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index ee68fcff..d56d33ff 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -242,3 +242,11 @@ pub struct MovePlayerRot { pub struct MovePlayerStatusOnly { pub flags: MovePlayerFlags, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct MoveVehicle { + pub position: Vec3, + pub y_rot: f32, + pub x_rot: f32, + pub on_ground: bool, +} From 49efbc103e91f123b8d22406ead7bf6b5f6acf3c Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 20:34:32 +0900 Subject: [PATCH 35/67] packet paddle_boat --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index eec489db..3cf1e48a 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -126,7 +126,7 @@ packets! { move_player_rot = game::MovePlayerRot, move_player_status_only = game::MovePlayerStatusOnly, move_vehicle = game::MoveVehicle, - // paddle_boat, + paddle_boat = game::PaddleBoat, // pick_item_from_block, // pick_item_from_entity, // ping_request, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index d56d33ff..49d363f4 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -250,3 +250,9 @@ pub struct MoveVehicle { pub x_rot: f32, pub on_ground: bool, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct PaddleBoat { + pub left: bool, + pub right: bool, +} From 131106104d47c8fde31e1f74e67fe1ecfae66dc2 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 20:36:00 +0900 Subject: [PATCH 36/67] packet pick_item_from_block --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 3cf1e48a..0fecbca4 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -127,7 +127,7 @@ packets! { move_player_status_only = game::MovePlayerStatusOnly, move_vehicle = game::MoveVehicle, paddle_boat = game::PaddleBoat, - // pick_item_from_block, + pick_item_from_block = game::PickItemFromBlock, // pick_item_from_entity, // ping_request, // place_recipe, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 49d363f4..be5a3c09 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -256,3 +256,9 @@ pub struct PaddleBoat { pub left: bool, pub right: bool, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct PickItemFromBlock { + pub pos: BlockPosPacked, + pub include_data: bool, +} From 3b09355e72850febbd7556b1dfa941a8d510ad5b Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 20:37:25 +0900 Subject: [PATCH 37/67] packet pick_item_from_entity --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 0fecbca4..6f139be1 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -128,7 +128,7 @@ packets! { move_vehicle = game::MoveVehicle, paddle_boat = game::PaddleBoat, pick_item_from_block = game::PickItemFromBlock, - // pick_item_from_entity, + pick_item_from_entity = game::PickItemFromEntity, // ping_request, // place_recipe, // player_abilities, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index be5a3c09..8f13f566 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -262,3 +262,10 @@ pub struct PickItemFromBlock { pub pos: BlockPosPacked, pub include_data: bool, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct PickItemFromEntity { + #[mser(varint)] + pub id: u32, + pub include_data: bool, +} From e3bf8825bb7e7b1c01c73653218dffc9995896ae Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 20:40:26 +0900 Subject: [PATCH 38/67] packet ping_request --- haya_protocol/src/serverbound.rs | 4 ++-- haya_protocol/src/serverbound/ping.rs | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 6f139be1..d72ce134 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -61,7 +61,7 @@ packets! { StatusHandler, handle, status_request = status::StatusRequest, - ping_request = ping::PingRequest, + ping_request = ping::StatusPingRequest, } packets! { serverbound__login, @@ -129,7 +129,7 @@ packets! { paddle_boat = game::PaddleBoat, pick_item_from_block = game::PickItemFromBlock, pick_item_from_entity = game::PickItemFromEntity, - // ping_request, + ping_request = ping::GamePingRequest, // place_recipe, // player_abilities, // player_action, diff --git a/haya_protocol/src/serverbound/ping.rs b/haya_protocol/src/serverbound/ping.rs index 8f107765..53c7a80b 100644 --- a/haya_protocol/src/serverbound/ping.rs +++ b/haya_protocol/src/serverbound/ping.rs @@ -1,3 +1,9 @@ +#[derive(Clone, Serialize, Deserialize)] +pub struct StatusPingRequest(pub PingRequest); + +#[derive(Clone, Serialize, Deserialize)] +pub struct GamePingRequest(pub PingRequest); + #[derive(Clone, Serialize, Deserialize)] pub struct PingRequest { pub time: u64, From ea227e8754db1ddacf6ad96a67994d01c45e31a9 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 20:42:21 +0900 Subject: [PATCH 39/67] packet place_recipe --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index d72ce134..2849494b 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -130,7 +130,7 @@ packets! { pick_item_from_block = game::PickItemFromBlock, pick_item_from_entity = game::PickItemFromEntity, ping_request = ping::GamePingRequest, - // place_recipe, + place_recipe = game::PlaceRecipe, // player_abilities, // player_action, // player_command, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 8f13f566..d7d49bfd 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -1,5 +1,6 @@ use crate::chat::{LastSeenMessagesUpdate, MessageSignature, RemoteChatSession}; use crate::command::ArgumentSignatures; +use crate::crafting::RecipeDisplayId; use crate::{ ClickType, ContainerId, Difficulty, GameType, HashedStack, InteractionHand, MilliSeconds, }; @@ -269,3 +270,10 @@ pub struct PickItemFromEntity { pub id: u32, pub include_data: bool, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct PlaceRecipe { + pub container_id: ContainerId, + pub recipe: RecipeDisplayId, + pub use_max_items: bool, +} From 51c2ddd0d1ae9f795eb30c4ce15af44a419d8104 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 20:45:05 +0900 Subject: [PATCH 40/67] packet player_abilities --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 2849494b..ca16393c 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -131,7 +131,7 @@ packets! { pick_item_from_entity = game::PickItemFromEntity, ping_request = ping::GamePingRequest, place_recipe = game::PlaceRecipe, - // player_abilities, + player_abilities = game::PlayerAbilities, // player_action, // player_command, // player_input, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index d7d49bfd..19df8c74 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -216,7 +216,7 @@ pub struct MovePlayerPos { pub flags: MovePlayerFlags, } -#[derive(Clone, Serialize, Deserialize)] +#[derive(Clone, Copy, Serialize, Deserialize)] pub struct MovePlayerFlags(pub u8); impl MovePlayerFlags { @@ -277,3 +277,19 @@ pub struct PlaceRecipe { pub recipe: RecipeDisplayId, pub use_max_items: bool, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct PlayerAbilities { + pub flags: PlayerAbilitiesFlags, +} + +#[derive(Clone, Copy, Serialize, Deserialize)] +pub struct PlayerAbilitiesFlags(pub u8); + +impl PlayerAbilitiesFlags { + pub const FLYING: u8 = 2; + + pub const fn flying(self) -> bool { + self.0 & Self::FLYING != 0 + } +} From c592d5c2f57abe1488c52f3d1e4169da94ef07f8 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 20:54:51 +0900 Subject: [PATCH 41/67] packet player_action --- haya_math/src/lib.rs | 30 +++++++++++++++++++++++++-- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 25 +++++++++++++++++++++- 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/haya_math/src/lib.rs b/haya_math/src/lib.rs index 8c0833a9..c6d8909c 100644 --- a/haya_math/src/lib.rs +++ b/haya_math/src/lib.rs @@ -325,8 +325,8 @@ impl From for LpVec3 { pub struct ByteAngle(pub u8); impl ByteAngle { - pub fn new(f: f32) -> ByteAngle { - ByteAngle(libm::floorf(f * 256.0 / 360.0) as u8) + pub fn new(f: f32) -> Self { + Self(libm::floorf(f * 256.0 / 360.0) as u8) } pub fn to_degrees(self) -> f32 { @@ -562,6 +562,32 @@ pub enum Direction { East, } +#[derive(Clone, Copy, Eq, PartialEq)] +pub struct ByteDirection(pub Direction); + +impl<'a> Read<'a> for ByteDirection { + fn read(buf: &mut Reader<'a>) -> Result { + Ok(Self(match buf.read_byte() { + 1 => Direction::Up, + 2 => Direction::North, + 3 => Direction::South, + 4 => Direction::West, + 5 => Direction::East, + _ => Direction::Down, + })) + } +} + +impl Write for ByteDirection { + unsafe fn write(&self, w: &mut Writer) { + unsafe { w.write_byte(self.0 as u8) } + } + + fn len_s(&self) -> usize { + 1 + } +} + impl<'a> Read<'a> for Direction { fn read(buf: &mut Reader<'a>) -> Result { Ok(match V21::read(buf)?.0 { diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index ca16393c..3874c692 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -132,7 +132,7 @@ packets! { ping_request = ping::GamePingRequest, place_recipe = game::PlaceRecipe, player_abilities = game::PlayerAbilities, - // player_action, + player_action = game::PlayerAction, // player_command, // player_input, // player_loaded, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 19df8c74..7698729a 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -5,7 +5,7 @@ use crate::{ ClickType, ContainerId, Difficulty, GameType, HashedStack, InteractionHand, MilliSeconds, }; use haya_collection::{List, Map}; -use haya_math::{BlockPosPacked, FVec3, Vec3}; +use haya_math::{BlockPosPacked, ByteDirection, Direction, FVec3, Vec3}; use minecraft_data::debug_subscription; use mser::Utf8; @@ -293,3 +293,26 @@ impl PlayerAbilitiesFlags { self.0 & Self::FLYING != 0 } } + +#[derive(Clone, Serialize, Deserialize)] +pub struct PlayerAction { + pub action: PlayerActionType, + pub pos: BlockPosPacked, + pub direction: ByteDirection, + #[mser(varint)] + pub sequence: u32, +} + +#[derive(Clone, Copy, Serialize, Deserialize)] +#[repr(u8)] +#[mser(varint)] +pub enum PlayerActionType { + StartDestroyBlock, + AbortDestroyBlock, + StopDestroyBlock, + DropAllItems, + DropItem, + ReleaseUseItem, + SwapItemWithOffhand, + Stab, +} From d0f7cd21841b13746656c6f9b647ab8029251ef0 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 20:57:33 +0900 Subject: [PATCH 42/67] packet player_command --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 3874c692..d8bc1369 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -133,7 +133,7 @@ packets! { place_recipe = game::PlaceRecipe, player_abilities = game::PlayerAbilities, player_action = game::PlayerAction, - // player_command, + player_command = game::PlayerCommand, // player_input, // player_loaded, // pong, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 7698729a..1a57bcf5 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -316,3 +316,25 @@ pub enum PlayerActionType { SwapItemWithOffhand, Stab, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct PlayerCommand { + #[mser(varint)] + pub id: u32, + pub action: PlayerCommandAction, + #[mser(varint)] + pub data: u32, +} + +#[derive(Clone, Copy, Serialize, Deserialize)] +#[repr(u8)] +#[mser(varint)] +pub enum PlayerCommandAction { + StopSleeping, + StartSprinting, + StopSprinting, + StartRidingJump, + StopRidingJump, + OpenInventory, + StartFallFlying, +} From 310460a24632fa6b88fcecb5059efa196faf6849 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 21:01:46 +0900 Subject: [PATCH 43/67] packet player_input --- haya_protocol/src/lib.rs | 13 +++++++++++++ haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 7 ++++++- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/haya_protocol/src/lib.rs b/haya_protocol/src/lib.rs index 3cf119f5..480fb818 100644 --- a/haya_protocol/src/lib.rs +++ b/haya_protocol/src/lib.rs @@ -872,6 +872,19 @@ pub struct HashedStack<'a> { pub components: HashedPatchMap<'a>, } +#[derive(Clone, Copy, Serialize, Deserialize)] +pub struct Input(pub u8); + +impl Input { + pub const FORWARD: u8 = 1; + pub const BACKWARD: u8 = 2; + pub const LEFT: u8 = 4; + pub const RIGHT: u8 = 8; + pub const JUMP: u8 = 16; + pub const SHIFT: u8 = 32; + pub const SPRINT: u8 = 64; +} + #[cfg(test)] mod tests { use super::*; diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index d8bc1369..4c8e5e7e 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -134,7 +134,7 @@ packets! { player_abilities = game::PlayerAbilities, player_action = game::PlayerAction, player_command = game::PlayerCommand, - // player_input, + player_input = game::PlayerInput, // player_loaded, // pong, // recipe_book_change_settings, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 1a57bcf5..459022b3 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -2,7 +2,7 @@ use crate::chat::{LastSeenMessagesUpdate, MessageSignature, RemoteChatSession}; use crate::command::ArgumentSignatures; use crate::crafting::RecipeDisplayId; use crate::{ - ClickType, ContainerId, Difficulty, GameType, HashedStack, InteractionHand, MilliSeconds, + ClickType, ContainerId, Difficulty, GameType, HashedStack, Input, InteractionHand, MilliSeconds, }; use haya_collection::{List, Map}; use haya_math::{BlockPosPacked, ByteDirection, Direction, FVec3, Vec3}; @@ -338,3 +338,8 @@ pub enum PlayerCommandAction { OpenInventory, StartFallFlying, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct PlayerInput { + pub input: Input, +} From 8743b8c47191abc3c4acb60a4ce5415def138348 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 21:02:22 +0900 Subject: [PATCH 44/67] packet player_loaded --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 4c8e5e7e..1b4087c7 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -135,7 +135,7 @@ packets! { player_action = game::PlayerAction, player_command = game::PlayerCommand, player_input = game::PlayerInput, - // player_loaded, + player_loaded = game::PlayerLoaded, // pong, // recipe_book_change_settings, // recipe_book_seen_recipe, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 459022b3..12d34a38 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -343,3 +343,6 @@ pub enum PlayerCommandAction { pub struct PlayerInput { pub input: Input, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct PlayerLoaded {} From aad3ed8170fe90824fcd15e9d8305115a1f43e86 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 21:05:15 +0900 Subject: [PATCH 45/67] packet pong --- haya_protocol/src/serverbound.rs | 4 ++-- haya_protocol/src/serverbound/common.rs | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 1b4087c7..5caa0e8c 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -82,7 +82,7 @@ packets! { custom_payload = common::ConfigurationCustomPayload<'_>, finish_configuration = configuration::FinishConfiguration, keep_alive = common::ConfigurationKeepAlive, - pong = common::Pong, + pong = common::ConfigurationPong, resource_pack = common::ResourcePack, select_known_packs = configuration::SelectKnownPacks<'_>, custom_click_action = common::CustomClickAction<'_>, @@ -136,7 +136,7 @@ packets! { player_command = game::PlayerCommand, player_input = game::PlayerInput, player_loaded = game::PlayerLoaded, - // pong, + pong = common::GamePong, // recipe_book_change_settings, // recipe_book_seen_recipe, // rename_item, diff --git a/haya_protocol/src/serverbound/common.rs b/haya_protocol/src/serverbound/common.rs index 421a6df1..8aa2214e 100644 --- a/haya_protocol/src/serverbound/common.rs +++ b/haya_protocol/src/serverbound/common.rs @@ -30,6 +30,12 @@ pub struct KeepAlive { pub id: u64, } +#[derive(Clone, Serialize, Deserialize)] +pub struct ConfigurationPong(pub Pong); + +#[derive(Clone, Serialize, Deserialize)] +pub struct GamePong(pub Pong); + #[derive(Clone, Serialize, Deserialize)] pub struct Pong { pub id: u32, From d94a58be190e3b106c1ea8c8e20f3de85f829bc1 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 21:11:53 +0900 Subject: [PATCH 46/67] packet recipe_book_change_settings --- haya_math/src/lib.rs | 2 +- haya_protocol/src/clientbound/game.rs | 6 +- haya_protocol/src/entity_data.rs | 5 +- haya_protocol/src/inventory.rs | 118 ++++++++++++++++++ haya_protocol/src/item_stack.rs | 3 +- .../item_stack/item_attribute_modifiers.rs | 3 +- haya_protocol/src/lib.rs | 109 +--------------- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 14 ++- 9 files changed, 141 insertions(+), 121 deletions(-) create mode 100644 haya_protocol/src/inventory.rs diff --git a/haya_math/src/lib.rs b/haya_math/src/lib.rs index c6d8909c..452bab40 100644 --- a/haya_math/src/lib.rs +++ b/haya_math/src/lib.rs @@ -567,7 +567,7 @@ pub struct ByteDirection(pub Direction); impl<'a> Read<'a> for ByteDirection { fn read(buf: &mut Reader<'a>) -> Result { - Ok(Self(match buf.read_byte() { + Ok(Self(match buf.read_byte()? { 1 => Direction::Up, 2 => Direction::North, 3 => Direction::South, diff --git a/haya_protocol/src/clientbound/game.rs b/haya_protocol/src/clientbound/game.rs index 961bfe53..995c685e 100644 --- a/haya_protocol/src/clientbound/game.rs +++ b/haya_protocol/src/clientbound/game.rs @@ -10,6 +10,7 @@ use crate::crafting::{ }; use crate::debug::{DebugSubscriptionEvent, DebugSubscriptionUpdate, RemoteDebugSampleType}; use crate::entity_data::EntityDataSerializer; +use crate::inventory::{ContainerId, EquipmentSlot, InteractionHand}; use crate::item_stack::OptionalItemStack; use crate::map::{MapDecoration, MapId, MapPatch}; use crate::minecart::MinecartStep; @@ -22,9 +23,8 @@ use crate::stat::Stat; use crate::trading::MerchantOffer; use crate::waypoint::TrackedWaypoint; use crate::{ - BitSet, ChatFormatting, Component, ContainerId, Difficulty, EntityAnchor, EquipmentSlot, - GameType, GlobalPos, HeightmapType, Holder, InteractionHand, OptionalGameType, Relatives, - RespawnData, V32List, WeightedList, + BitSet, ChatFormatting, Component, Difficulty, EntityAnchor, GameType, GlobalPos, + HeightmapType, Holder, OptionalGameType, Relatives, RespawnData, V32List, WeightedList, }; use alloc::vec::Vec; use haya_collection::{List, Map, capacity_fix}; diff --git a/haya_protocol/src/entity_data.rs b/haya_protocol/src/entity_data.rs index 714f644e..21036fec 100644 --- a/haya_protocol/src/entity_data.rs +++ b/haya_protocol/src/entity_data.rs @@ -2,15 +2,14 @@ use crate::entity::{ ArmadilloState, CopperGolemState, EntityReference, PaintingVariant, Pose, SnifferState, VillagerData, }; +use crate::inventory::HumanoidArm; use crate::item_stack::OptionalItemStack; use crate::profile::ResolvableProfile; use crate::registry::{ CatVariantRef, ChickenVariantRef, CowVariantRef, FrogVariantRef, PaintingVariantRef, PigVariantRef, WolfSoundVariantRef, WolfVariantRef, ZombieNautilusVariantRef, }; -use crate::{ - Component, GlobalPos, Holder, HumanoidArm, OptionalV32, Rotations, WeatheringCopperState, -}; +use crate::{Component, GlobalPos, Holder, OptionalV32, Rotations, WeatheringCopperState}; use haya_collection::List; use haya_math::{BlockPosPacked, Direction, FQuat, FVec3}; use minecraft_data::{block_state, particle_type}; diff --git a/haya_protocol/src/inventory.rs b/haya_protocol/src/inventory.rs new file mode 100644 index 00000000..b2def68f --- /dev/null +++ b/haya_protocol/src/inventory.rs @@ -0,0 +1,118 @@ +use crate::Translatable; + +#[derive(Clone, Copy, Serialize, Deserialize)] +#[repr(u8)] +#[mser(varint)] +pub enum HumanoidArm { + Left, + Right, +} + +impl HumanoidArm { + pub const fn translation_key(self) -> Translatable<'static> { + Translatable(match self { + Self::Left => "options.mainHand.left", + Self::Right => "options.mainHand.right", + }) + } + + pub const fn name(self) -> &'static str { + match self { + Self::Left => "left", + Self::Right => "right", + } + } +} + +#[derive(Clone, Copy, Serialize, Deserialize)] +pub struct ContainerId(#[mser(varint)] pub u32); + +#[derive(Clone, Copy, Serialize, Deserialize)] +#[repr(u8)] +#[mser(varint)] +pub enum EquipmentSlotGroup { + Any, + Mainhand, + Offhand, + Hand, + Feet, + Legs, + Chest, + Head, + Armor, + Body, + Saddle, +} + +impl EquipmentSlotGroup { + pub const fn name(self) -> &'static str { + match self { + Self::Any => "any", + Self::Mainhand => "mainhand", + Self::Offhand => "offhand", + Self::Hand => "hand", + Self::Feet => "feet", + Self::Legs => "legs", + Self::Chest => "chest", + Self::Head => "head", + Self::Armor => "armor", + Self::Body => "body", + Self::Saddle => "saddle", + } + } +} + +#[derive(Clone, Copy, Serialize, Deserialize)] +#[repr(u8)] +#[mser(varint)] +pub enum EquipmentSlot { + Mainhand, + Feet, + Legs, + Chest, + Head, + Offhand, + Body, + Saddle, +} + +impl EquipmentSlot { + pub const fn new(n: u8) -> Self { + if n > Self::Saddle as u8 { + Self::Mainhand + } else { + unsafe { core::mem::transmute::(n) } + } + } + + pub const fn name(self) -> &'static str { + match self { + Self::Mainhand => "mainhand", + Self::Feet => "feet", + Self::Legs => "legs", + Self::Chest => "chest", + Self::Head => "head", + Self::Offhand => "offhand", + Self::Body => "body", + Self::Saddle => "saddle", + } + } +} + +#[derive(Clone, Copy, Serialize, Deserialize)] +#[repr(u8)] +#[mser(varint)] +pub enum InteractionHand { + MainHand, + OffHand, +} + +#[derive(Clone, Copy, Serialize, Deserialize)] +#[repr(u8)] +#[mser(varint)] +pub enum RecipeBookType { + Crafting, + Furnace, + BlastFurnace, + Smoker, +} diff --git a/haya_protocol/src/item_stack.rs b/haya_protocol/src/item_stack.rs index 80cd1285..9ae28c2f 100644 --- a/haya_protocol/src/item_stack.rs +++ b/haya_protocol/src/item_stack.rs @@ -23,6 +23,7 @@ use crate::entity::{ ParrotVariant, RabbitVariant, SalmonVariant, TropicalFishPattern, }; use crate::food::FoodProperties; +use crate::inventory::EquipmentSlot; use crate::map::MapId; use crate::profile::ResolvableProfile; use crate::registry::{ @@ -32,7 +33,7 @@ use crate::registry::{ }; use crate::sound::SoundEvent; use crate::trim::{TrimMaterial, TrimPattern}; -use crate::{Component, DyeColor, EquipmentSlot, Filterable, Holder, HolderSet, LockCode, Rarity}; +use crate::{Component, DyeColor, Filterable, Holder, HolderSet, LockCode, Rarity}; use alloc::vec::Vec; use haya_collection::{List, Map, capacity_fix}; use haya_ident::{Ident, ResourceKey, TagKey}; diff --git a/haya_protocol/src/item_stack/item_attribute_modifiers.rs b/haya_protocol/src/item_stack/item_attribute_modifiers.rs index f512600d..bc7810fc 100644 --- a/haya_protocol/src/item_stack/item_attribute_modifiers.rs +++ b/haya_protocol/src/item_stack/item_attribute_modifiers.rs @@ -1,5 +1,6 @@ +use crate::Component; use crate::attribute::AttributeModifier; -use crate::{Component, EquipmentSlotGroup}; +use crate::inventory::EquipmentSlotGroup; use haya_collection::List; use minecraft_data::attribute; use mser::{Error, Read, Reader, V21, Write, Writer}; diff --git a/haya_protocol/src/lib.rs b/haya_protocol/src/lib.rs index 480fb818..fdaea829 100644 --- a/haya_protocol/src/lib.rs +++ b/haya_protocol/src/lib.rs @@ -1,5 +1,6 @@ #![no_std] +use crate::inventory::HumanoidArm; use alloc::vec::Vec; use haya_collection::{List, Map, capacity_fix}; use haya_ident::{Ident, ResourceKey}; @@ -21,6 +22,7 @@ pub mod entity; pub mod entity_data; pub mod food; pub mod game_event; +pub mod inventory; pub mod item_stack; pub mod level_event; pub mod map; @@ -168,30 +170,6 @@ impl ChatVisibility { } } -#[derive(Clone, Copy, Serialize, Deserialize)] -#[repr(u8)] -#[mser(varint)] -pub enum HumanoidArm { - Left, - Right, -} - -impl HumanoidArm { - pub const fn translation_key(self) -> Translatable<'static> { - Translatable(match self { - Self::Left => "options.mainHand.left", - Self::Right => "options.mainHand.right", - }) - } - - pub const fn name(self) -> &'static str { - match self { - Self::Left => "left", - Self::Right => "right", - } - } -} - #[derive(Clone, Copy, Serialize, Deserialize)] #[repr(u8)] #[mser(varint)] @@ -251,9 +229,6 @@ impl Difficulty { } } -#[derive(Clone, Copy, Serialize, Deserialize)] -pub struct ContainerId(#[mser(varint)] pub u32); - #[derive(Clone, Copy, Serialize, Deserialize)] #[repr(u8)] #[mser(varint)] @@ -334,78 +309,6 @@ pub enum Holder { Direct(T), } -#[derive(Clone, Copy, Serialize, Deserialize)] -#[repr(u8)] -#[mser(varint)] -pub enum EquipmentSlotGroup { - Any, - Mainhand, - Offhand, - Hand, - Feet, - Legs, - Chest, - Head, - Armor, - Body, - Saddle, -} - -impl EquipmentSlotGroup { - pub const fn name(self) -> &'static str { - match self { - Self::Any => "any", - Self::Mainhand => "mainhand", - Self::Offhand => "offhand", - Self::Hand => "hand", - Self::Feet => "feet", - Self::Legs => "legs", - Self::Chest => "chest", - Self::Head => "head", - Self::Armor => "armor", - Self::Body => "body", - Self::Saddle => "saddle", - } - } -} - -#[derive(Clone, Copy, Serialize, Deserialize)] -#[repr(u8)] -#[mser(varint)] -pub enum EquipmentSlot { - Mainhand, - Feet, - Legs, - Chest, - Head, - Offhand, - Body, - Saddle, -} - -impl EquipmentSlot { - pub const fn new(n: u8) -> Self { - if n > Self::Saddle as u8 { - Self::Mainhand - } else { - unsafe { core::mem::transmute::(n) } - } - } - - pub const fn name(self) -> &'static str { - match self { - Self::Mainhand => "mainhand", - Self::Feet => "feet", - Self::Legs => "legs", - Self::Chest => "chest", - Self::Head => "head", - Self::Offhand => "offhand", - Self::Body => "body", - Self::Saddle => "saddle", - } - } -} - #[derive(Clone, Copy, Serialize, Deserialize)] #[repr(u8)] #[mser(varint)] @@ -615,14 +518,6 @@ pub struct GlobalPos<'a> { pub pos: BlockPosPacked, } -#[derive(Clone, Copy, Serialize, Deserialize)] -#[repr(u8)] -#[mser(varint)] -pub enum InteractionHand { - MainHand, - OffHand, -} - #[derive(Clone, Copy, Serialize, Deserialize)] #[repr(u8)] #[mser(varint)] diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 5caa0e8c..c1b33038 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -137,7 +137,7 @@ packets! { player_input = game::PlayerInput, player_loaded = game::PlayerLoaded, pong = common::GamePong, - // recipe_book_change_settings, + recipe_book_change_settings = game::RecipeBookChangeSettings, // recipe_book_seen_recipe, // rename_item, // resource_pack, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 12d34a38..199d9042 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -1,11 +1,10 @@ use crate::chat::{LastSeenMessagesUpdate, MessageSignature, RemoteChatSession}; use crate::command::ArgumentSignatures; use crate::crafting::RecipeDisplayId; -use crate::{ - ClickType, ContainerId, Difficulty, GameType, HashedStack, Input, InteractionHand, MilliSeconds, -}; +use crate::inventory::{ContainerId, InteractionHand, RecipeBookType}; +use crate::{ClickType, Difficulty, GameType, HashedStack, Input, MilliSeconds}; use haya_collection::{List, Map}; -use haya_math::{BlockPosPacked, ByteDirection, Direction, FVec3, Vec3}; +use haya_math::{BlockPosPacked, ByteDirection, FVec3, Vec3}; use minecraft_data::debug_subscription; use mser::Utf8; @@ -346,3 +345,10 @@ pub struct PlayerInput { #[derive(Clone, Serialize, Deserialize)] pub struct PlayerLoaded {} + +#[derive(Clone, Serialize, Deserialize)] +pub struct RecipeBookChangeSettings { + pub book_type: RecipeBookType, + pub is_open: bool, + pub is_filtering: bool, +} From a5071b491eb557dc4a4ba415ad29bcfaf95e8d27 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 21:18:05 +0900 Subject: [PATCH 47/67] packet recipe_book_seen_recipe --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index c1b33038..59c23a37 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -138,7 +138,7 @@ packets! { player_loaded = game::PlayerLoaded, pong = common::GamePong, recipe_book_change_settings = game::RecipeBookChangeSettings, - // recipe_book_seen_recipe, + recipe_book_seen_recipe = game::RecipeBookSeenRecipe, // rename_item, // resource_pack, // seen_advancements, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 199d9042..30e70d9b 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -352,3 +352,8 @@ pub struct RecipeBookChangeSettings { pub is_open: bool, pub is_filtering: bool, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct RecipeBookSeenRecipe { + pub recipe: RecipeDisplayId, +} From 729194321731c726da10fd6bc90ff07d4899d449 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 21:19:33 +0900 Subject: [PATCH 48/67] packet rename_item --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 59c23a37..e6904134 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -139,7 +139,7 @@ packets! { pong = common::GamePong, recipe_book_change_settings = game::RecipeBookChangeSettings, recipe_book_seen_recipe = game::RecipeBookSeenRecipe, - // rename_item, + rename_item = game::RenameItem<'_>, // resource_pack, // seen_advancements, // select_trade, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 30e70d9b..ddb0c218 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -357,3 +357,8 @@ pub struct RecipeBookChangeSettings { pub struct RecipeBookSeenRecipe { pub recipe: RecipeDisplayId, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct RenameItem<'a> { + pub name: Utf8<'a>, +} From 18ae84087b6ad3bbd5e38f6f04a5e41cfcf780f0 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 21:26:54 +0900 Subject: [PATCH 49/67] packet resource_pack --- haya_protocol/src/serverbound.rs | 4 ++-- haya_protocol/src/serverbound/common.rs | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index e6904134..c8c6ecdf 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -83,7 +83,7 @@ packets! { finish_configuration = configuration::FinishConfiguration, keep_alive = common::ConfigurationKeepAlive, pong = common::ConfigurationPong, - resource_pack = common::ResourcePack, + resource_pack = common::ConfigurationResourcePack, select_known_packs = configuration::SelectKnownPacks<'_>, custom_click_action = common::CustomClickAction<'_>, accept_code_of_conduct = configuration::AcceptCodeOfConduct, @@ -140,7 +140,7 @@ packets! { recipe_book_change_settings = game::RecipeBookChangeSettings, recipe_book_seen_recipe = game::RecipeBookSeenRecipe, rename_item = game::RenameItem<'_>, - // resource_pack, + resource_pack = common::GameResourcePack, // seen_advancements, // select_trade, // set_beacon, diff --git a/haya_protocol/src/serverbound/common.rs b/haya_protocol/src/serverbound/common.rs index 8aa2214e..bba9630b 100644 --- a/haya_protocol/src/serverbound/common.rs +++ b/haya_protocol/src/serverbound/common.rs @@ -41,6 +41,12 @@ pub struct Pong { pub id: u32, } +#[derive(Clone, Serialize, Deserialize)] +pub struct ConfigurationResourcePack(pub ResourcePack); + +#[derive(Clone, Serialize, Deserialize)] +pub struct GameResourcePack(pub ResourcePack); + #[derive(Clone, Serialize, Deserialize)] pub struct ResourcePack { pub id: Uuid, From 42363e36eb40d59616541b31ec8eb93630dd1a59 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 21:33:17 +0900 Subject: [PATCH 50/67] packet seen_advancements --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index c8c6ecdf..9af1a506 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -141,7 +141,7 @@ packets! { recipe_book_seen_recipe = game::RecipeBookSeenRecipe, rename_item = game::RenameItem<'_>, resource_pack = common::GameResourcePack, - // seen_advancements, + seen_advancements = game::SeenAdvancements<'_>, // select_trade, // set_beacon, // set_carried_item, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index ddb0c218..562341db 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -4,6 +4,7 @@ use crate::crafting::RecipeDisplayId; use crate::inventory::{ContainerId, InteractionHand, RecipeBookType}; use crate::{ClickType, Difficulty, GameType, HashedStack, Input, MilliSeconds}; use haya_collection::{List, Map}; +use haya_ident::Ident; use haya_math::{BlockPosPacked, ByteDirection, FVec3, Vec3}; use minecraft_data::debug_subscription; use mser::Utf8; @@ -362,3 +363,23 @@ pub struct RecipeBookSeenRecipe { pub struct RenameItem<'a> { pub name: Utf8<'a>, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct SeenAdvancements<'a> { + pub action: SeenAdvancementsAction<'a>, +} + +#[derive(Clone, Serialize, Deserialize)] +#[mser(header = SeenAdvancementsType, camel_case)] +pub enum SeenAdvancementsAction<'a> { + OpenedTab { tab: Ident<'a> }, + ClosedScreen, +} + +#[derive(Clone, Copy, Serialize, Deserialize)] +#[repr(u8)] +#[mser(varint)] +pub enum SeenAdvancementsType { + OpenedTab, + ClosedScreen, +} From 831521b270152cd29e1a5d1a1e240b3efd30c9bc Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 21:35:10 +0900 Subject: [PATCH 51/67] packet select_trade --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 9af1a506..9ff9a52f 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -142,7 +142,7 @@ packets! { rename_item = game::RenameItem<'_>, resource_pack = common::GameResourcePack, seen_advancements = game::SeenAdvancements<'_>, - // select_trade, + select_trade = game::SelectTrade, // set_beacon, // set_carried_item, // set_command_block, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 562341db..6c25a3fc 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -383,3 +383,9 @@ pub enum SeenAdvancementsType { OpenedTab, ClosedScreen, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct SelectTrade { + #[mser(varint)] + pub item: u32, +} From 7a02ff44681de7bf7b7e1f5ccb031e5b899851c6 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 21:38:03 +0900 Subject: [PATCH 52/67] packet set_beacon --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 9ff9a52f..e6ed9052 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -143,7 +143,7 @@ packets! { resource_pack = common::GameResourcePack, seen_advancements = game::SeenAdvancements<'_>, select_trade = game::SelectTrade, - // set_beacon, + set_beacon = game::SetBeacon, // set_carried_item, // set_command_block, // set_command_minecart, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 6c25a3fc..3fcae01e 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -6,7 +6,7 @@ use crate::{ClickType, Difficulty, GameType, HashedStack, Input, MilliSeconds}; use haya_collection::{List, Map}; use haya_ident::Ident; use haya_math::{BlockPosPacked, ByteDirection, FVec3, Vec3}; -use minecraft_data::debug_subscription; +use minecraft_data::{debug_subscription, mob_effect}; use mser::Utf8; #[derive(Clone, Serialize, Deserialize)] @@ -389,3 +389,9 @@ pub struct SelectTrade { #[mser(varint)] pub item: u32, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct SetBeacon { + pub primary: Option, + pub secondary: Option, +} From d6321668fdf2676c66e8b73cb7c3f70db16916bb Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 21:39:51 +0900 Subject: [PATCH 53/67] packet set_carried_item --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index e6ed9052..bbfcca89 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -144,7 +144,7 @@ packets! { seen_advancements = game::SeenAdvancements<'_>, select_trade = game::SelectTrade, set_beacon = game::SetBeacon, - // set_carried_item, + set_carried_item = game::SetCarriedItem, // set_command_block, // set_command_minecart, // set_creative_mode_slot, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 3fcae01e..9aed87d4 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -395,3 +395,8 @@ pub struct SetBeacon { pub primary: Option, pub secondary: Option, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct SetCarriedItem { + pub slot: u16, +} From 8001838b3abe6df8e98d25b4c0a117a5261e4758 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 21:49:56 +0900 Subject: [PATCH 54/67] packet set_command_block --- haya_protocol/src/lib.rs | 9 +++++++++ haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 21 ++++++++++++++++++++- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/haya_protocol/src/lib.rs b/haya_protocol/src/lib.rs index fdaea829..bb2a0bfa 100644 --- a/haya_protocol/src/lib.rs +++ b/haya_protocol/src/lib.rs @@ -780,6 +780,15 @@ impl Input { pub const SPRINT: u8 = 64; } +#[derive(Clone, Copy, Serialize, Deserialize)] +#[repr(u8)] +#[mser(varint)] +pub enum CommandBlockEntityMode { + Sequence, + Auto, + Redstone, +} + #[cfg(test)] mod tests { use super::*; diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index bbfcca89..2253e7d9 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -145,7 +145,7 @@ packets! { select_trade = game::SelectTrade, set_beacon = game::SetBeacon, set_carried_item = game::SetCarriedItem, - // set_command_block, + set_command_block = game::SetCommandBlock<'_>, // set_command_minecart, // set_creative_mode_slot, // set_jigsaw_block, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 9aed87d4..908ec433 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -2,7 +2,9 @@ use crate::chat::{LastSeenMessagesUpdate, MessageSignature, RemoteChatSession}; use crate::command::ArgumentSignatures; use crate::crafting::RecipeDisplayId; use crate::inventory::{ContainerId, InteractionHand, RecipeBookType}; -use crate::{ClickType, Difficulty, GameType, HashedStack, Input, MilliSeconds}; +use crate::{ + ClickType, CommandBlockEntityMode, Difficulty, GameType, HashedStack, Input, MilliSeconds, +}; use haya_collection::{List, Map}; use haya_ident::Ident; use haya_math::{BlockPosPacked, ByteDirection, FVec3, Vec3}; @@ -400,3 +402,20 @@ pub struct SetBeacon { pub struct SetCarriedItem { pub slot: u16, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct SetCommandBlock<'a> { + pub pos: BlockPosPacked, + pub command: Utf8<'a>, + pub mode: CommandBlockEntityMode, + pub flags: SetCommandBlockFlags, +} + +#[derive(Clone, Serialize, Deserialize)] +pub struct SetCommandBlockFlags(pub u8); + +impl SetCommandBlockFlags { + pub const TRACK_OUTPUT: u8 = 1; + pub const CONDITIONAL: u8 = 2; + pub const AUTOMATIC: u8 = 4; +} From d55b9442e98c144c49c26c87ba48683ac2b7ca4c Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 21:56:55 +0900 Subject: [PATCH 55/67] packet set_command_minecart --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 2253e7d9..1fd2c4a1 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -146,7 +146,7 @@ packets! { set_beacon = game::SetBeacon, set_carried_item = game::SetCarriedItem, set_command_block = game::SetCommandBlock<'_>, - // set_command_minecart, + set_command_minecart = game::SetCommandMinecart<'_>, // set_creative_mode_slot, // set_jigsaw_block, // set_structure_block, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 908ec433..80911913 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -419,3 +419,11 @@ impl SetCommandBlockFlags { pub const CONDITIONAL: u8 = 2; pub const AUTOMATIC: u8 = 4; } + +#[derive(Clone, Serialize, Deserialize)] +pub struct SetCommandMinecart<'a> { + #[mser(varint)] + pub entity: u32, + pub command: Utf8<'a>, + pub track_output: bool, +} From eb67cf18241c2b2961e82cd401dc789498440a96 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 22:04:12 +0900 Subject: [PATCH 56/67] packet set_creative_mode_slot --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 1fd2c4a1..d4c09ec5 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -147,7 +147,7 @@ packets! { set_carried_item = game::SetCarriedItem, set_command_block = game::SetCommandBlock<'_>, set_command_minecart = game::SetCommandMinecart<'_>, - // set_creative_mode_slot, + set_creative_mode_slot = game::SetCreativeModeSlot<'_>, // set_jigsaw_block, // set_structure_block, // set_test_block, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 80911913..7e9e7460 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -9,7 +9,7 @@ use haya_collection::{List, Map}; use haya_ident::Ident; use haya_math::{BlockPosPacked, ByteDirection, FVec3, Vec3}; use minecraft_data::{debug_subscription, mob_effect}; -use mser::Utf8; +use mser::{Rest, Utf8}; #[derive(Clone, Serialize, Deserialize)] pub struct AcceptTeleportation { @@ -427,3 +427,10 @@ pub struct SetCommandMinecart<'a> { pub command: Utf8<'a>, pub track_output: bool, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct SetCreativeModeSlot<'a> { + pub slot_num: u16, + // pub item_stack: OptionalItemStack<'a>, + pub item_stack: Rest<'a>, +} From d178acc913f593c388d4b6be734a65b770311be9 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 22:19:56 +0900 Subject: [PATCH 57/67] packet set_jigsaw_block --- haya_protocol/src/lib.rs | 44 +++++++++++++++++++++++++++ haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 17 ++++++++++- 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/haya_protocol/src/lib.rs b/haya_protocol/src/lib.rs index bb2a0bfa..71408746 100644 --- a/haya_protocol/src/lib.rs +++ b/haya_protocol/src/lib.rs @@ -789,6 +789,50 @@ pub enum CommandBlockEntityMode { Redstone, } +#[derive(Serialize, Deserialize, Clone, Copy)] +#[repr(u8)] +#[mser(varint)] +pub enum JointType { + Rollable, + Aligned, +} + +#[derive(Clone, Copy)] +pub struct JointTypeName(pub JointType); + +impl<'a> Read<'a> for JointTypeName { + fn read(buf: &mut Reader<'a>) -> Result { + let a: Utf8 = Utf8::read(buf)?; + Ok(match a.0 { + "rollable" => Self(JointType::Rollable), + _ => Self(JointType::Aligned), + }) + } +} + +impl Write for JointTypeName { + unsafe fn write(&self, w: &mut Writer) { + unsafe { + let a: Utf8 = Utf8(self.0.name()); + a.write(w); + } + } + + fn len_s(&self) -> usize { + let a: Utf8 = Utf8(self.0.name()); + a.len_s() + } +} + +impl JointType { + pub const fn name(self) -> &'static str { + match self { + Self::Rollable => "rollable", + Self::Aligned => "aligned", + } + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index d4c09ec5..e6f715b7 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -148,7 +148,7 @@ packets! { set_command_block = game::SetCommandBlock<'_>, set_command_minecart = game::SetCommandMinecart<'_>, set_creative_mode_slot = game::SetCreativeModeSlot<'_>, - // set_jigsaw_block, + set_jigsaw_block = game::SetJigsawBlock<'_>, // set_structure_block, // set_test_block, // sign_update, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 7e9e7460..86bcda3f 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -3,7 +3,8 @@ use crate::command::ArgumentSignatures; use crate::crafting::RecipeDisplayId; use crate::inventory::{ContainerId, InteractionHand, RecipeBookType}; use crate::{ - ClickType, CommandBlockEntityMode, Difficulty, GameType, HashedStack, Input, MilliSeconds, + ClickType, CommandBlockEntityMode, Difficulty, GameType, HashedStack, Input, JointTypeName, + MilliSeconds, }; use haya_collection::{List, Map}; use haya_ident::Ident; @@ -434,3 +435,17 @@ pub struct SetCreativeModeSlot<'a> { // pub item_stack: OptionalItemStack<'a>, pub item_stack: Rest<'a>, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct SetJigsawBlock<'a> { + pub pos: BlockPosPacked, + pub name: Ident<'a>, + pub target: Ident<'a>, + pub pool: Ident<'a>, + pub final_state: Utf8<'a>, + pub joint: JointTypeName, + #[mser(varint)] + pub selection_priority: u32, + #[mser(varint)] + pub placement_priority: u32, +} From ec02907aef0df84389271a87da313a9797ff3f65 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 22:54:38 +0900 Subject: [PATCH 58/67] packet set_structure_block --- haya_protocol/src/lib.rs | 71 +++++++++++++++++++++++++++ haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 33 ++++++++++++- 3 files changed, 104 insertions(+), 2 deletions(-) diff --git a/haya_protocol/src/lib.rs b/haya_protocol/src/lib.rs index 71408746..3a5957e4 100644 --- a/haya_protocol/src/lib.rs +++ b/haya_protocol/src/lib.rs @@ -833,6 +833,77 @@ impl JointType { } } +#[derive(Clone, Copy, Serialize, Deserialize)] +#[repr(u8)] +#[mser(varint)] +pub enum StructureUpdateType { + UpdateData, + SaveArea, + LoadArea, + ScanArea, +} + +#[derive(Clone, Copy, Serialize, Deserialize)] +#[repr(u8)] +#[mser(varint)] +pub enum StructureMode { + Save, + Load, + Corner, + Data, +} + +impl StructureMode { + pub const fn name(self) -> &'static str { + match self { + Self::Save => "save", + Self::Load => "load", + Self::Corner => "corner", + Self::Data => "data", + } + } +} + +#[derive(Clone, Copy, Serialize, Deserialize)] +#[repr(u8)] +#[mser(varint)] +pub enum Mirror { + None, + LeftRight, + FrontBack, +} + +impl Mirror { + pub const fn name(self) -> &'static str { + match self { + Self::None => "none", + Self::LeftRight => "left_right", + Self::FrontBack => "front_back", + } + } +} + +#[derive(Clone, Copy, Serialize, Deserialize)] +#[repr(u8)] +#[mser(varint)] +pub enum Rotation { + None, + Clockwise90, + Clockwise180, + Counterclockwise90, +} + +impl Rotation { + pub const fn name(self) -> &'static str { + match self { + Self::None => "none", + Self::Clockwise90 => "clockwise_90", + Self::Clockwise180 => "180", + Self::Counterclockwise90 => "counterclockwise_90", + } + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index e6f715b7..50ed403c 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -149,7 +149,7 @@ packets! { set_command_minecart = game::SetCommandMinecart<'_>, set_creative_mode_slot = game::SetCreativeModeSlot<'_>, set_jigsaw_block = game::SetJigsawBlock<'_>, - // set_structure_block, + set_structure_block = game::SetStructureBlock<'_>, // set_test_block, // sign_update, // swing, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 86bcda3f..a3e8aa11 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -4,7 +4,7 @@ use crate::crafting::RecipeDisplayId; use crate::inventory::{ContainerId, InteractionHand, RecipeBookType}; use crate::{ ClickType, CommandBlockEntityMode, Difficulty, GameType, HashedStack, Input, JointTypeName, - MilliSeconds, + MilliSeconds, Mirror, Rotation, StructureMode, StructureUpdateType, }; use haya_collection::{List, Map}; use haya_ident::Ident; @@ -449,3 +449,34 @@ pub struct SetJigsawBlock<'a> { #[mser(varint)] pub placement_priority: u32, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct SetStructureBlock<'a> { + pub pos: BlockPosPacked, + pub update_type: StructureUpdateType, + pub mode: StructureMode, + pub name: Utf8<'a>, + pub offset_x: i8, + pub offset_y: i8, + pub offset_z: i8, + pub size_x: i8, + pub size_y: i8, + pub size_z: i8, + pub mirror: Mirror, + pub rotation: Rotation, + pub data: Utf8<'a, 128>, + pub integrity: f32, + #[mser(varint)] + pub seed: u64, + pub flags: SetStructureBlockFlags, +} + +#[derive(Clone, Copy, Serialize, Deserialize)] +pub struct SetStructureBlockFlags(pub u8); + +impl SetStructureBlockFlags { + pub const IGNORE_ENTITIES: u8 = 1; + pub const SHOW_AIR: u8 = 2; + pub const SHOW_BOUNDING_BOX: u8 = 4; + pub const STRICT: u8 = 8; +} From 856c85f0419a645ac3450710c2e2670a6728263a Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 22:58:39 +0900 Subject: [PATCH 59/67] packet set_test_block --- haya_protocol/src/lib.rs | 21 +++++++++++++++++++++ haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 9 ++++++++- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/haya_protocol/src/lib.rs b/haya_protocol/src/lib.rs index 3a5957e4..44ac8b61 100644 --- a/haya_protocol/src/lib.rs +++ b/haya_protocol/src/lib.rs @@ -904,6 +904,27 @@ impl Rotation { } } +#[derive(Clone, Copy, Serialize, Deserialize)] +#[repr(u8)] +#[mser(varint)] +pub enum TestBlockMode { + Start, + Log, + Fail, + Accept, +} + +impl TestBlockMode { + pub const fn name(self) -> &'static str { + match self { + Self::Start => "start", + Self::Log => "log", + Self::Fail => "fail", + Self::Accept => "accept", + } + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 50ed403c..2ca069b7 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -150,7 +150,7 @@ packets! { set_creative_mode_slot = game::SetCreativeModeSlot<'_>, set_jigsaw_block = game::SetJigsawBlock<'_>, set_structure_block = game::SetStructureBlock<'_>, - // set_test_block, + set_test_block = game::SetTestBlock<'_>, // sign_update, // swing, // teleport_to_entity, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index a3e8aa11..3e943ad5 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -4,7 +4,7 @@ use crate::crafting::RecipeDisplayId; use crate::inventory::{ContainerId, InteractionHand, RecipeBookType}; use crate::{ ClickType, CommandBlockEntityMode, Difficulty, GameType, HashedStack, Input, JointTypeName, - MilliSeconds, Mirror, Rotation, StructureMode, StructureUpdateType, + MilliSeconds, Mirror, Rotation, StructureMode, StructureUpdateType, TestBlockMode, }; use haya_collection::{List, Map}; use haya_ident::Ident; @@ -480,3 +480,10 @@ impl SetStructureBlockFlags { pub const SHOW_BOUNDING_BOX: u8 = 4; pub const STRICT: u8 = 8; } + +#[derive(Clone, Serialize, Deserialize)] +pub struct SetTestBlock<'a> { + pub position: BlockPosPacked, + pub mode: TestBlockMode, + pub message: Utf8<'a>, +} From 78c4f0d1068257d015b4def9bdb5fa328fa2e331 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 23:01:39 +0900 Subject: [PATCH 60/67] packet sign_update --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 2ca069b7..f749109c 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -151,7 +151,7 @@ packets! { set_jigsaw_block = game::SetJigsawBlock<'_>, set_structure_block = game::SetStructureBlock<'_>, set_test_block = game::SetTestBlock<'_>, - // sign_update, + sign_update = game::SignUpdate<'_>, // swing, // teleport_to_entity, // test_instance_block_action, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 3e943ad5..482b84ea 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -487,3 +487,13 @@ pub struct SetTestBlock<'a> { pub mode: TestBlockMode, pub message: Utf8<'a>, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct SignUpdate<'a> { + pub pos: BlockPosPacked, + pub is_front_text: bool, + pub line1: Utf8<'a, 384>, + pub line2: Utf8<'a, 384>, + pub line3: Utf8<'a, 384>, + pub line4: Utf8<'a, 384>, +} From db8d53595f6857fbb1429dae9b3ac13dbaa941b3 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 23:02:35 +0900 Subject: [PATCH 61/67] packet swing --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index f749109c..2f76e036 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -152,7 +152,7 @@ packets! { set_structure_block = game::SetStructureBlock<'_>, set_test_block = game::SetTestBlock<'_>, sign_update = game::SignUpdate<'_>, - // swing, + swing = game::Swing, // teleport_to_entity, // test_instance_block_action, // use_item_on, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 482b84ea..20399c2d 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -497,3 +497,8 @@ pub struct SignUpdate<'a> { pub line3: Utf8<'a, 384>, pub line4: Utf8<'a, 384>, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct Swing { + pub hand: InteractionHand, +} From 655e6a93d74d985d9b8334bbae757449929fff2d Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sun, 3 May 2026 23:04:04 +0900 Subject: [PATCH 62/67] packet teleport_to_entity --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 2f76e036..7a9d21ef 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -153,7 +153,7 @@ packets! { set_test_block = game::SetTestBlock<'_>, sign_update = game::SignUpdate<'_>, swing = game::Swing, - // teleport_to_entity, + teleport_to_entity = game::TeleportToEntity, // test_instance_block_action, // use_item_on, // use_item, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 20399c2d..cbec756c 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -11,6 +11,7 @@ use haya_ident::Ident; use haya_math::{BlockPosPacked, ByteDirection, FVec3, Vec3}; use minecraft_data::{debug_subscription, mob_effect}; use mser::{Rest, Utf8}; +use uuid::Uuid; #[derive(Clone, Serialize, Deserialize)] pub struct AcceptTeleportation { @@ -502,3 +503,8 @@ pub struct SignUpdate<'a> { pub struct Swing { pub hand: InteractionHand, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct TeleportToEntity { + pub uuid: Uuid, +} From 2a2a8d9a9898e5d7a5356ade0fe9ca975bf9e377 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Mon, 4 May 2026 17:12:55 +0900 Subject: [PATCH 63/67] add hashbrown --- Cargo.lock | 7 + haya_palette/Cargo.toml | 2 + haya_palette/src/chunk.rs | 449 +++++--------------------------------- haya_palette/src/lib.rs | 16 +- 4 files changed, 70 insertions(+), 404 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3df73ba4..03fc570f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,6 +19,12 @@ dependencies = [ "wasi", ] +[[package]] +name = "hashbrown" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" + [[package]] name = "haya_collection" version = "0.4.0" @@ -70,6 +76,7 @@ dependencies = [ name = "haya_palette" version = "0.5.0" dependencies = [ + "hashbrown", "minecraft_data", "mser", ] diff --git a/haya_palette/Cargo.toml b/haya_palette/Cargo.toml index 3256bbe0..5f345993 100644 --- a/haya_palette/Cargo.toml +++ b/haya_palette/Cargo.toml @@ -10,3 +10,5 @@ edition.workspace = true [dependencies] mser = { workspace = true } minecraft_data = { workspace = true } + +hashbrown = { version = "0", default-features = false } diff --git a/haya_palette/src/chunk.rs b/haya_palette/src/chunk.rs index 31966d32..e5fee5d9 100644 --- a/haya_palette/src/chunk.rs +++ b/haya_palette/src/chunk.rs @@ -1,6 +1,7 @@ use crate::Palette; use alloc::vec::Vec; -use core::iter::FusedIterator; +use hashbrown::HashTable; +use mser::cold_path; const BLOCK_PER_CHUNK: usize = 4 * 4 * 4; const INDIRECT4_PER_CHUNK: usize = BLOCK_PER_CHUNK / 2; @@ -29,36 +30,52 @@ pub struct ChunkCache { pub direct: Vec>, pub indirect2: Vec>, pub indirect4: Vec>, - pub chunks: Int64Map, + pub chunks: HashTable<(u64, u64)>, pub direct_key: Vec, pub indirect4_key: Vec, pub indirect2_key: Vec, pub single_key: Vec, } +impl Default for ChunkCache { + fn default() -> Self { + Self::new() + } +} + impl ChunkCache { - pub fn get(&self, x: i32, y: i32, z: i32) -> Option { + pub const fn new() -> Self { + Self { + direct: Vec::new(), + indirect2: Vec::new(), + indirect4: Vec::new(), + chunks: HashTable::new(), + direct_key: Vec::new(), + indirect4_key: Vec::new(), + indirect2_key: Vec::new(), + single_key: Vec::new(), + } + } + + pub fn get_block(&self, x: i32, y: i32, z: i32) -> T { let j = ((x & 3) | ((y & 3) << 2) | ((z & 3) << 4)) as usize; - let sx = ((x >> 2) & 0x3FF_FFFF) as i64; - let sy = ((y >> 2) & 0xFFF) as i64; - let sz = ((z >> 2) & 0x3FF_FFFF) as i64; - let i = ((sx << 38) | (sz << 12) | sy) as u64; - let t = match self.chunks.get(i) { - Some(t) => t, + let chunk = pack(x >> 2, y >> 2, z >> 2); + let t = match self.chunks.find(mix(chunk), |x| x.0 == chunk) { + Some(t) => t.1, None => { - mser::cold_path(); - return None; + cold_path(); + return T::default(); } }; let n = (t & INDEX_MASK) as usize; let ty = t >> 62; unsafe { - Some(match ty { + match ty { 3 => T::from_id(n as u32), 2 => self.indirect2.get_unchecked(n).get(j), 1 => self.indirect4.get_unchecked(n).get(j), _ => *self.direct.get_unchecked(n).data.get_unchecked(j), - }) + } } } } @@ -83,393 +100,27 @@ impl Indirect4 { } } -fn mix(x: u64, mask: usize) -> usize { - (U64_PRIME_MAX.wrapping_mul(x) as usize) & mask -} - -const U64_PRIME_MAX: u64 = u64::MAX - 58; - -#[derive(Clone, Copy)] -struct Slot(u64, u64); - -impl Slot { - const EMPTY: Self = Self(u64::MAX, u64::MAX); - - fn is_empty(self) -> bool { - self.0 == u64::MAX - } -} - -#[derive(Clone)] -pub struct Int64Map { - slots: Vec, - mask: usize, - len: usize, -} - -impl Int64Map { - pub fn with_capacity(capacity: usize) -> Self { - let size = capacity.next_power_of_two(); - let mask = size - 1; - let slots = alloc::vec![Slot::EMPTY; size]; - Self { - slots, - len: 0, - mask, - } - } - - pub fn reserve(&mut self, additional: usize) { - let capacity = self.len + additional; - while self.mask < capacity { - self.rehash(); - } - } - - pub fn insert(&mut self, key: u64, value: u64) -> Option { - debug_assert_ne!(key, u64::MAX); - while self.len * 4 > self.slots.len() * 3 { - self.rehash(); - } - let mut i = mix(key, self.mask); - loop { - let slot = unsafe { self.slots.get_unchecked_mut(i) }; - if slot.is_empty() { - *slot = Slot(key, value); - self.len += 1; - return None; - } - if slot.0 == key { - let old = slot.1; - *slot = Slot(key, value); - return Some(old); - } - i = (i + 1) & self.mask; - } - } - - pub fn get(&self, key: u64) -> Option { - let mut i = mix(key, self.mask); - loop { - let slot = unsafe { self.slots.get_unchecked(i) }; - if slot.0 == key { - return Some(slot.1); - } - if slot.is_empty() { - return None; - } - i = (i + 1) & self.mask; - } - } - - pub fn get_mut(&mut self, key: u64) -> Option<&mut u64> { - let mut i = mix(key, self.mask); - loop { - let slot = unsafe { self.slots.get_unchecked_mut(i) }; - if slot.0 == key { - return Some(unsafe { &mut self.slots.get_unchecked_mut(i).1 }); - } - if slot.is_empty() { - return None; - } - i = (i + 1) & self.mask; - } - } - - pub fn remove(&mut self, key: u64) -> Option { - let mut i = mix(key, self.mask); - let mut slot = unsafe { self.slots.get_unchecked_mut(i) }; - loop { - if slot.0 == key { - break; - } - if slot.is_empty() { - return None; - } - i = (i + 1) & self.mask; - slot = unsafe { self.slots.get_unchecked_mut(i) }; - } - self.len -= 1; - let v = slot.1; - *slot = Slot::EMPTY; - let mut j = (i + 1) & self.mask; - loop { - let v = unsafe { *self.slots.get_unchecked(j) }; - if v.is_empty() { - break; - } - let natural = mix(v.0, self.mask); - let remove = if natural <= i { - i < j || j < natural - } else { - j < natural && i < j - }; - if remove { - unsafe { - *self.slots.get_unchecked_mut(i) = v; - *self.slots.get_unchecked_mut(j) = Slot::EMPTY; - } - i = j; - } - j = (j + 1) & self.mask; - } - Some(v) - } - - pub fn contains_key(&self, key: u64) -> bool { - self.get(key).is_some() - } - - pub fn clear(&mut self) { - self.slots.fill(Slot::EMPTY); - self.len = 0; - } - - pub fn is_empty(&self) -> bool { - self.len == 0 - } - - pub fn iter(&self) -> Iter<'_> { - Iter::new(&self.slots) - } - - pub fn iter_mut(&mut self) -> IterMut<'_> { - IterMut::new(&mut self.slots) - } - - pub fn keys(&self) -> Keys<'_> { - Keys { inner: self.iter() } - } - - pub fn values(&self) -> Values<'_> { - Values { inner: self.iter() } - } - - pub fn values_mut(&mut self) -> ValuesMut<'_> { - ValuesMut { - inner: self.iter_mut(), - } - } - - #[cold] - fn rehash(&mut self) { - let new_size = (self.mask + 1) << 1; - self.mask = new_size - 1; - let old = core::mem::replace(&mut self.slots, alloc::vec![Slot::EMPTY; new_size]); - for slot in old { - if slot.is_empty() { - continue; - } - let mut i = mix(slot.0, self.mask); - loop { - let j = unsafe { self.slots.get_unchecked_mut(i) }; - if j.is_empty() { - *j = slot; - break; - } - i = (i + 1) & self.mask; - } - } - } - - pub fn len(&self) -> usize { - self.len - } - - pub fn capacity(&self) -> usize { - self.slots.len() - } -} - -impl Default for Int64Map { - fn default() -> Self { - Self::with_capacity(8) - } -} +const PRIME_MAX_A: u32 = u32::MAX - 4; +const PRIME_MAX_B: u32 = u32::MAX - 16; +const PRIME_MAX_C: u32 = u32::MAX - 64; -impl PartialEq for Int64Map { - fn eq(&self, other: &Int64Map) -> bool { - self.len == other.len - && self - .slots - .iter() - .filter(|x| !x.is_empty()) - .all(|slot| other.get(slot.0) == Some(slot.1)) - } +#[inline] +fn pack(x: i32, y: i32, z: i32) -> u64 { + let sx = (x & 0x3FF_FFFF) as i64; + let sy = (y & 0xFFF) as i64; + let sz = (z & 0x3FF_FFFF) as i64; + ((sx << 38) | (sz << 12) | sy) as u64 } -impl Eq for Int64Map {} - -impl core::fmt::Debug for Int64Map { - fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result { - fmt.debug_map().entries(self.iter()).finish() - } -} - -#[derive(Clone)] -pub struct Iter<'a> { - inner: core::slice::Iter<'a, Slot>, -} - -impl<'a> Iter<'a> { - fn new(vec: &'a [Slot]) -> Self { - Iter { inner: vec.iter() } - } -} - -impl<'a> Iterator for Iter<'a> { - type Item = (u64, u64); - - fn next(&mut self) -> Option { - self.inner.find(|&x| !x.is_empty()).map(|r| (r.0, r.1)) - } -} - -impl<'a> DoubleEndedIterator for Iter<'a> { - fn next_back(&mut self) -> Option { - self.inner.rfind(|&x| !x.is_empty()).map(|r| (r.0, r.1)) - } -} - -impl<'a> FusedIterator for Iter<'a> {} - -impl<'a> IntoIterator for &'a mut Int64Map { - type Item = (&'a mut u64, &'a mut u64); - type IntoIter = IterMut<'a>; - - fn into_iter(self) -> Self::IntoIter { - IterMut::new(&mut self.slots) - } -} - -pub struct IterMut<'a> { - inner: core::slice::IterMut<'a, Slot>, -} - -impl<'a> IterMut<'a> { - fn new(vec: &'a mut [Slot]) -> Self { - IterMut { - inner: vec.iter_mut(), - } - } -} - -impl<'a> Iterator for IterMut<'a> { - type Item = (&'a mut u64, &'a mut u64); - - fn next(&mut self) -> Option { - self.inner - .find(|x| !x.is_empty()) - .map(|x| (&mut x.0, &mut x.1)) - } -} - -impl<'a> DoubleEndedIterator for IterMut<'a> { - fn next_back(&mut self) -> Option { - self.inner - .rfind(|x| !x.is_empty()) - .map(|x| (&mut x.0, &mut x.1)) - } -} - -impl<'a> FusedIterator for IterMut<'a> {} - -pub struct Keys<'a> { - inner: Iter<'a>, -} - -impl<'a> Iterator for Keys<'a> { - type Item = u64; - - fn next(&mut self) -> Option { - self.inner.next().map(|kv| kv.0) - } -} - -impl<'a> DoubleEndedIterator for Keys<'a> { - fn next_back(&mut self) -> Option { - self.inner.next_back().map(|(k, _)| k) - } -} - -pub struct Values<'a> { - inner: Iter<'a>, -} - -impl<'a> Iterator for Values<'a> { - type Item = u64; - - fn next(&mut self) -> Option { - self.inner.next().map(|(_, v)| v) - } -} - -pub struct ValuesMut<'a> { - pub(crate) inner: IterMut<'a>, -} - -impl<'a> Iterator for ValuesMut<'a> { - type Item = &'a mut u64; - - fn next(&mut self) -> Option { - self.inner.next().map(|x| x.1) - } -} - -impl IntoIterator for Int64Map { - type Item = (u64, u64); - type IntoIter = IntoIter; - - fn into_iter(self) -> Self::IntoIter { - IntoIter::new(self.slots) - } -} - -pub struct IntoIter { - inner: alloc::vec::IntoIter, -} - -impl IntoIter { - fn new(vec: Vec) -> Self { - IntoIter { - inner: vec.into_iter(), - } - } -} - -impl Iterator for IntoIter { - type Item = (u64, u64); - - fn next(&mut self) -> Option<(u64, u64)> { - self.inner.find(|x| !x.is_empty()).map(|kv| (kv.0, kv.1)) - } -} - -impl<'a> FusedIterator for Keys<'a> {} - -impl<'a> FusedIterator for Values<'a> {} - -impl<'a> FusedIterator for ValuesMut<'a> {} - -impl FusedIterator for IntoIter {} - -impl Extend<(u64, u64)> for Int64Map { - #[inline] - fn extend>(&mut self, iter: T) { - for elem in iter { - self.insert(elem.0, elem.1); - } - } -} - -impl core::iter::FromIterator<(u64, u64)> for Int64Map { - fn from_iter>(iter: T) -> Self { - let iterator = iter.into_iter(); - let (lower_bound, _) = iterator.size_hint(); - let mut map = Int64Map::with_capacity(lower_bound); - for elem in iterator { - map.insert(elem.0, elem.1); - } - map - } +// 32 bits +#[inline] +fn mix(v: u64) -> u64 { + let x = (v >> 38) as i32 as u32; + let y = ((v << 52) >> 52) as i32 as u32; + let z = ((v << 26) >> 38) as i32 as u32; + let m = PRIME_MAX_A + .wrapping_mul(x) + .wrapping_add(PRIME_MAX_B.wrapping_mul(y)) + .wrapping_add(PRIME_MAX_C.wrapping_mul(z)); + m as u64 } diff --git a/haya_palette/src/lib.rs b/haya_palette/src/lib.rs index 28162fcd..2d802fc0 100644 --- a/haya_palette/src/lib.rs +++ b/haya_palette/src/lib.rs @@ -4,17 +4,14 @@ mod chunk; extern crate alloc; -pub use self::chunk::{ - ChunkCache, Direct, Indirect2, Indirect4, Int64Map, IntoIter, Iter, IterMut, Keys, Values, - ValuesMut, -}; +pub use self::chunk::{ChunkCache, Direct, Indirect2, Indirect4}; use alloc::alloc::{alloc, alloc_zeroed, dealloc, handle_alloc_error}; use core::alloc::Layout; use core::array::from_fn; use core::mem::{align_of, size_of}; use core::ptr::NonNull; use core::slice::from_raw_parts; -use minecraft_data::block_state; +use minecraft_data::{block, block_state}; use mser::{Error, Read, Reader, V21, V32, Write, Writer}; pub trait Palette: Copy { @@ -23,6 +20,7 @@ pub trait Palette: Copy { /// `value` must be a valid id. unsafe fn from_id(value: u32) -> Self; fn to_id(self) -> u32; + fn default() -> Self; } impl Palette for block_state { @@ -33,6 +31,10 @@ impl Palette for block_state { fn to_id(self) -> u32 { self.id() as u32 } + + fn default() -> Self { + block::void_air.state_default() + } } impl Palette for Biome { @@ -43,6 +45,10 @@ impl Palette for Biome { fn to_id(self) -> u32 { self as u32 } + + fn default() -> Self { + Biome::TheVoid + } } #[derive(Clone, Default, Copy, PartialEq, Eq)] From 54ed1fbaa674ec38eb8a5ddfff026ef6e02f4c37 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Tue, 5 May 2026 17:31:09 +0900 Subject: [PATCH 64/67] packet test_instance_block_action --- haya_protocol/src/lib.rs | 30 ++++++++++++++++++++++++++- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 21 +++++++++++++++++++ 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/haya_protocol/src/lib.rs b/haya_protocol/src/lib.rs index 44ac8b61..9c603196 100644 --- a/haya_protocol/src/lib.rs +++ b/haya_protocol/src/lib.rs @@ -4,7 +4,7 @@ use crate::inventory::HumanoidArm; use alloc::vec::Vec; use haya_collection::{List, Map, capacity_fix}; use haya_ident::{Ident, ResourceKey}; -use haya_math::BlockPosPacked; +use haya_math::{BlockPosPacked, IVec3}; use haya_nbt::Tag; use minecraft_data::data_component_type; use mser::{Either, Error, Read, Reader, Utf8, V21, V32, Write, Writer}; @@ -925,6 +925,34 @@ impl TestBlockMode { } } +#[derive(Clone, Serialize, Deserialize)] +pub struct TestInstanceData<'a> { + pub test: Option>, + pub size: IVec3, + pub rotation: Rotation, + pub ignore_entities: bool, + pub status: TestInstanceStatus, + pub error_message: Option, +} + +#[derive(Clone, Copy, Serialize, Deserialize)] +#[repr(u8)] +#[mser(varint)] +pub enum TestInstanceStatus { + Cleared, + Running, + Finished, +} + +impl TestInstanceStatus { + pub const fn name(self) -> &'static str { + match self { + Self::Cleared => "cleared", + Self::Running => "running", + Self::Finished => "finished", + } + } +} #[cfg(test)] mod tests { use super::*; diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index 7a9d21ef..dd075ecf 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -154,7 +154,7 @@ packets! { sign_update = game::SignUpdate<'_>, swing = game::Swing, teleport_to_entity = game::TeleportToEntity, - // test_instance_block_action, + test_instance_block_action = game::TestInstanceBlockAction<'_>, // use_item_on, // use_item, // custom_click_action, diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index cbec756c..46c22e61 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -5,6 +5,7 @@ use crate::inventory::{ContainerId, InteractionHand, RecipeBookType}; use crate::{ ClickType, CommandBlockEntityMode, Difficulty, GameType, HashedStack, Input, JointTypeName, MilliSeconds, Mirror, Rotation, StructureMode, StructureUpdateType, TestBlockMode, + TestInstanceData, }; use haya_collection::{List, Map}; use haya_ident::Ident; @@ -508,3 +509,23 @@ pub struct Swing { pub struct TeleportToEntity { pub uuid: Uuid, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct TestInstanceBlockAction<'a> { + pub pos: BlockPosPacked, + pub action: TestInstanceBlockActionType, + pub data: TestInstanceData<'a>, +} + +#[derive(Clone, Copy, Serialize, Deserialize)] +#[repr(u8)] +#[mser(varint)] +pub enum TestInstanceBlockActionType { + Init, + Query, + Set, + Reset, + Save, + Export, + Run, +} From fbf70951d4020ee8dd39be7b16c4a35ffa695d9f Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Tue, 5 May 2026 17:36:47 +0900 Subject: [PATCH 65/67] packet use_item_on --- haya_protocol/src/lib.rs | 12 +++++++++++- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 14 +++++++++++--- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/haya_protocol/src/lib.rs b/haya_protocol/src/lib.rs index 9c603196..4bc06e84 100644 --- a/haya_protocol/src/lib.rs +++ b/haya_protocol/src/lib.rs @@ -4,7 +4,7 @@ use crate::inventory::HumanoidArm; use alloc::vec::Vec; use haya_collection::{List, Map, capacity_fix}; use haya_ident::{Ident, ResourceKey}; -use haya_math::{BlockPosPacked, IVec3}; +use haya_math::{BlockPosPacked, Direction, FVec3, IVec3}; use haya_nbt::Tag; use minecraft_data::data_component_type; use mser::{Either, Error, Read, Reader, Utf8, V21, V32, Write, Writer}; @@ -953,6 +953,16 @@ impl TestInstanceStatus { } } } + +#[derive(Clone, Serialize, Deserialize)] +pub struct BlockHitResult { + pub block_pos: BlockPosPacked, + pub face: Direction, + pub click: FVec3, + pub inside: bool, + pub world_border_hit: bool, +} + #[cfg(test)] mod tests { use super::*; diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index dd075ecf..f0c132a7 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -155,7 +155,7 @@ packets! { swing = game::Swing, teleport_to_entity = game::TeleportToEntity, test_instance_block_action = game::TestInstanceBlockAction<'_>, - // use_item_on, + use_item_on = game::UseItemOn, // use_item, // custom_click_action, } diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 46c22e61..e2ac371d 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -3,9 +3,9 @@ use crate::command::ArgumentSignatures; use crate::crafting::RecipeDisplayId; use crate::inventory::{ContainerId, InteractionHand, RecipeBookType}; use crate::{ - ClickType, CommandBlockEntityMode, Difficulty, GameType, HashedStack, Input, JointTypeName, - MilliSeconds, Mirror, Rotation, StructureMode, StructureUpdateType, TestBlockMode, - TestInstanceData, + BlockHitResult, ClickType, CommandBlockEntityMode, Difficulty, GameType, HashedStack, Input, + JointTypeName, MilliSeconds, Mirror, Rotation, StructureMode, StructureUpdateType, + TestBlockMode, TestInstanceData, }; use haya_collection::{List, Map}; use haya_ident::Ident; @@ -529,3 +529,11 @@ pub enum TestInstanceBlockActionType { Export, Run, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct UseItemOn { + pub hand: InteractionHand, + pub block_hit: BlockHitResult, + #[mser(varint)] + pub sequence: u32, +} From 8d1809329b62901e0d3e7ce8156b140634f64a7d Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Tue, 5 May 2026 17:38:19 +0900 Subject: [PATCH 66/67] packet use_item --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index f0c132a7..e6b4ec1a 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -156,6 +156,6 @@ packets! { teleport_to_entity = game::TeleportToEntity, test_instance_block_action = game::TestInstanceBlockAction<'_>, use_item_on = game::UseItemOn, - // use_item, + use_item = game::UseItem, // custom_click_action, } diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index e2ac371d..904df8fd 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -537,3 +537,12 @@ pub struct UseItemOn { #[mser(varint)] pub sequence: u32, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct UseItem { + pub hand: InteractionHand, + #[mser(varint)] + pub sequence: u32, + pub y_rot: f32, + pub x_rot: f32, +} From ec6d2ad7d82a65e51d89be79ed711a77aa42d4a8 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Tue, 5 May 2026 17:42:26 +0900 Subject: [PATCH 67/67] packet custom_click_action --- haya_protocol/src/serverbound.rs | 2 +- haya_protocol/src/serverbound/game.rs | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/haya_protocol/src/serverbound.rs b/haya_protocol/src/serverbound.rs index e6b4ec1a..36c6aaeb 100644 --- a/haya_protocol/src/serverbound.rs +++ b/haya_protocol/src/serverbound.rs @@ -157,5 +157,5 @@ packets! { test_instance_block_action = game::TestInstanceBlockAction<'_>, use_item_on = game::UseItemOn, use_item = game::UseItem, - // custom_click_action, + custom_click_action = game::CustomClickAction<'_>, } diff --git a/haya_protocol/src/serverbound/game.rs b/haya_protocol/src/serverbound/game.rs index 904df8fd..d5ddb20d 100644 --- a/haya_protocol/src/serverbound/game.rs +++ b/haya_protocol/src/serverbound/game.rs @@ -11,7 +11,7 @@ use haya_collection::{List, Map}; use haya_ident::Ident; use haya_math::{BlockPosPacked, ByteDirection, FVec3, Vec3}; use minecraft_data::{debug_subscription, mob_effect}; -use mser::{Rest, Utf8}; +use mser::{ByteArray, Rest, Utf8}; use uuid::Uuid; #[derive(Clone, Serialize, Deserialize)] @@ -546,3 +546,9 @@ pub struct UseItem { pub y_rot: f32, pub x_rot: f32, } + +#[derive(Clone, Serialize, Deserialize)] +pub struct CustomClickAction<'a> { + pub id: Ident<'a>, + pub payload: ByteArray<'a, 65536>, +}