Skip to main content

steel_registry/data_component_predicate/
basic.rs

1use super::*;
2
3/// Durability and current-damage bounds.
4#[derive(Debug, Clone, PartialEq, Eq)]
5pub struct DamagePredicate {
6    durability: IntBounds,
7    damage: IntBounds,
8}
9
10impl DamagePredicate {
11    #[must_use]
12    pub const fn new(durability: IntBounds, damage: IntBounds) -> Self {
13        Self { durability, damage }
14    }
15
16    #[must_use]
17    pub const fn durability(&self) -> IntBounds {
18        self.durability
19    }
20
21    #[must_use]
22    pub const fn damage(&self) -> IntBounds {
23        self.damage
24    }
25}
26
27impl DataComponentPredicateCodec for DamagePredicate {
28    fn from_nbt_value(tag: &NbtTag) -> Option<Self> {
29        let compound = tag.compound()?;
30        Some(Self::new(
31            compound
32                .get("durability")
33                .map_or(Some(IntBounds::ANY), IntBounds::from_owned_nbt)?,
34            compound
35                .get("damage")
36                .map_or(Some(IntBounds::ANY), IntBounds::from_owned_nbt)?,
37        ))
38    }
39
40    fn to_nbt_value(&self) -> NbtTag {
41        let mut compound = NbtCompound::new();
42        if !self.durability.is_any() {
43            compound.insert("durability", self.durability.as_nbt_tag());
44        }
45        if !self.damage.is_any() {
46            compound.insert("damage", self.damage.as_nbt_tag());
47        }
48        NbtTag::Compound(compound)
49    }
50}
51
52impl HashComponent for DamagePredicate {
53    fn hash_component(&self, hasher: &mut ComponentHasher) {
54        hash_nbt_codec(self, hasher);
55    }
56}
57
58impl_predicate_downcast_type!(DamagePredicate, "steel:data_component_predicate/damage");
59
60/// One enchantment holder-set and accepted level range.
61#[derive(Debug, Clone, PartialEq)]
62pub struct EnchantmentPredicate {
63    enchantments: Option<RegistryHolderSet<Enchantment>>,
64    levels: IntBounds,
65}
66
67impl EnchantmentPredicate {
68    #[must_use]
69    pub const fn new(
70        enchantments: Option<RegistryHolderSet<Enchantment>>,
71        levels: IntBounds,
72    ) -> Self {
73        Self {
74            enchantments,
75            levels,
76        }
77    }
78
79    #[must_use]
80    pub const fn enchantments(&self) -> Option<&RegistryHolderSet<Enchantment>> {
81        self.enchantments.as_ref()
82    }
83
84    #[must_use]
85    pub const fn levels(&self) -> IntBounds {
86        self.levels
87    }
88
89    fn from_nbt_value(tag: &NbtTag) -> Option<Self> {
90        let compound = tag.compound()?;
91        Some(Self::new(
92            decode_optional(compound, "enchantments", RegistryHolderSet::from_owned_nbt)?,
93            compound
94                .get("levels")
95                .map_or(Some(IntBounds::ANY), IntBounds::from_owned_nbt)?,
96        ))
97    }
98
99    fn to_nbt_value(&self) -> NbtTag {
100        let mut compound = NbtCompound::new();
101        if let Some(enchantments) = &self.enchantments {
102            compound.insert("enchantments", enchantments.clone().to_nbt_tag());
103        }
104        if !self.levels.is_any() {
105            compound.insert("levels", self.levels.as_nbt_tag());
106        }
107        NbtTag::Compound(compound)
108    }
109}
110
111/// Applied-enchantment predicates.
112#[derive(Debug, Clone, PartialEq)]
113pub struct EnchantmentsPredicate(Vec<EnchantmentPredicate>);
114
115impl EnchantmentsPredicate {
116    #[must_use]
117    pub const fn new(enchantments: Vec<EnchantmentPredicate>) -> Self {
118        Self(enchantments)
119    }
120
121    #[must_use]
122    pub fn enchantments(&self) -> &[EnchantmentPredicate] {
123        &self.0
124    }
125}
126
127impl DataComponentPredicateCodec for EnchantmentsPredicate {
128    fn from_nbt_value(tag: &NbtTag) -> Option<Self> {
129        decode_list(tag, EnchantmentPredicate::from_nbt_value).map(Self)
130    }
131
132    fn to_nbt_value(&self) -> NbtTag {
133        encode_list(&self.0, EnchantmentPredicate::to_nbt_value)
134    }
135}
136
137impl HashComponent for EnchantmentsPredicate {
138    fn hash_component(&self, hasher: &mut ComponentHasher) {
139        hash_nbt_codec(self, hasher);
140    }
141}
142
143impl_predicate_downcast_type!(
144    EnchantmentsPredicate,
145    "steel:data_component_predicate/enchantments"
146);
147
148/// Stored-enchantment predicates.
149#[derive(Debug, Clone, PartialEq)]
150pub struct StoredEnchantmentsPredicate(Vec<EnchantmentPredicate>);
151
152impl StoredEnchantmentsPredicate {
153    #[must_use]
154    pub const fn new(enchantments: Vec<EnchantmentPredicate>) -> Self {
155        Self(enchantments)
156    }
157
158    #[must_use]
159    pub fn enchantments(&self) -> &[EnchantmentPredicate] {
160        &self.0
161    }
162}
163
164impl DataComponentPredicateCodec for StoredEnchantmentsPredicate {
165    fn from_nbt_value(tag: &NbtTag) -> Option<Self> {
166        decode_list(tag, EnchantmentPredicate::from_nbt_value).map(Self)
167    }
168
169    fn to_nbt_value(&self) -> NbtTag {
170        encode_list(&self.0, EnchantmentPredicate::to_nbt_value)
171    }
172}
173
174impl HashComponent for StoredEnchantmentsPredicate {
175    fn hash_component(&self, hasher: &mut ComponentHasher) {
176        hash_nbt_codec(self, hasher);
177    }
178}
179
180impl_predicate_downcast_type!(
181    StoredEnchantmentsPredicate,
182    "steel:data_component_predicate/stored_enchantments"
183);
184
185/// Accepted registered potion values.
186#[derive(Debug, Clone, PartialEq)]
187pub struct PotionsPredicate(RegistryHolderSet<Potion>);
188
189impl PotionsPredicate {
190    #[must_use]
191    pub const fn new(potions: RegistryHolderSet<Potion>) -> Self {
192        Self(potions)
193    }
194
195    #[must_use]
196    pub const fn potions(&self) -> &RegistryHolderSet<Potion> {
197        &self.0
198    }
199}
200
201impl DataComponentPredicateCodec for PotionsPredicate {
202    fn from_nbt_value(tag: &NbtTag) -> Option<Self> {
203        RegistryHolderSet::from_owned_nbt(tag).map(Self)
204    }
205
206    fn to_nbt_value(&self) -> NbtTag {
207        self.0.clone().to_nbt_tag()
208    }
209}
210
211impl HashComponent for PotionsPredicate {
212    fn hash_component(&self, hasher: &mut ComponentHasher) {
213        self.0.hash_component(hasher);
214    }
215}
216
217impl_predicate_downcast_type!(
218    PotionsPredicate,
219    "steel:data_component_predicate/potion_contents"
220);
221
222/// Partial custom-data NBT predicate.
223#[derive(Debug, Clone, PartialEq)]
224pub struct CustomDataPredicate(NbtPredicate);
225
226impl CustomDataPredicate {
227    #[must_use]
228    pub const fn new(value: NbtPredicate) -> Self {
229        Self(value)
230    }
231
232    #[must_use]
233    pub const fn value(&self) -> &NbtPredicate {
234        &self.0
235    }
236}
237
238impl DataComponentPredicateCodec for CustomDataPredicate {
239    fn from_nbt_value(tag: &NbtTag) -> Option<Self> {
240        NbtPredicate::from_owned_nbt(tag).map(Self)
241    }
242
243    fn to_nbt_value(&self) -> NbtTag {
244        self.0.to_nbt_tag_ref()
245    }
246}
247
248impl HashComponent for CustomDataPredicate {
249    fn hash_component(&self, hasher: &mut ComponentHasher) {
250        self.0.hash_component(hasher);
251    }
252}
253
254impl_predicate_downcast_type!(
255    CustomDataPredicate,
256    "steel:data_component_predicate/custom_data"
257);
258
259/// Nested item predicates over container contents.
260#[derive(Debug, Clone, PartialEq)]
261pub struct ContainerPredicate(Option<CollectionPredicate<ItemPredicate>>);
262
263impl ContainerPredicate {
264    #[must_use]
265    pub const fn new(items: Option<CollectionPredicate<ItemPredicate>>) -> Self {
266        Self(items)
267    }
268
269    #[must_use]
270    pub const fn items(&self) -> Option<&CollectionPredicate<ItemPredicate>> {
271        self.0.as_ref()
272    }
273}
274
275impl DataComponentPredicateCodec for ContainerPredicate {
276    fn from_nbt_value(tag: &NbtTag) -> Option<Self> {
277        let compound = tag.compound()?;
278        decode_optional(compound, "items", |tag| {
279            CollectionPredicate::from_nbt_with(tag, ItemPredicate::from_owned_nbt)
280        })
281        .map(Self)
282    }
283
284    fn to_nbt_value(&self) -> NbtTag {
285        collection_field_nbt(self.0.as_ref(), "items", ItemPredicate::to_nbt_tag_ref)
286    }
287}
288
289impl HashComponent for ContainerPredicate {
290    fn hash_component(&self, hasher: &mut ComponentHasher) {
291        hash_optional_collection_field(
292            self.0.as_ref(),
293            "items",
294            hasher,
295            HashComponent::compute_hash,
296        );
297    }
298}
299
300impl_predicate_downcast_type!(
301    ContainerPredicate,
302    "steel:data_component_predicate/container"
303);
304
305/// Nested item predicates over bundle contents.
306#[derive(Debug, Clone, PartialEq)]
307pub struct BundlePredicate(Option<CollectionPredicate<ItemPredicate>>);
308
309impl BundlePredicate {
310    #[must_use]
311    pub const fn new(items: Option<CollectionPredicate<ItemPredicate>>) -> Self {
312        Self(items)
313    }
314
315    #[must_use]
316    pub const fn items(&self) -> Option<&CollectionPredicate<ItemPredicate>> {
317        self.0.as_ref()
318    }
319}
320
321impl DataComponentPredicateCodec for BundlePredicate {
322    fn from_nbt_value(tag: &NbtTag) -> Option<Self> {
323        let compound = tag.compound()?;
324        decode_optional(compound, "items", |tag| {
325            CollectionPredicate::from_nbt_with(tag, ItemPredicate::from_owned_nbt)
326        })
327        .map(Self)
328    }
329
330    fn to_nbt_value(&self) -> NbtTag {
331        collection_field_nbt(self.0.as_ref(), "items", ItemPredicate::to_nbt_tag_ref)
332    }
333}
334
335impl HashComponent for BundlePredicate {
336    fn hash_component(&self, hasher: &mut ComponentHasher) {
337        hash_optional_collection_field(
338            self.0.as_ref(),
339            "items",
340            hasher,
341            HashComponent::compute_hash,
342        );
343    }
344}
345
346impl_predicate_downcast_type!(
347    BundlePredicate,
348    "steel:data_component_predicate/bundle_contents"
349);