1use std::fmt::Debug;
2use std::io::Write;
3
4use chunkedge_binary::{Encode, VarInt};
5use chunkedge_generated::item::ItemKind;
6
7use crate::components::{ItemComponent, Patchable};
8use crate::vanilla_components::ItemKindExt;
9use crate::NUM_ITEM_COMPONENTS;
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 encode_recursive<W: Write>(
201 &self,
202 mut w: W,
203 prefixed: bool,
204 ) -> Result<(), anyhow::Error> {
205 if self.is_empty() {
206 VarInt(0).encode(w)
207 } else {
208 let w: &mut dyn Write = &mut w;
210
211 VarInt(i32::from(self.count)).encode(&mut *w)?;
212 self.item.encode(&mut *w)?;
213
214 let mut added = Vec::new();
215 let mut removed = Vec::new();
216
217 for (i, patch) in self.components.iter().enumerate() {
218 match patch {
219 Patchable::Added((comp, _)) => added.push((i, comp)),
220 Patchable::Removed => removed.push(i),
221 _ => {}
222 }
223 }
224
225 VarInt(added.len() as i32).encode(&mut *w)?;
227 VarInt(removed.len() as i32).encode(&mut *w)?;
228
229 for (id, comp) in added {
230 VarInt(id as i32).encode(&mut *w)?;
231 if prefixed {
232 struct ByteCounter {
238 count: usize,
239 }
240
241 impl Write for ByteCounter {
242 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
243 self.count += buf.len();
244 Ok(buf.len())
245 }
246
247 fn flush(&mut self) -> std::io::Result<()> {
248 Ok(())
249 }
250 }
251
252 let mut counter = ByteCounter { count: 0 };
254 comp.encode(&mut counter)?;
255
256 VarInt(counter.count as i32).encode(&mut *w)?;
258
259 comp.encode(&mut *w)?;
261 } else {
262 comp.encode(&mut *w)?;
263 }
264 }
265
266 for id in removed {
267 VarInt(id as i32).encode(&mut *w)?;
268 }
269
270 Ok(())
271 }
272 }
273}