1use std::{
2 any::Any,
3 fmt,
4 io::{self, Cursor, Write},
5};
6
7use azalea_buf::{AzaleaRead, AzaleaReadVar, AzaleaWrite, AzaleaWriteVar, BufReadError};
8use azalea_registry::DataComponentKind;
9use indexmap::IndexMap;
10
11use crate::components::{self};
12
13#[derive(Debug, Clone, Default, PartialEq)]
15pub enum ItemStack {
16 #[default]
17 Empty,
18 Present(ItemStackData),
19}
20
21impl ItemStack {
22 pub fn is_empty(&self) -> bool {
27 match self {
28 ItemStack::Empty => true,
29 ItemStack::Present(item) => item.is_empty(),
30 }
31 }
32 pub fn is_present(&self) -> bool {
37 !self.is_empty()
38 }
39
40 pub fn count(&self) -> i32 {
45 match self {
46 ItemStack::Empty => 0,
47 ItemStack::Present(i) => i.count,
48 }
49 }
50
51 pub fn split(&mut self, count: u32) -> ItemStack {
53 match self {
54 ItemStack::Empty => ItemStack::Empty,
55 ItemStack::Present(i) => {
56 let returning = i.split(count);
57 if i.is_empty() {
58 *self = ItemStack::Empty;
59 }
60 ItemStack::Present(returning)
61 }
62 }
63 }
64
65 pub fn kind(&self) -> azalea_registry::Item {
68 match self {
69 ItemStack::Empty => azalea_registry::Item::Air,
70 ItemStack::Present(i) => i.kind,
71 }
72 }
73
74 pub fn update_empty(&mut self) {
76 if let ItemStack::Present(i) = self
77 && i.is_empty()
78 {
79 *self = ItemStack::Empty;
80 }
81 }
82
83 pub fn as_present(&self) -> Option<&ItemStackData> {
85 match self {
86 ItemStack::Empty => None,
87 ItemStack::Present(i) => Some(i),
88 }
89 }
90
91 pub fn as_present_mut(&mut self) -> Option<&mut ItemStackData> {
92 match self {
93 ItemStack::Empty => None,
94 ItemStack::Present(i) => Some(i),
95 }
96 }
97}
98
99#[derive(Debug, Clone, PartialEq)]
102pub struct ItemStackData {
103 pub count: i32,
107 pub kind: azalea_registry::Item,
108 pub components: DataComponentPatch,
109}
110
111impl ItemStackData {
112 pub fn split(&mut self, count: u32) -> ItemStackData {
114 let returning_count = i32::min(count as i32, self.count);
115 let mut returning = self.clone();
116 returning.count = returning_count;
117 self.count -= returning_count;
118 returning
119 }
120
121 pub fn is_empty(&self) -> bool {
123 self.count <= 0 || self.kind == azalea_registry::Item::Air
124 }
125
126 pub fn is_same_item_and_components(&self, other: &ItemStackData) -> bool {
147 self.kind == other.kind && self.components == other.components
148 }
149}
150
151impl AzaleaRead for ItemStack {
152 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
153 let count = i32::azalea_read_var(buf)?;
154 if count <= 0 {
155 Ok(ItemStack::Empty)
156 } else {
157 let kind = azalea_registry::Item::azalea_read(buf)?;
158 let components = DataComponentPatch::azalea_read(buf)?;
159 Ok(ItemStack::Present(ItemStackData {
160 count,
161 kind,
162 components,
163 }))
164 }
165 }
166}
167
168impl AzaleaWrite for ItemStack {
169 fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
170 match self {
171 ItemStack::Empty => 0_i32.azalea_write_var(buf)?,
172 ItemStack::Present(i) => {
173 i.count.azalea_write_var(buf)?;
174 i.kind.azalea_write(buf)?;
175 i.components.azalea_write(buf)?;
176 }
177 };
178 Ok(())
179 }
180}
181
182impl From<ItemStackData> for ItemStack {
183 fn from(item: ItemStackData) -> Self {
184 if item.is_empty() {
185 ItemStack::Empty
186 } else {
187 ItemStack::Present(item)
188 }
189 }
190}
191
192#[derive(Default)]
197pub struct DataComponentPatch {
198 pub components:
199 IndexMap<DataComponentKind, Option<Box<dyn components::EncodableDataComponent>>>,
200}
201
202impl DataComponentPatch {
203 pub fn get<T: components::DataComponent>(&self) -> Option<&T> {
215 let component = self.components.get(&T::KIND).and_then(|c| c.as_deref())?;
216 let component_any = component as &dyn Any;
217 component_any.downcast_ref::<T>()
218 }
219
220 pub fn get_kind(
221 &self,
222 kind: DataComponentKind,
223 ) -> Option<&dyn components::EncodableDataComponent> {
224 self.components.get(&kind).and_then(|c| c.as_deref())
225 }
226
227 pub fn has<T: components::DataComponent>(&self) -> bool {
242 self.has_kind(T::KIND)
243 }
244
245 pub fn has_kind(&self, kind: DataComponentKind) -> bool {
246 self.get_kind(kind).is_some()
247 }
248}
249
250impl AzaleaRead for DataComponentPatch {
251 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
252 let components_with_data_count = u32::azalea_read_var(buf)?;
253 let components_without_data_count = u32::azalea_read_var(buf)?;
254
255 if components_without_data_count == 0 && components_with_data_count == 0 {
256 return Ok(DataComponentPatch::default());
257 }
258
259 let mut components = IndexMap::new();
260 for _ in 0..components_with_data_count {
261 let component_kind = DataComponentKind::azalea_read(buf)?;
262 let component_data = components::from_kind(component_kind, buf)?;
263 components.insert(component_kind, Some(component_data));
264 }
265
266 for _ in 0..components_without_data_count {
267 let component_kind = DataComponentKind::azalea_read(buf)?;
268 components.insert(component_kind, None);
269 }
270
271 Ok(DataComponentPatch { components })
272 }
273}
274
275impl AzaleaWrite for DataComponentPatch {
276 fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
277 let mut components_with_data_count: u32 = 0;
278 let mut components_without_data_count: u32 = 0;
279 for component in self.components.values() {
280 if component.is_some() {
281 components_with_data_count += 1;
282 } else {
283 components_without_data_count += 1;
284 }
285 }
286
287 components_with_data_count.azalea_write_var(buf)?;
288 components_without_data_count.azalea_write_var(buf)?;
289
290 let mut component_buf = Vec::new();
291 for (kind, component) in &self.components {
292 if let Some(component) = component {
293 kind.azalea_write(buf)?;
294
295 component_buf.clear();
296 component.encode(&mut component_buf)?;
297 buf.write_all(&component_buf)?;
298 }
299 }
300
301 for (kind, component) in &self.components {
302 if component.is_none() {
303 kind.azalea_write(buf)?;
304 }
305 }
306
307 Ok(())
308 }
309}
310
311impl Clone for DataComponentPatch {
312 fn clone(&self) -> Self {
313 let mut components = IndexMap::with_capacity(self.components.len());
314 for (kind, component) in &self.components {
315 components.insert(*kind, component.as_ref().map(|c| (*c).clone()));
316 }
317 DataComponentPatch { components }
318 }
319}
320impl fmt::Debug for DataComponentPatch {
321 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
322 f.debug_set().entries(self.components.keys()).finish()
323 }
324}
325impl PartialEq for DataComponentPatch {
326 fn eq(&self, other: &Self) -> bool {
327 if self.components.len() != other.components.len() {
328 return false;
329 }
330 for (kind, component) in &self.components {
331 let Some(other_component) = other.components.get(kind) else {
332 return false;
333 };
334 if let Some(component) = component {
336 let Some(other_component) = other_component else {
337 return false;
338 };
339 if !component.eq((*other_component).clone()) {
340 return false;
341 }
342 } else if other_component.is_some() {
343 return false;
344 }
345 }
346 true
347 }
348}