azalea_protocol/packets/game/
s_container_click.rs1use azalea_buf::AzBuf;
2use azalea_core::{checksum::Checksum, registry_holder::RegistryHolder};
3use azalea_inventory::{ItemStack, operations::ClickType};
4use azalea_protocol_macros::ServerboundGamePacket;
5use azalea_registry::builtin::{DataComponentKind, ItemKind};
6use indexmap::IndexMap;
7
8#[derive(Clone, Debug, AzBuf, PartialEq, ServerboundGamePacket)]
9pub struct ServerboundContainerClick {
10 #[var]
11 pub container_id: i32,
12 #[var]
13 pub state_id: u32,
14 pub slot_num: i16,
15 pub button_num: u8,
16 pub click_type: ClickType,
17 pub changed_slots: IndexMap<u16, HashedStack>,
18 pub carried_item: HashedStack,
19}
20
21#[derive(Clone, Debug, AzBuf, PartialEq)]
24pub struct HashedStack(pub Option<HashedActualItem>);
25
26#[derive(Clone, Debug, AzBuf, PartialEq)]
27pub struct HashedActualItem {
28 pub kind: ItemKind,
29 #[var]
30 pub count: i32,
31 pub components: HashedPatchMap,
32}
33
34#[derive(Clone, Debug, AzBuf, PartialEq)]
35pub struct HashedPatchMap {
36 #[limit(256)]
37 pub added_components: Vec<(DataComponentKind, Checksum)>,
38 #[limit(256)]
39 pub removed_components: Vec<DataComponentKind>,
40}
41
42impl HashedStack {
43 pub fn from_item_stack(item: &ItemStack, registries: &RegistryHolder) -> Self {
52 let ItemStack::Present(item) = item else {
53 return HashedStack(None);
54 };
55
56 let mut added_components = Vec::new();
57 let mut removed_components = Vec::new();
58
59 for (kind, data) in item.component_patch.iter() {
60 if let Some(data) = data {
61 added_components.push((kind, data.crc_hash(registries)));
62 } else {
63 removed_components.push(kind);
64 }
65 }
66
67 let components = HashedPatchMap {
68 added_components,
69 removed_components,
70 };
71 let item = HashedActualItem {
72 kind: item.kind,
73 count: item.count,
74 components,
75 };
76 Self(Some(item))
77 }
78}