1use std::{
2 any::Any,
3 borrow::Cow,
4 fmt,
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::{DataComponentKind, Item};
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(Debug, Clone, Default, PartialEq)]
21pub enum ItemStack {
22 #[default]
23 Empty,
24 Present(ItemStackData),
25}
26
27impl ItemStack {
28 pub fn new(item: Item, 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) -> azalea_registry::Item {
85 match self {
86 ItemStack::Empty => azalea_registry::Item::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 get_component<'a, T: components::DataComponentTrait>(&'a self) -> Option<Cow<'a, T>> {
120 self.as_present().and_then(|i| i.get_component::<T>())
121 }
122
123 pub fn with_component<
124 T: components::EncodableDataComponent + components::DataComponentTrait,
125 >(
126 mut self,
127 component: impl Into<Option<T>>,
128 ) -> Self {
129 if let ItemStack::Present(i) = &mut self {
130 let component: Option<T> = component.into();
131 let component: Option<DataComponentUnion> = component.map(|c| c.into());
132 i.component_patch.components.insert(T::KIND, component);
133 }
134 self
135 }
136}
137impl Serialize for ItemStack {
138 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
139 where
140 S: serde::Serializer,
141 {
142 match self {
143 ItemStack::Empty => serializer.serialize_unit(),
144 ItemStack::Present(i) => i.serialize(serializer),
145 }
146 }
147}
148
149#[derive(Debug, Clone, PartialEq, Serialize)]
153pub struct ItemStackData {
154 #[serde(rename = "id")]
155 pub kind: azalea_registry::Item,
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: Item, count: i32) -> Self {
169 ItemStackData {
170 count,
171 kind: item,
172 component_patch: DataComponentPatch::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 == azalea_registry::Item::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 = azalea_registry::Item::azalea_read(buf)?;
226 let component_patch = DataComponentPatch::azalea_read(buf)?;
227 Ok(ItemStack::Present(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<Item> for ItemStack {
260 fn from(item: Item) -> Self {
261 ItemStack::new(item, 1)
262 }
263}
264impl From<(Item, i32)> for ItemStack {
265 fn from(item: (Item, i32)) -> Self {
266 ItemStack::new(item.0, item.1)
267 }
268}
269impl From<Item> for ItemStackData {
270 fn from(item: Item) -> Self {
271 ItemStackData::new(item, 1)
272 }
273}
274impl From<(Item, i32)> for ItemStackData {
275 fn from(item: (Item, i32)) -> Self {
276 ItemStackData::new(item.0, item.1)
277 }
278}
279
280#[derive(Default)]
285pub struct DataComponentPatch {
286 components: 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 &mut self.components {
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 { components })
400 }
401}
402
403impl AzaleaWrite for DataComponentPatch {
404 fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
405 let mut components_with_data_count: u32 = 0;
406 let mut components_without_data_count: u32 = 0;
407 for component in self.components.values() {
408 if component.is_some() {
409 components_with_data_count += 1;
410 } else {
411 components_without_data_count += 1;
412 }
413 }
414
415 components_with_data_count.azalea_write_var(buf)?;
416 components_without_data_count.azalea_write_var(buf)?;
417
418 let mut component_buf = Vec::new();
419 for (kind, component) in &self.components {
420 if let Some(component) = component {
421 kind.azalea_write(buf)?;
422
423 component_buf.clear();
424 unsafe { component.azalea_write_as(*kind, &mut component_buf) }?;
426 buf.write_all(&component_buf)?;
427 }
428 }
429
430 for (kind, component) in &self.components {
431 if component.is_none() {
432 kind.azalea_write(buf)?;
433 }
434 }
435
436 Ok(())
437 }
438}
439
440impl Clone for DataComponentPatch {
441 fn clone(&self) -> Self {
442 let mut components = IndexMap::with_capacity(self.components.len());
443 for (kind, component) in &self.components {
444 components.insert(
445 *kind,
446 component.as_ref().map(|c| unsafe { c.clone_as(*kind) }),
447 );
448 }
449 DataComponentPatch { components }
450 }
451}
452impl fmt::Debug for DataComponentPatch {
453 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
454 f.debug_set().entries(self.components.keys()).finish()
455 }
456}
457impl PartialEq for DataComponentPatch {
458 fn eq(&self, other: &Self) -> bool {
459 if self.components.len() != other.components.len() {
460 return false;
461 }
462 for (kind, component) in &self.components {
463 let Some(other_component) = other.components.get(kind) else {
464 return false;
465 };
466 if let Some(component) = component {
468 let Some(other_component) = other_component else {
469 return false;
470 };
471 if !unsafe { component.eq_as(other_component, *kind) } {
474 return false;
475 }
476 } else if other_component.is_some() {
477 return false;
478 }
479 }
480 true
481 }
482}
483
484impl Serialize for DataComponentPatch {
485 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
486 where
487 S: serde::Serializer,
488 {
489 let mut s = serializer.serialize_map(Some(self.components.len()))?;
490 for (kind, component) in &self.components {
491 if let Some(component) = component {
492 unsafe { component.serialize_entry_as(&mut s, *kind) }?;
493 } else {
494 #[derive(Serialize)]
495 struct EmptyComponent;
496 s.serialize_entry(&format!("!{kind}"), &EmptyComponent)?;
497 }
498 }
499 s.end()
500 }
501}
502
503#[cfg(test)]
504mod tests {
505 use super::*;
506 use crate::components::MapId;
507
508 #[test]
509 fn test_get_component() {
510 let item = ItemStack::from(Item::Map).with_component(MapId { id: 1 });
511 let map_id = item.get_component::<MapId>().unwrap();
512 assert_eq!(map_id.id, 1);
513 }
514}