1use std::{
2 any::Any,
3 borrow::Cow,
4 fmt::{self, Debug},
5 io::{self, Cursor, Write},
6};
7
8use azalea_buf::{AzBuf, AzBufVar, BufReadError};
9use azalea_core::codec_utils::is_default;
10use azalea_registry::builtin::{DataComponentKind, ItemKind};
11use indexmap::IndexMap;
12use serde::{Serialize, ser::SerializeMap};
13
14use crate::{
15 components::{self, DataComponentUnion},
16 default_components::get_default_component,
17};
18
19#[derive(Clone, Debug, Default, PartialEq)]
21pub enum ItemStack {
22 #[default]
23 Empty,
24 Present(ItemStackData),
25}
26
27impl ItemStack {
28 pub fn new(item: ItemKind, count: i32) -> Self {
33 let mut i = ItemStack::Present(ItemStackData::new(item, count));
34 i.update_empty();
36 i
37 }
38
39 pub fn is_empty(&self) -> bool {
44 match self {
45 ItemStack::Empty => true,
46 ItemStack::Present(item) => item.is_empty(),
47 }
48 }
49 pub fn is_present(&self) -> bool {
54 !self.is_empty()
55 }
56
57 pub fn count(&self) -> i32 {
62 match self {
63 ItemStack::Empty => 0,
64 ItemStack::Present(i) => i.count,
65 }
66 }
67
68 pub fn split(&mut self, count: u32) -> ItemStack {
70 match self {
71 ItemStack::Empty => ItemStack::Empty,
72 ItemStack::Present(i) => {
73 let returning = i.split(count);
74 if i.is_empty() {
75 *self = ItemStack::Empty;
76 }
77 ItemStack::Present(returning)
78 }
79 }
80 }
81
82 pub fn kind(&self) -> ItemKind {
84 match self {
85 ItemStack::Empty => ItemKind::Air,
86 ItemStack::Present(i) => i.kind,
87 }
88 }
89
90 pub fn update_empty(&mut self) {
92 if let ItemStack::Present(i) = self
93 && i.is_empty()
94 {
95 *self = ItemStack::Empty;
96 }
97 }
98
99 pub fn as_present(&self) -> Option<&ItemStackData> {
101 match self {
102 ItemStack::Empty => None,
103 ItemStack::Present(i) => Some(i),
104 }
105 }
106
107 pub fn as_present_mut(&mut self) -> Option<&mut ItemStackData> {
108 match self {
109 ItemStack::Empty => None,
110 ItemStack::Present(i) => Some(i),
111 }
112 }
113
114 pub fn get_component<'a, T: components::DataComponentTrait>(&'a self) -> Option<Cow<'a, T>> {
119 self.as_present().and_then(|i| i.get_component::<T>())
120 }
121
122 pub fn with_component<
123 T: components::EncodableDataComponent + components::DataComponentTrait,
124 >(
125 mut self,
126 component: impl Into<Option<T>>,
127 ) -> Self {
128 if let ItemStack::Present(i) = &mut self {
129 let component: Option<T> = component.into();
130 let component: Option<DataComponentUnion> = component.map(|c| c.into());
131 i.component_patch.components.insert(T::KIND, component);
132 }
133 self
134 }
135}
136impl Serialize for ItemStack {
137 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
138 where
139 S: serde::Serializer,
140 {
141 match self {
142 ItemStack::Empty => serializer.serialize_unit(),
143 ItemStack::Present(i) => i.serialize(serializer),
144 }
145 }
146}
147
148#[derive(Clone, Debug, PartialEq, Serialize)]
153pub struct ItemStackData {
154 #[serde(rename = "id")]
155 pub kind: ItemKind,
156 pub count: i32,
160 #[serde(rename = "components", skip_serializing_if = "is_default")]
163 pub component_patch: DataComponentPatch,
164}
165
166impl ItemStackData {
167 pub fn new(item: ItemKind, count: i32) -> Self {
169 ItemStackData {
170 count,
171 kind: item,
172 component_patch: Default::default(),
173 }
174 }
175
176 pub fn split(&mut self, count: u32) -> ItemStackData {
178 let returning_count = i32::min(count as i32, self.count);
179 let mut returning = self.clone();
180 returning.count = returning_count;
181 self.count -= returning_count;
182 returning
183 }
184
185 pub fn is_empty(&self) -> bool {
187 self.count <= 0 || self.kind == ItemKind::Air
188 }
189
190 pub fn is_same_item_and_components(&self, other: &ItemStackData) -> bool {
203 self.kind == other.kind && self.component_patch == other.component_patch
204 }
205
206 pub fn get_component<'a, T: components::DataComponentTrait>(&'a self) -> Option<Cow<'a, T>> {
211 if let Some(c) = self.component_patch.get::<T>() {
212 Some(Cow::Borrowed(c))
213 } else {
214 get_default_component::<T>(self.kind).map(|c| Cow::Owned(c))
215 }
216 }
217}
218
219impl AzBuf for ItemStack {
220 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
221 let count = i32::azalea_read_var(buf)?;
222 if count <= 0 {
223 Ok(ItemStack::Empty)
224 } else {
225 let kind = ItemKind::azalea_read(buf)?;
226 let component_patch = DataComponentPatch::azalea_read(buf)?;
227 Ok(ItemStack::from(ItemStackData {
228 count,
229 kind,
230 component_patch,
231 }))
232 }
233 }
234 fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
235 match self {
236 ItemStack::Empty => 0_i32.azalea_write_var(buf)?,
237 ItemStack::Present(i) => {
238 i.count.azalea_write_var(buf)?;
239 i.kind.azalea_write(buf)?;
240 i.component_patch.azalea_write(buf)?;
241 }
242 };
243 Ok(())
244 }
245}
246
247impl From<ItemStackData> for ItemStack {
248 fn from(item: ItemStackData) -> Self {
249 if item.is_empty() {
250 ItemStack::Empty
251 } else {
252 ItemStack::Present(item)
253 }
254 }
255}
256impl From<ItemKind> for ItemStack {
257 fn from(item: ItemKind) -> Self {
258 ItemStack::new(item, 1)
259 }
260}
261impl From<(ItemKind, i32)> for ItemStack {
262 fn from(item: (ItemKind, i32)) -> Self {
263 ItemStack::new(item.0, item.1)
264 }
265}
266impl From<ItemKind> for ItemStackData {
267 fn from(item: ItemKind) -> Self {
268 ItemStackData::new(item, 1)
269 }
270}
271impl From<(ItemKind, i32)> for ItemStackData {
272 fn from(item: (ItemKind, i32)) -> Self {
273 ItemStackData::new(item.0, item.1)
274 }
275}
276
277#[derive(Default)]
282pub struct DataComponentPatch {
283 components: Box<IndexMap<DataComponentKind, Option<DataComponentUnion>>>,
284}
285
286impl DataComponentPatch {
287 pub fn get<T: components::DataComponentTrait>(&self) -> Option<&T> {
299 let component = self.get_kind(T::KIND)?;
300 let component_any = component as &dyn Any;
301 component_any.downcast_ref::<T>()
302 }
303
304 pub fn get_kind(
305 &self,
306 kind: DataComponentKind,
307 ) -> Option<&dyn components::EncodableDataComponent> {
308 self.components.get(&kind).and_then(|c| {
309 c.as_ref().map(|c| {
310 unsafe { c.as_kind(kind) }
313 })
314 })
315 }
316
317 pub fn has<T: components::DataComponentTrait>(&self) -> bool {
328 self.has_kind(T::KIND)
329 }
330
331 pub fn has_kind(&self, kind: DataComponentKind) -> bool {
332 self.get_kind(kind).is_some()
333 }
334
335 pub fn iter<'a>(
336 &'a self,
337 ) -> impl Iterator<
338 Item = (
339 DataComponentKind,
340 Option<&'a dyn components::EncodableDataComponent>,
341 ),
342 > + 'a {
343 self.components.iter().map(|(&kind, component)| {
344 component.as_ref().map_or_else(
345 || (kind, None),
346 |c| (kind, unsafe { Some(c.as_kind(kind)) }),
347 )
348 })
349 }
350 pub unsafe fn unchecked_insert_component(
355 &mut self,
356 kind: DataComponentKind,
357 value: Option<DataComponentUnion>,
358 ) {
359 let existing = self.components.insert(kind, value);
360 if let Some(Some(mut existing)) = existing {
361 unsafe { existing.drop_as(kind) };
364 }
365 }
366}
367
368impl Drop for DataComponentPatch {
369 fn drop(&mut self) {
370 for (kind, component) in self.components.iter_mut() {
372 if let Some(component) = component {
373 unsafe { component.drop_as(*kind) };
375 }
376 }
377 }
378}
379
380impl AzBuf for DataComponentPatch {
381 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
382 let components_with_data_count = u32::azalea_read_var(buf)?;
383 let components_without_data_count = u32::azalea_read_var(buf)?;
384
385 if components_without_data_count == 0 && components_with_data_count == 0 {
386 return Ok(DataComponentPatch::default());
387 }
388
389 let mut components = DataComponentPatch::default();
390
391 for _ in 0..components_with_data_count {
392 let component_kind = DataComponentKind::azalea_read(buf)?;
393 let component_data = DataComponentUnion::azalea_read_as(component_kind, buf)?;
394 unsafe { components.unchecked_insert_component(component_kind, Some(component_data)) };
397 }
398
399 for _ in 0..components_without_data_count {
400 let component_kind = DataComponentKind::azalea_read(buf)?;
401 unsafe { components.unchecked_insert_component(component_kind, None) };
403 }
404
405 Ok(components)
406 }
407 fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
408 let mut components_with_data_count: u32 = 0;
409 let mut components_without_data_count: u32 = 0;
410 for component in self.components.values() {
411 if component.is_some() {
412 components_with_data_count += 1;
413 } else {
414 components_without_data_count += 1;
415 }
416 }
417
418 components_with_data_count.azalea_write_var(buf)?;
419 components_without_data_count.azalea_write_var(buf)?;
420
421 let mut component_buf = Vec::new();
422 for (kind, component) in self.components.iter() {
423 if let Some(component) = component {
424 kind.azalea_write(buf)?;
425
426 component_buf.clear();
427 unsafe { component.azalea_write_as(*kind, &mut component_buf) }?;
429 buf.write_all(&component_buf)?;
430 }
431 }
432
433 for (kind, component) in self.components.iter() {
434 if component.is_none() {
435 kind.azalea_write(buf)?;
436 }
437 }
438
439 Ok(())
440 }
441}
442
443impl Clone for DataComponentPatch {
444 fn clone(&self) -> Self {
445 let mut components = IndexMap::with_capacity(self.components.len());
446 for (kind, component) in self.components.iter() {
447 components.insert(
448 *kind,
449 component.as_ref().map(|c| unsafe { c.clone_as(*kind) }),
450 );
451 }
452 DataComponentPatch {
453 components: Box::new(components),
454 }
455 }
456}
457impl Debug for DataComponentPatch {
458 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
459 f.debug_set().entries(self.components.keys()).finish()
460 }
461}
462impl PartialEq for DataComponentPatch {
463 fn eq(&self, other: &Self) -> bool {
464 if self.components.len() != other.components.len() {
465 return false;
466 }
467 for (kind, component) in self.components.iter() {
468 let Some(other_component) = other.components.get(kind) else {
469 return false;
470 };
471 if let Some(component) = component {
473 let Some(other_component) = other_component else {
474 return false;
475 };
476 if !unsafe { component.eq_as(other_component, *kind) } {
479 return false;
480 }
481 } else if other_component.is_some() {
482 return false;
483 }
484 }
485 true
486 }
487}
488
489impl Serialize for DataComponentPatch {
490 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
491 where
492 S: serde::Serializer,
493 {
494 let mut s = serializer.serialize_map(Some(self.components.len()))?;
495 for (kind, component) in self.components.iter() {
496 if let Some(component) = component {
497 unsafe { component.serialize_entry_as(&mut s, *kind) }?;
498 } else {
499 #[derive(Serialize)]
500 struct EmptyComponent;
501 s.serialize_entry(&format!("!{kind}"), &EmptyComponent)?;
502 }
503 }
504 s.end()
505 }
506}
507
508#[cfg(test)]
509mod tests {
510 use super::*;
511 use crate::components::MapId;
512
513 #[test]
514 fn test_get_component() {
515 let item = ItemStack::from(ItemKind::Map).with_component(MapId { id: 1 });
516 let map_id = item.get_component::<MapId>().unwrap();
517 assert_eq!(map_id.id, 1);
518 }
519}