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 pub components:
182 IndexMap<DataComponentKind, Option<Box<dyn components::EncodableDataComponent>>>,
183}
184
185impl DataComponentPatch {
186 pub fn get<T: components::DataComponent>(&self) -> Option<&T> {
198 let component = self.components.get(&T::KIND).and_then(|c| c.as_deref())?;
199 let component_any = component as &dyn Any;
200 component_any.downcast_ref::<T>()
201 }
202
203 pub fn get_kind(
204 &self,
205 kind: DataComponentKind,
206 ) -> Option<&dyn components::EncodableDataComponent> {
207 self.components.get(&kind).and_then(|c| c.as_deref())
208 }
209
210 pub fn has<T: components::DataComponent>(&self) -> bool {
225 self.has_kind(T::KIND)
226 }
227
228 pub fn has_kind(&self, kind: DataComponentKind) -> bool {
229 self.get_kind(kind).is_some()
230 }
231}
232
233impl AzaleaRead for DataComponentPatch {
234 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
235 let components_with_data_count = u32::azalea_read_var(buf)?;
236 let components_without_data_count = u32::azalea_read_var(buf)?;
237
238 if components_without_data_count == 0 && components_with_data_count == 0 {
239 return Ok(DataComponentPatch::default());
240 }
241
242 let mut components = IndexMap::new();
243 for _ in 0..components_with_data_count {
244 let component_kind = DataComponentKind::azalea_read(buf)?;
245 let component_data = components::from_kind(component_kind, buf)?;
246 components.insert(component_kind, Some(component_data));
247 }
248
249 for _ in 0..components_without_data_count {
250 let component_kind = DataComponentKind::azalea_read(buf)?;
251 components.insert(component_kind, None);
252 }
253
254 Ok(DataComponentPatch { components })
255 }
256}
257
258impl AzaleaWrite for DataComponentPatch {
259 fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
260 let mut components_with_data_count: u32 = 0;
261 let mut components_without_data_count: u32 = 0;
262 for component in self.components.values() {
263 if component.is_some() {
264 components_with_data_count += 1;
265 } else {
266 components_without_data_count += 1;
267 }
268 }
269
270 components_with_data_count.azalea_write_var(buf)?;
271 components_without_data_count.azalea_write_var(buf)?;
272
273 let mut component_buf = Vec::new();
274 for (kind, component) in &self.components {
275 if let Some(component) = component {
276 kind.azalea_write(buf)?;
277
278 component_buf.clear();
279 component.encode(&mut component_buf)?;
280 buf.write_all(&component_buf)?;
281 }
282 }
283
284 for (kind, component) in &self.components {
285 if component.is_none() {
286 kind.azalea_write(buf)?;
287 }
288 }
289
290 Ok(())
291 }
292}
293
294impl Clone for DataComponentPatch {
295 fn clone(&self) -> Self {
296 let mut components = IndexMap::with_capacity(self.components.len());
297 for (kind, component) in &self.components {
298 components.insert(*kind, component.as_ref().map(|c| (*c).clone()));
299 }
300 DataComponentPatch { components }
301 }
302}
303impl fmt::Debug for DataComponentPatch {
304 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
305 f.debug_set().entries(self.components.keys()).finish()
306 }
307}
308impl PartialEq for DataComponentPatch {
309 fn eq(&self, other: &Self) -> bool {
310 if self.components.len() != other.components.len() {
311 return false;
312 }
313 for (kind, component) in &self.components {
314 match other.components.get(kind) {
315 Some(other_component) => {
316 if let Some(component) = component {
318 if let Some(other_component) = other_component {
319 if !component.eq((*other_component).clone()) {
320 return false;
321 }
322 } else {
323 return false;
324 }
325 } else if other_component.is_some() {
326 return false;
327 }
328 }
329 _ => {
330 return false;
331 }
332 }
333 }
334 true
335 }
336}