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)]
152pub struct ItemStackData {
153 #[serde(rename = "id")]
154 pub kind: azalea_registry::Item,
155 pub count: i32,
159 #[serde(rename = "components", skip_serializing_if = "is_default")]
162 pub component_patch: DataComponentPatch,
163}
164
165impl ItemStackData {
166 pub fn new(item: Item, count: i32) -> Self {
168 ItemStackData {
169 count,
170 kind: item,
171 component_patch: DataComponentPatch::default(),
172 }
173 }
174
175 pub fn split(&mut self, count: u32) -> ItemStackData {
177 let returning_count = i32::min(count as i32, self.count);
178 let mut returning = self.clone();
179 returning.count = returning_count;
180 self.count -= returning_count;
181 returning
182 }
183
184 pub fn is_empty(&self) -> bool {
186 self.count <= 0 || self.kind == azalea_registry::Item::Air
187 }
188
189 pub fn is_same_item_and_components(&self, other: &ItemStackData) -> bool {
202 self.kind == other.kind && self.component_patch == other.component_patch
203 }
204
205 pub fn get_component<'a, T: components::DataComponentTrait>(&'a self) -> Option<Cow<'a, T>> {
210 if let Some(c) = self.component_patch.get::<T>() {
211 Some(Cow::Borrowed(c))
212 } else {
213 get_default_component::<T>(self.kind).map(|c| Cow::Owned(c))
214 }
215 }
216}
217
218impl AzaleaRead for ItemStack {
219 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
220 let count = i32::azalea_read_var(buf)?;
221 if count <= 0 {
222 Ok(ItemStack::Empty)
223 } else {
224 let kind = azalea_registry::Item::azalea_read(buf)?;
225 let component_patch = DataComponentPatch::azalea_read(buf)?;
226 Ok(ItemStack::Present(ItemStackData {
227 count,
228 kind,
229 component_patch,
230 }))
231 }
232 }
233}
234
235impl AzaleaWrite for ItemStack {
236 fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
237 match self {
238 ItemStack::Empty => 0_i32.azalea_write_var(buf)?,
239 ItemStack::Present(i) => {
240 i.count.azalea_write_var(buf)?;
241 i.kind.azalea_write(buf)?;
242 i.component_patch.azalea_write(buf)?;
243 }
244 };
245 Ok(())
246 }
247}
248
249impl From<ItemStackData> for ItemStack {
250 fn from(item: ItemStackData) -> Self {
251 if item.is_empty() {
252 ItemStack::Empty
253 } else {
254 ItemStack::Present(item)
255 }
256 }
257}
258impl From<Item> for ItemStack {
259 fn from(item: Item) -> Self {
260 ItemStack::new(item, 1)
261 }
262}
263impl From<(Item, i32)> for ItemStack {
264 fn from(item: (Item, i32)) -> Self {
265 ItemStack::new(item.0, item.1)
266 }
267}
268impl From<Item> for ItemStackData {
269 fn from(item: Item) -> Self {
270 ItemStackData::new(item, 1)
271 }
272}
273impl From<(Item, i32)> for ItemStackData {
274 fn from(item: (Item, i32)) -> Self {
275 ItemStackData::new(item.0, item.1)
276 }
277}
278
279#[derive(Default)]
284pub struct DataComponentPatch {
285 components: IndexMap<DataComponentKind, Option<DataComponentUnion>>,
286}
287
288impl DataComponentPatch {
289 pub fn get<T: components::DataComponentTrait>(&self) -> Option<&T> {
301 let component = self.get_kind(T::KIND)?;
302 let component_any = component as &dyn Any;
303 component_any.downcast_ref::<T>()
304 }
305
306 pub fn get_kind(
307 &self,
308 kind: DataComponentKind,
309 ) -> Option<&dyn components::EncodableDataComponent> {
310 self.components.get(&kind).and_then(|c| {
311 c.as_ref().map(|c| {
312 unsafe { c.as_kind(kind) }
315 })
316 })
317 }
318
319 pub fn has<T: components::DataComponentTrait>(&self) -> bool {
330 self.has_kind(T::KIND)
331 }
332
333 pub fn has_kind(&self, kind: DataComponentKind) -> bool {
334 self.get_kind(kind).is_some()
335 }
336
337 pub fn iter<'a>(
338 &'a self,
339 ) -> impl Iterator<
340 Item = (
341 DataComponentKind,
342 Option<&'a dyn components::EncodableDataComponent>,
343 ),
344 > + 'a {
345 self.components.iter().map(|(&kind, component)| {
346 component.as_ref().map_or_else(
347 || (kind, None),
348 |c| (kind, unsafe { Some(c.as_kind(kind)) }),
349 )
350 })
351 }
352 pub unsafe fn unchecked_insert_component(
357 &mut self,
358 kind: DataComponentKind,
359 value: Option<DataComponentUnion>,
360 ) {
361 self.components.insert(kind, value);
362 }
363}
364
365impl Drop for DataComponentPatch {
366 fn drop(&mut self) {
367 for (kind, component) in &mut self.components {
369 if let Some(component) = component {
370 unsafe { component.drop_as(*kind) };
372 }
373 }
374 }
375}
376
377impl AzaleaRead for DataComponentPatch {
378 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
379 let components_with_data_count = u32::azalea_read_var(buf)?;
380 let components_without_data_count = u32::azalea_read_var(buf)?;
381
382 if components_without_data_count == 0 && components_with_data_count == 0 {
383 return Ok(DataComponentPatch::default());
384 }
385
386 let mut components = IndexMap::new();
387 for _ in 0..components_with_data_count {
388 let component_kind = DataComponentKind::azalea_read(buf)?;
389 let component_data = DataComponentUnion::azalea_read_as(component_kind, buf)?;
390 components.insert(component_kind, Some(component_data));
391 }
392
393 for _ in 0..components_without_data_count {
394 let component_kind = DataComponentKind::azalea_read(buf)?;
395 components.insert(component_kind, None);
396 }
397
398 Ok(DataComponentPatch { components })
399 }
400}
401
402impl AzaleaWrite for DataComponentPatch {
403 fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
404 let mut components_with_data_count: u32 = 0;
405 let mut components_without_data_count: u32 = 0;
406 for component in self.components.values() {
407 if component.is_some() {
408 components_with_data_count += 1;
409 } else {
410 components_without_data_count += 1;
411 }
412 }
413
414 components_with_data_count.azalea_write_var(buf)?;
415 components_without_data_count.azalea_write_var(buf)?;
416
417 let mut component_buf = Vec::new();
418 for (kind, component) in &self.components {
419 if let Some(component) = component {
420 kind.azalea_write(buf)?;
421
422 component_buf.clear();
423 unsafe { component.azalea_write_as(*kind, &mut component_buf) }?;
425 buf.write_all(&component_buf)?;
426 }
427 }
428
429 for (kind, component) in &self.components {
430 if component.is_none() {
431 kind.azalea_write(buf)?;
432 }
433 }
434
435 Ok(())
436 }
437}
438
439impl Clone for DataComponentPatch {
440 fn clone(&self) -> Self {
441 let mut components = IndexMap::with_capacity(self.components.len());
442 for (kind, component) in &self.components {
443 components.insert(
444 *kind,
445 component.as_ref().map(|c| unsafe { c.clone_as(*kind) }),
446 );
447 }
448 DataComponentPatch { components }
449 }
450}
451impl fmt::Debug for DataComponentPatch {
452 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
453 f.debug_set().entries(self.components.keys()).finish()
454 }
455}
456impl PartialEq for DataComponentPatch {
457 fn eq(&self, other: &Self) -> bool {
458 if self.components.len() != other.components.len() {
459 return false;
460 }
461 for (kind, component) in &self.components {
462 let Some(other_component) = other.components.get(kind) else {
463 return false;
464 };
465 if let Some(component) = component {
467 let Some(other_component) = other_component else {
468 return false;
469 };
470 if !unsafe { component.eq_as(other_component, *kind) } {
473 return false;
474 }
475 } else if other_component.is_some() {
476 return false;
477 }
478 }
479 true
480 }
481}
482
483impl Serialize for DataComponentPatch {
484 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
485 where
486 S: serde::Serializer,
487 {
488 let mut s = serializer.serialize_map(Some(self.components.len()))?;
489 for (kind, component) in &self.components {
490 if let Some(component) = component {
491 unsafe { component.serialize_entry_as(&mut s, *kind) }?;
492 } else {
493 #[derive(Serialize)]
494 struct EmptyComponent;
495 s.serialize_entry(&format!("!{kind}"), &EmptyComponent)?;
496 }
497 }
498 s.end()
499 }
500}
501
502#[cfg(test)]
503mod tests {
504 use super::*;
505 use crate::components::MapId;
506
507 #[test]
508 fn test_get_component() {
509 let item = ItemStack::from(Item::Map).with_component(MapId { id: 1 });
510 let map_id = item.get_component::<MapId>().unwrap();
511 assert_eq!(map_id.id, 1);
512 }
513}