Skip to main content

steel_registry/data_component_predicate/
attributes.rs

1use super::*;
2
3/// Predicate for one attribute-modifier entry.
4#[derive(Debug, Clone, PartialEq)]
5pub struct AttributeModifierEntryPredicate {
6    attribute: Option<RegistryHolderSet<Attribute>>,
7    id: Option<Identifier>,
8    amount: DoubleBounds,
9    operation: Option<AttributeModifierOperation>,
10    slot: Option<EquipmentSlotGroup>,
11}
12
13impl AttributeModifierEntryPredicate {
14    #[must_use]
15    pub const fn new(
16        attribute: Option<RegistryHolderSet<Attribute>>,
17        id: Option<Identifier>,
18        amount: DoubleBounds,
19        operation: Option<AttributeModifierOperation>,
20        slot: Option<EquipmentSlotGroup>,
21    ) -> Self {
22        Self {
23            attribute,
24            id,
25            amount,
26            operation,
27            slot,
28        }
29    }
30
31    #[must_use]
32    pub const fn attribute(&self) -> Option<&RegistryHolderSet<Attribute>> {
33        self.attribute.as_ref()
34    }
35
36    #[must_use]
37    pub const fn id(&self) -> Option<&Identifier> {
38        self.id.as_ref()
39    }
40
41    #[must_use]
42    pub const fn amount(&self) -> DoubleBounds {
43        self.amount
44    }
45
46    #[must_use]
47    pub const fn operation(&self) -> Option<AttributeModifierOperation> {
48        self.operation
49    }
50
51    #[must_use]
52    pub const fn slot(&self) -> Option<EquipmentSlotGroup> {
53        self.slot
54    }
55
56    fn from_nbt_value(tag: &NbtTag) -> Option<Self> {
57        let compound = tag.compound()?;
58        Some(Self {
59            attribute: decode_optional(compound, "attribute", RegistryHolderSet::from_owned_nbt)?,
60            id: decode_optional(compound, "id", |tag| owned_string(tag)?.parse().ok())?,
61            amount: compound
62                .get("amount")
63                .map_or(Some(DoubleBounds::ANY), DoubleBounds::from_owned_nbt)?,
64            operation: decode_optional(compound, "operation", |tag| {
65                AttributeModifierOperation::by_name(&owned_string(tag)?)
66            })?,
67            slot: decode_optional(compound, "slot", |tag| {
68                EquipmentSlotGroup::by_name(&owned_string(tag)?)
69            })?,
70        })
71    }
72
73    fn to_nbt_value(&self) -> NbtTag {
74        let mut compound = NbtCompound::new();
75        if let Some(attribute) = &self.attribute {
76            compound.insert("attribute", attribute.clone().to_nbt_tag());
77        }
78        if let Some(id) = &self.id {
79            compound.insert("id", id.to_string());
80        }
81        if !self.amount.is_any() {
82            compound.insert("amount", self.amount.as_nbt_tag());
83        }
84        if let Some(operation) = self.operation {
85            compound.insert("operation", operation.name());
86        }
87        if let Some(slot) = self.slot {
88            compound.insert("slot", slot.name());
89        }
90        NbtTag::Compound(compound)
91    }
92}
93
94impl HashComponent for AttributeModifierEntryPredicate {
95    fn hash_component(&self, hasher: &mut ComponentHasher) {
96        let mut entries = Vec::new();
97        if let Some(attribute) = &self.attribute {
98            push_hash_entry(&mut entries, "attribute", attribute);
99        }
100        if let Some(id) = &self.id {
101            push_hash_entry(&mut entries, "id", id);
102        }
103        if !self.amount.is_any() {
104            push_hash_entry(&mut entries, "amount", &self.amount);
105        }
106        if let Some(operation) = self.operation {
107            push_hash_entry(&mut entries, "operation", operation.name());
108        }
109        if let Some(slot) = self.slot {
110            push_hash_entry(&mut entries, "slot", slot.name());
111        }
112        hash_entries(hasher, &mut entries);
113    }
114}
115
116/// Predicate over item attribute modifiers.
117#[derive(Debug, Clone, PartialEq)]
118pub struct AttributeModifiersPredicate(
119    Option<CollectionPredicate<AttributeModifierEntryPredicate>>,
120);
121
122impl AttributeModifiersPredicate {
123    #[must_use]
124    pub const fn new(
125        modifiers: Option<CollectionPredicate<AttributeModifierEntryPredicate>>,
126    ) -> Self {
127        Self(modifiers)
128    }
129
130    #[must_use]
131    pub const fn modifiers(&self) -> Option<&CollectionPredicate<AttributeModifierEntryPredicate>> {
132        self.0.as_ref()
133    }
134}
135
136impl DataComponentPredicateCodec for AttributeModifiersPredicate {
137    fn from_nbt_value(tag: &NbtTag) -> Option<Self> {
138        let compound = tag.compound()?;
139        decode_optional(compound, "modifiers", |tag| {
140            CollectionPredicate::from_nbt_with(tag, AttributeModifierEntryPredicate::from_nbt_value)
141        })
142        .map(Self)
143    }
144
145    fn to_nbt_value(&self) -> NbtTag {
146        collection_field_nbt(
147            self.0.as_ref(),
148            "modifiers",
149            AttributeModifierEntryPredicate::to_nbt_value,
150        )
151    }
152}
153
154impl HashComponent for AttributeModifiersPredicate {
155    fn hash_component(&self, hasher: &mut ComponentHasher) {
156        hash_optional_collection_field(
157            self.0.as_ref(),
158            "modifiers",
159            hasher,
160            HashComponent::compute_hash,
161        );
162    }
163}
164
165impl_predicate_downcast_type!(
166    AttributeModifiersPredicate,
167    "steel:data_component_predicate/attribute_modifiers"
168);