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