1use std::fmt::Debug;
2use std::io::Write;
3
4use chunkedge_binary::{Encode, VarInt};
5use chunkedge_generated::item::ItemKind;
6
7use crate::NUM_ITEM_COMPONENTS;
8use crate::components::{ItemComponent, Patchable};
9use crate::vanilla_components::ItemKindExt;
10
11#[derive(Clone, PartialEq)]
13pub struct ItemStack {
14 pub item: ItemKind,
15 pub count: i8,
16 pub(crate) components: [Patchable<Box<ItemComponent>>; NUM_ITEM_COMPONENTS],
17}
18
19impl Default for ItemStack {
20 fn default() -> Self {
21 ItemStack::EMPTY
22 }
23}
24
25impl Debug for ItemStack {
26 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27 f.debug_struct("ItemStack")
28 .field("item", &self.item)
29 .field("count", &self.count)
30 .field(
31 "components",
32 &self
33 .components
34 .iter()
35 .enumerate()
36 .filter_map(|(i, c)| c.as_option().map(|comp| (i, comp)))
37 .collect::<Vec<_>>(),
38 )
39 .finish()
40 }
41}
42
43#[derive(Clone, PartialEq, Debug)]
44pub struct HashedItemStack {
45 pub item: ItemKind,
46 pub count: i8,
47 pub(crate) components: [Patchable<()>; NUM_ITEM_COMPONENTS],
48}
49impl HashedItemStack {
50 pub const EMPTY: Self = Self {
51 item: ItemKind::Air,
52 count: 0,
53 components: [const { Patchable::None }; NUM_ITEM_COMPONENTS],
54 };
55
56 #[must_use]
57 pub const fn new(item: ItemKind, count: i8) -> Self {
58 Self {
59 item,
60 count,
61 components: [const { Patchable::None }; NUM_ITEM_COMPONENTS],
62 }
63 }
64
65 pub const fn is_empty(&self) -> bool {
66 matches!(self.item, ItemKind::Air) || self.count <= 0
67 }
68}
69
70impl From<ItemStack> for HashedItemStack {
71 fn from(stack: ItemStack) -> Self {
72 Self {
73 item: stack.item,
74 count: stack.count,
75 components: stack.components.map(|c| match c {
76 Patchable::Default(_) => Patchable::Default(()),
77 Patchable::Added((_, h)) => Patchable::Added(((), h)),
78 Patchable::Removed => Patchable::Removed,
79 Patchable::None => Patchable::None,
80 }),
81 }
82 }
83}
84
85impl ItemStack {
86 pub const EMPTY: ItemStack = ItemStack {
87 item: ItemKind::Air,
88 count: 0,
89 components: [const { Patchable::None }; NUM_ITEM_COMPONENTS],
90 };
91
92 #[must_use]
94 pub const fn new(item: ItemKind, count: i8) -> Self {
95 Self {
96 item,
97 count,
98 components: [const { Patchable::None }; NUM_ITEM_COMPONENTS],
99 }
100 }
101
102 pub fn new_vanilla(item: ItemKind, count: i8) -> Self {
105 let components = item.default_components();
106 Self {
107 item,
108 count,
109 components,
110 }
111 }
112
113 pub fn components(&self) -> Vec<&ItemComponent> {
115 self.components
116 .iter()
117 .filter_map(|component| component.as_option())
118 .map(|boxed| &**boxed)
119 .collect()
120 }
121
122 pub fn default_components(&self) -> Vec<ItemComponent> {
124 self.item
125 .default_components()
126 .iter()
127 .filter_map(|component| component.as_option().map(|b| &**b))
128 .cloned()
129 .collect()
130 }
131
132 pub fn insert_component(&mut self, component: ItemComponent) {
134 let id = component.id() as usize;
135 if let Patchable::Default(default) = &self.components[id] {
136 if **default == component {
138 return;
139 }
140 }
141
142 let hash = component.hash();
143 self.components[id] = Patchable::Added((Box::new(component), hash));
144 }
145
146 pub fn remove_component<I: Into<usize>>(&mut self, id: I) -> Option<ItemComponent> {
151 let id = id.into();
152 if id < NUM_ITEM_COMPONENTS {
153 std::mem::replace(&mut self.components[id], Patchable::Removed)
154 .to_option()
155 .map(|boxed| *boxed)
156 } else {
157 None
158 }
159 }
160
161 pub fn get_component<I: Into<usize>>(&self, id: I) -> Option<&ItemComponent> {
163 let id = id.into();
164 if id < NUM_ITEM_COMPONENTS {
165 match &self.components[id] {
166 Patchable::Added((component, _)) | Patchable::Default(component) => {
167 Some(&**component)
168 }
169 _ => None,
170 }
171 } else {
172 None
173 }
174 }
175
176 #[must_use]
177 pub const fn with_count(mut self, count: i8) -> Self {
178 self.count = count;
179 self
180 }
181
182 #[must_use]
183 pub const fn with_item(mut self, item: ItemKind) -> Self {
184 self.item = item;
185 self
186 }
187
188 #[must_use]
189 pub fn with_components(mut self, components: Vec<ItemComponent>) -> Self {
190 for component in components {
191 self.insert_component(component);
192 }
193 self
194 }
195
196 pub const fn is_empty(&self) -> bool {
197 matches!(self.item, ItemKind::Air) || self.count <= 0
198 }
199
200 pub fn is_same_item_kind_and_same_components(&self, other: &Self) -> bool {
203 self.item == other.item && self.components == other.components
204 }
205
206 pub fn encode_recursive<W: Write>(
207 &self,
208 mut w: W,
209 prefixed: bool,
210 ) -> Result<(), anyhow::Error> {
211 if self.is_empty() {
212 VarInt(0).encode(w)
213 } else {
214 let w: &mut dyn Write = &mut w;
216
217 VarInt(i32::from(self.count)).encode(&mut *w)?;
218 self.item.encode(&mut *w)?;
219
220 let mut added = Vec::new();
221 let mut removed = Vec::new();
222
223 for (i, patch) in self.components.iter().enumerate() {
224 match patch {
225 Patchable::Added((comp, _)) => added.push((i, comp)),
226 Patchable::Removed => removed.push(i),
227 _ => {}
228 }
229 }
230
231 VarInt(added.len() as i32).encode(&mut *w)?;
233 VarInt(removed.len() as i32).encode(&mut *w)?;
234
235 for (id, comp) in added {
236 VarInt(id as i32).encode(&mut *w)?;
237 if prefixed {
238 struct ByteCounter {
244 count: usize,
245 }
246
247 impl Write for ByteCounter {
248 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
249 self.count += buf.len();
250 Ok(buf.len())
251 }
252
253 fn flush(&mut self) -> std::io::Result<()> {
254 Ok(())
255 }
256 }
257
258 let mut counter = ByteCounter { count: 0 };
260 comp.encode(&mut counter)?;
261
262 VarInt(counter.count as i32).encode(&mut *w)?;
264
265 comp.encode(&mut *w)?;
267 } else {
268 comp.encode(&mut *w)?;
269 }
270 }
271
272 for id in removed {
273 VarInt(id as i32).encode(&mut *w)?;
274 }
275
276 Ok(())
277 }
278 }
279}