Skip to main content

steel_registry/data_component_predicate/
fireworks.rs

1use super::{
2    CollectionPredicate, ComponentHasher, DataComponentPredicateCodec, Debug, DowncastType,
3    DowncastTypeKey, HashComponent, IntBounds, NbtCompound, NbtNumeric, NbtTag, decode_optional,
4    hash_entries, push_hash_entry,
5};
6
7/// Fields matched within one firework explosion.
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct FireworkPredicate {
10    shape: Option<crate::data_components::components::FireworkExplosionShape>,
11    has_twinkle: Option<bool>,
12    has_trail: Option<bool>,
13}
14
15impl FireworkPredicate {
16    #[must_use]
17    pub const fn new(
18        shape: Option<crate::data_components::components::FireworkExplosionShape>,
19        has_twinkle: Option<bool>,
20        has_trail: Option<bool>,
21    ) -> Self {
22        Self {
23            shape,
24            has_twinkle,
25            has_trail,
26        }
27    }
28
29    #[must_use]
30    pub const fn shape(
31        &self,
32    ) -> Option<crate::data_components::components::FireworkExplosionShape> {
33        self.shape
34    }
35
36    #[must_use]
37    pub const fn has_twinkle(&self) -> Option<bool> {
38        self.has_twinkle
39    }
40
41    #[must_use]
42    pub const fn has_trail(&self) -> Option<bool> {
43        self.has_trail
44    }
45
46    fn from_nbt_value(tag: &NbtTag) -> Option<Self> {
47        let compound = tag.compound()?;
48        Some(Self {
49            shape: decode_optional(compound, "shape", |tag| {
50                match tag.string()?.to_owned().try_into_string().ok()?.as_str() {
51                    "small_ball" => {
52                        Some(crate::data_components::components::FireworkExplosionShape::SmallBall)
53                    }
54                    "large_ball" => {
55                        Some(crate::data_components::components::FireworkExplosionShape::LargeBall)
56                    }
57                    "star" => {
58                        Some(crate::data_components::components::FireworkExplosionShape::Star)
59                    }
60                    "creeper" => {
61                        Some(crate::data_components::components::FireworkExplosionShape::Creeper)
62                    }
63                    "burst" => {
64                        Some(crate::data_components::components::FireworkExplosionShape::Burst)
65                    }
66                    _ => None,
67                }
68            })?,
69            has_twinkle: decode_optional(compound, "has_twinkle", NbtNumeric::codec_bool)?,
70            has_trail: decode_optional(compound, "has_trail", NbtNumeric::codec_bool)?,
71        })
72    }
73
74    pub(super) fn to_nbt_value(&self) -> NbtTag {
75        let mut compound = NbtCompound::new();
76        if let Some(shape) = self.shape {
77            compound.insert("shape", shape.serialized_name());
78        }
79        if let Some(has_twinkle) = self.has_twinkle {
80            compound.insert("has_twinkle", has_twinkle);
81        }
82        if let Some(has_trail) = self.has_trail {
83            compound.insert("has_trail", has_trail);
84        }
85        NbtTag::Compound(compound)
86    }
87}
88
89impl HashComponent for FireworkPredicate {
90    fn hash_component(&self, hasher: &mut ComponentHasher) {
91        let mut entries = Vec::new();
92        if let Some(shape) = self.shape {
93            push_hash_entry(&mut entries, "shape", shape.serialized_name());
94        }
95        if let Some(has_twinkle) = self.has_twinkle {
96            push_hash_entry(&mut entries, "has_twinkle", &has_twinkle);
97        }
98        if let Some(has_trail) = self.has_trail {
99            push_hash_entry(&mut entries, "has_trail", &has_trail);
100        }
101        hash_entries(hasher, &mut entries);
102    }
103}
104
105/// Predicate over the `firework_explosion` component.
106#[derive(Debug, Clone, PartialEq, Eq)]
107pub struct FireworkExplosionPredicate(FireworkPredicate);
108
109impl FireworkExplosionPredicate {
110    #[must_use]
111    pub const fn new(predicate: FireworkPredicate) -> Self {
112        Self(predicate)
113    }
114
115    #[must_use]
116    pub const fn predicate(&self) -> &FireworkPredicate {
117        &self.0
118    }
119}
120
121impl DataComponentPredicateCodec for FireworkExplosionPredicate {
122    fn from_nbt_value(tag: &NbtTag) -> Option<Self> {
123        FireworkPredicate::from_nbt_value(tag).map(Self)
124    }
125
126    fn to_nbt_value(&self) -> NbtTag {
127        self.0.to_nbt_value()
128    }
129}
130
131impl HashComponent for FireworkExplosionPredicate {
132    fn hash_component(&self, hasher: &mut ComponentHasher) {
133        self.0.hash_component(hasher);
134    }
135}
136
137impl_predicate_downcast_type!(
138    FireworkExplosionPredicate,
139    "steel:data_component_predicate/firework_explosion"
140);
141
142/// Predicate over firework explosions and flight duration.
143#[derive(Debug, Clone, PartialEq)]
144pub struct FireworksPredicate {
145    explosions: Option<CollectionPredicate<FireworkPredicate>>,
146    flight_duration: IntBounds,
147}
148
149impl FireworksPredicate {
150    #[must_use]
151    pub const fn new(
152        explosions: Option<CollectionPredicate<FireworkPredicate>>,
153        flight_duration: IntBounds,
154    ) -> Self {
155        Self {
156            explosions,
157            flight_duration,
158        }
159    }
160
161    #[must_use]
162    pub const fn explosions(&self) -> Option<&CollectionPredicate<FireworkPredicate>> {
163        self.explosions.as_ref()
164    }
165
166    #[must_use]
167    pub const fn flight_duration(&self) -> IntBounds {
168        self.flight_duration
169    }
170}
171
172impl DataComponentPredicateCodec for FireworksPredicate {
173    fn from_nbt_value(tag: &NbtTag) -> Option<Self> {
174        let compound = tag.compound()?;
175        Some(Self {
176            explosions: decode_optional(compound, "explosions", |tag| {
177                CollectionPredicate::from_nbt_with(tag, FireworkPredicate::from_nbt_value)
178            })?,
179            flight_duration: compound
180                .get("flight_duration")
181                .map_or(Some(IntBounds::ANY), IntBounds::from_owned_nbt)?,
182        })
183    }
184
185    fn to_nbt_value(&self) -> NbtTag {
186        let mut compound = NbtCompound::new();
187        if let Some(explosions) = &self.explosions {
188            compound.insert(
189                "explosions",
190                explosions.to_nbt_with(FireworkPredicate::to_nbt_value),
191            );
192        }
193        if !self.flight_duration.is_any() {
194            compound.insert("flight_duration", self.flight_duration.as_nbt_tag());
195        }
196        NbtTag::Compound(compound)
197    }
198}
199
200impl HashComponent for FireworksPredicate {
201    fn hash_component(&self, hasher: &mut ComponentHasher) {
202        let mut entries = Vec::new();
203        if let Some(explosions) = &self.explosions {
204            let mut value_hasher = ComponentHasher::new();
205            explosions.hash_with(&mut value_hasher, HashComponent::compute_hash);
206            crate::item_predicate::push_prehashed_entry(&mut entries, "explosions", value_hasher);
207        }
208        if !self.flight_duration.is_any() {
209            push_hash_entry(&mut entries, "flight_duration", &self.flight_duration);
210        }
211        hash_entries(hasher, &mut entries);
212    }
213}
214
215impl_predicate_downcast_type!(
216    FireworksPredicate,
217    "steel:data_component_predicate/fireworks"
218);