1use std::{
2 any::Any,
3 borrow::Cow,
4 fmt::{self, Debug},
5 io::{self, Cursor, Write},
6};
7
8use azalea_buf::{AzaleaRead, AzaleaReadVar, AzaleaWrite, AzaleaWriteVar, 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 AzaleaRead 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}
235
236impl AzaleaWrite for ItemStack {
237 fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
238 match self {
239 ItemStack::Empty => 0_i32.azalea_write_var(buf)?,
240 ItemStack::Present(i) => {
241 i.count.azalea_write_var(buf)?;
242 i.kind.azalea_write(buf)?;
243 i.component_patch.azalea_write(buf)?;
244 }
245 };
246 Ok(())
247 }
248}
249
250impl From<ItemStackData> for ItemStack {
251 fn from(item: ItemStackData) -> Self {
252 if item.is_empty() {
253 ItemStack::Empty
254 } else {
255 ItemStack::Present(item)
256 }
257 }
258}
259impl From<ItemKind> for ItemStack {
260 fn from(item: ItemKind) -> Self {
261 ItemStack::new(item, 1)
262 }
263}
264impl From<(ItemKind, i32)> for ItemStack {
265 fn from(item: (ItemKind, i32)) -> Self {
266 ItemStack::new(item.0, item.1)
267 }
268}
269impl From<ItemKind> for ItemStackData {
270 fn from(item: ItemKind) -> Self {
271 ItemStackData::new(item, 1)
272 }
273}
274impl From<(ItemKind, i32)> for ItemStackData {
275 fn from(item: (ItemKind, i32)) -> Self {
276 ItemStackData::new(item.0, item.1)
277 }
278}
279
280#[derive(Default)]
285pub struct DataComponentPatch {
286 components: Box<IndexMap<DataComponentKind, Option<DataComponentUnion>>>,
287}
288
289impl DataComponentPatch {
290 pub fn get<T: components::DataComponentTrait>(&self) -> Option<&T> {
302 let component = self.get_kind(T::KIND)?;
303 let component_any = component as &dyn Any;
304 component_any.downcast_ref::<T>()
305 }
306
307 pub fn get_kind(
308 &self,
309 kind: DataComponentKind,
310 ) -> Option<&dyn components::EncodableDataComponent> {
311 self.components.get(&kind).and_then(|c| {
312 c.as_ref().map(|c| {
313 unsafe { c.as_kind(kind) }
316 })
317 })
318 }
319
320 pub fn has<T: components::DataComponentTrait>(&self) -> bool {
331 self.has_kind(T::KIND)
332 }
333
334 pub fn has_kind(&self, kind: DataComponentKind) -> bool {
335 self.get_kind(kind).is_some()
336 }
337
338 pub fn iter<'a>(
339 &'a self,
340 ) -> impl Iterator<
341 Item = (
342 DataComponentKind,
343 Option<&'a dyn components::EncodableDataComponent>,
344 ),
345 > + 'a {
346 self.components.iter().map(|(&kind, component)| {
347 component.as_ref().map_or_else(
348 || (kind, None),
349 |c| (kind, unsafe { Some(c.as_kind(kind)) }),
350 )
351 })
352 }
353 pub unsafe fn unchecked_insert_component(
358 &mut self,
359 kind: DataComponentKind,
360 value: Option<DataComponentUnion>,
361 ) {
362 self.components.insert(kind, value);
363 }
364}
365
366impl Drop for DataComponentPatch {
367 fn drop(&mut self) {
368 for (kind, component) in self.components.iter_mut() {
370 if let Some(component) = component {
371 unsafe { component.drop_as(*kind) };
373 }
374 }
375 }
376}
377
378impl AzaleaRead for DataComponentPatch {
379 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
380 let components_with_data_count = u32::azalea_read_var(buf)?;
381 let components_without_data_count = u32::azalea_read_var(buf)?;
382
383 if components_without_data_count == 0 && components_with_data_count == 0 {
384 return Ok(DataComponentPatch::default());
385 }
386
387 let mut components = IndexMap::new();
388 for _ in 0..components_with_data_count {
389 let component_kind = DataComponentKind::azalea_read(buf)?;
390 let component_data = DataComponentUnion::azalea_read_as(component_kind, buf)?;
391 components.insert(component_kind, Some(component_data));
392 }
393
394 for _ in 0..components_without_data_count {
395 let component_kind = DataComponentKind::azalea_read(buf)?;
396 components.insert(component_kind, None);
397 }
398
399 Ok(DataComponentPatch {
400 components: Box::new(components),
401 })
402 }
403}
404
405impl AzaleaWrite for DataComponentPatch {
406 fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
407 let mut components_with_data_count: u32 = 0;
408 let mut components_without_data_count: u32 = 0;
409 for component in self.components.values() {
410 if component.is_some() {
411 components_with_data_count += 1;
412 } else {
413 components_without_data_count += 1;
414 }
415 }
416
417 components_with_data_count.azalea_write_var(buf)?;
418 components_without_data_count.azalea_write_var(buf)?;
419
420 let mut component_buf = Vec::new();
421 for (kind, component) in self.components.iter() {
422 if let Some(component) = component {
423 kind.azalea_write(buf)?;
424
425 component_buf.clear();
426 unsafe { component.azalea_write_as(*kind, &mut component_buf) }?;
428 buf.write_all(&component_buf)?;
429 }
430 }
431
432 for (kind, component) in self.components.iter() {
433 if component.is_none() {
434 kind.azalea_write(buf)?;
435 }
436 }
437
438 Ok(())
439 }
440}
441
442impl Clone for DataComponentPatch {
443 fn clone(&self) -> Self {
444 let mut components = IndexMap::with_capacity(self.components.len());
445 for (kind, component) in self.components.iter() {
446 components.insert(
447 *kind,
448 component.as_ref().map(|c| unsafe { c.clone_as(*kind) }),
449 );
450 }
451 DataComponentPatch {
452 components: Box::new(components),
453 }
454 }
455}
456impl Debug for DataComponentPatch {
457 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
458 f.debug_set().entries(self.components.keys()).finish()
459 }
460}
461impl PartialEq for DataComponentPatch {
462 fn eq(&self, other: &Self) -> bool {
463 if self.components.len() != other.components.len() {
464 return false;
465 }
466 for (kind, component) in self.components.iter() {
467 let Some(other_component) = other.components.get(kind) else {
468 return false;
469 };
470 if let Some(component) = component {
472 let Some(other_component) = other_component else {
473 return false;
474 };
475 if !unsafe { component.eq_as(other_component, *kind) } {
478 return false;
479 }
480 } else if other_component.is_some() {
481 return false;
482 }
483 }
484 true
485 }
486}
487
488impl Serialize for DataComponentPatch {
489 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
490 where
491 S: serde::Serializer,
492 {
493 let mut s = serializer.serialize_map(Some(self.components.len()))?;
494 for (kind, component) in self.components.iter() {
495 if let Some(component) = component {
496 unsafe { component.serialize_entry_as(&mut s, *kind) }?;
497 } else {
498 #[derive(Serialize)]
499 struct EmptyComponent;
500 s.serialize_entry(&format!("!{kind}"), &EmptyComponent)?;
501 }
502 }
503 s.end()
504 }
505}
506
507#[cfg(test)]
508mod tests {
509 use super::*;
510 use crate::components::MapId;
511
512 #[test]
513 fn test_get_component() {
514 let item = ItemStack::from(ItemKind::Map).with_component(MapId { id: 1 });
515 let map_id = item.get_component::<MapId>().unwrap();
516 assert_eq!(map_id.id, 1);
517 }
518}