1use std::{
2 any::Any,
3 fmt,
4 io::{Cursor, Write},
5};
6
7use azalea_buf::{AzaleaRead, AzaleaReadVar, AzaleaWrite, AzaleaWriteVar, BufReadError};
8use azalea_registry::DataComponentKind;
9use indexmap::IndexMap;
10
11use crate::components::{self};
12
13#[derive(Debug, Clone, Default, PartialEq)]
15pub enum ItemStack {
16 #[default]
17 Empty,
18 Present(ItemStackData),
19}
20
21impl ItemStack {
22 pub fn is_empty(&self) -> bool {
27 match self {
28 ItemStack::Empty => true,
29 ItemStack::Present(item) => item.is_empty(),
30 }
31 }
32 pub fn is_present(&self) -> bool {
37 !self.is_empty()
38 }
39
40 pub fn count(&self) -> i32 {
45 match self {
46 ItemStack::Empty => 0,
47 ItemStack::Present(i) => i.count,
48 }
49 }
50
51 pub fn split(&mut self, count: u32) -> ItemStack {
53 match self {
54 ItemStack::Empty => ItemStack::Empty,
55 ItemStack::Present(i) => {
56 let returning = i.split(count);
57 if i.is_empty() {
58 *self = ItemStack::Empty;
59 }
60 ItemStack::Present(returning)
61 }
62 }
63 }
64
65 pub fn kind(&self) -> azalea_registry::Item {
68 match self {
69 ItemStack::Empty => azalea_registry::Item::Air,
70 ItemStack::Present(i) => i.kind,
71 }
72 }
73
74 pub fn update_empty(&mut self) {
76 if let ItemStack::Present(i) = self {
77 if i.is_empty() {
78 *self = ItemStack::Empty;
79 }
80 }
81 }
82
83 pub fn as_present(&self) -> Option<&ItemStackData> {
85 match self {
86 ItemStack::Empty => None,
87 ItemStack::Present(i) => Some(i),
88 }
89 }
90}
91
92#[derive(Debug, Clone, PartialEq)]
95pub struct ItemStackData {
96 pub count: i32,
100 pub kind: azalea_registry::Item,
101 pub components: DataComponentPatch,
102}
103
104impl ItemStackData {
105 pub fn split(&mut self, count: u32) -> ItemStackData {
107 let returning_count = i32::min(count as i32, self.count);
108 let mut returning = self.clone();
109 returning.count = returning_count;
110 self.count -= returning_count;
111 returning
112 }
113
114 pub fn is_empty(&self) -> bool {
116 self.count <= 0 || self.kind == azalea_registry::Item::Air
117 }
118
119 pub fn is_same_item_and_components(&self, other: &ItemStackData) -> bool {
140 self.kind == other.kind && self.components == other.components
141 }
142}
143
144impl AzaleaRead for ItemStack {
145 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
146 let count = i32::azalea_read_var(buf)?;
147 if count <= 0 {
148 Ok(ItemStack::Empty)
149 } else {
150 let kind = azalea_registry::Item::azalea_read(buf)?;
151 let components = DataComponentPatch::azalea_read(buf)?;
152 Ok(ItemStack::Present(ItemStackData {
153 count,
154 kind,
155 components,
156 }))
157 }
158 }
159}
160
161impl AzaleaWrite for ItemStack {
162 fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
163 match self {
164 ItemStack::Empty => 0_i32.azalea_write_var(buf)?,
165 ItemStack::Present(i) => {
166 i.count.azalea_write_var(buf)?;
167 i.kind.azalea_write(buf)?;
168 i.components.azalea_write(buf)?;
169 }
170 };
171 Ok(())
172 }
173}
174
175#[derive(Default)]
180pub struct DataComponentPatch {
181 components: IndexMap<DataComponentKind, Option<Box<dyn components::EncodableDataComponent>>>,
182}
183
184impl DataComponentPatch {
185 pub fn get<T: components::DataComponent>(&self) -> Option<&T> {
197 let component = self.components.get(&T::KIND).and_then(|c| c.as_deref())?;
198 let component_any = component as &dyn Any;
199 component_any.downcast_ref::<T>()
200 }
201
202 pub fn get_kind(
203 &self,
204 kind: DataComponentKind,
205 ) -> Option<&dyn components::EncodableDataComponent> {
206 self.components.get(&kind).and_then(|c| c.as_deref())
207 }
208
209 pub fn has<T: components::DataComponent>(&self) -> bool {
224 self.has_kind(T::KIND)
225 }
226
227 pub fn has_kind(&self, kind: DataComponentKind) -> bool {
228 self.get_kind(kind).is_some()
229 }
230}
231
232impl AzaleaRead for DataComponentPatch {
233 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
234 let components_with_data_count = u32::azalea_read_var(buf)?;
235 let components_without_data_count = u32::azalea_read_var(buf)?;
236
237 if components_without_data_count == 0 && components_with_data_count == 0 {
238 return Ok(DataComponentPatch::default());
239 }
240
241 let mut components = IndexMap::new();
242 for _ in 0..components_with_data_count {
243 let component_kind = DataComponentKind::azalea_read(buf)?;
244 let component_data = components::from_kind(component_kind, buf)?;
245 components.insert(component_kind, Some(component_data));
246 }
247
248 for _ in 0..components_without_data_count {
249 let component_kind = DataComponentKind::azalea_read(buf)?;
250 components.insert(component_kind, None);
251 }
252
253 Ok(DataComponentPatch { components })
254 }
255}
256
257impl AzaleaWrite for DataComponentPatch {
258 fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
259 let mut components_with_data_count: u32 = 0;
260 let mut components_without_data_count: u32 = 0;
261 for component in self.components.values() {
262 if component.is_some() {
263 components_with_data_count += 1;
264 } else {
265 components_without_data_count += 1;
266 }
267 }
268
269 components_with_data_count.azalea_write_var(buf)?;
270 components_without_data_count.azalea_write_var(buf)?;
271
272 let mut component_buf = Vec::new();
273 for (kind, component) in &self.components {
274 if let Some(component) = component {
275 kind.azalea_write(buf)?;
276
277 component_buf.clear();
278 component.encode(&mut component_buf)?;
279 buf.write_all(&component_buf)?;
280 }
281 }
282
283 for (kind, component) in &self.components {
284 if component.is_none() {
285 kind.azalea_write(buf)?;
286 }
287 }
288
289 Ok(())
290 }
291}
292
293impl Clone for DataComponentPatch {
294 fn clone(&self) -> Self {
295 let mut components = IndexMap::with_capacity(self.components.len());
296 for (kind, component) in &self.components {
297 components.insert(*kind, component.as_ref().map(|c| (*c).clone()));
298 }
299 DataComponentPatch { components }
300 }
301}
302impl fmt::Debug for DataComponentPatch {
303 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
304 f.debug_set().entries(self.components.keys()).finish()
305 }
306}
307impl PartialEq for DataComponentPatch {
308 fn eq(&self, other: &Self) -> bool {
309 if self.components.len() != other.components.len() {
310 return false;
311 }
312 for (kind, component) in &self.components {
313 if let Some(other_component) = other.components.get(kind) {
314 if let Some(component) = component {
316 if let Some(other_component) = other_component {
317 if !component.eq((*other_component).clone()) {
318 return false;
319 }
320 } else {
321 return false;
322 }
323 } else if other_component.is_some() {
324 return false;
325 }
326 } else {
327 return false;
328 }
329 }
330 true
331 }
332}