Skip to main content

steel_registry/data_components/components/
brewing_fuel.rs

1//! Vanilla `minecraft:brewing_fuel` item component.
2
3use std::io::{Cursor, Result, Write};
4
5use simdnbt::owned::{NbtCompound, NbtTag};
6use simdnbt::{FromNbtTag, ToNbtTag};
7use steel_utils::Identifier;
8use steel_utils::hash::{ComponentHasher, HashComponent, HashEntry, sort_map_entries};
9use steel_utils::serial::{ReadFrom, WriteTo};
10
11/// References to the context int/float providers that give a brewing fuel
12/// item its number of uses and brewing-speed multiplier.
13#[derive(Debug, Clone, PartialEq, Eq)]
14pub struct BrewingFuel {
15    pub uses: Identifier,
16    pub speed_multiplier: Identifier,
17}
18
19impl BrewingFuel {
20    #[must_use]
21    pub const fn new(uses: Identifier, speed_multiplier: Identifier) -> Self {
22        Self {
23            uses,
24            speed_multiplier,
25        }
26    }
27}
28
29impl WriteTo for BrewingFuel {
30    fn write(&self, writer: &mut impl Write) -> Result<()> {
31        self.uses.write(writer)?;
32        self.speed_multiplier.write(writer)
33    }
34}
35
36impl ReadFrom for BrewingFuel {
37    fn read(data: &mut Cursor<&[u8]>) -> Result<Self> {
38        Ok(Self {
39            uses: Identifier::read(data)?,
40            speed_multiplier: Identifier::read(data)?,
41        })
42    }
43}
44
45impl ToNbtTag for BrewingFuel {
46    fn to_nbt_tag(self) -> NbtTag {
47        let mut compound = NbtCompound::new();
48        compound.insert("uses", self.uses.to_nbt_tag());
49        compound.insert("speed_multiplier", self.speed_multiplier.to_nbt_tag());
50        NbtTag::Compound(compound)
51    }
52}
53
54impl FromNbtTag for BrewingFuel {
55    fn from_nbt_tag(tag: simdnbt::borrow::NbtTag) -> Option<Self> {
56        let compound = tag.compound()?;
57        let uses = Identifier::from_nbt_tag(compound.get("uses")?)?;
58        let speed_multiplier = Identifier::from_nbt_tag(compound.get("speed_multiplier")?)?;
59        Some(Self {
60            uses,
61            speed_multiplier,
62        })
63    }
64}
65
66impl HashComponent for BrewingFuel {
67    fn hash_component(&self, hasher: &mut ComponentHasher) {
68        let mut entries = Vec::with_capacity(2);
69        push_hash_entry(&mut entries, "uses", &self.uses);
70        push_hash_entry(&mut entries, "speed_multiplier", &self.speed_multiplier);
71        sort_map_entries(&mut entries);
72        hasher.start_map();
73        for entry in entries {
74            hasher.put_raw_bytes(&entry.key_bytes);
75            hasher.put_raw_bytes(&entry.value_bytes);
76        }
77        hasher.end_map();
78    }
79}
80
81fn push_hash_entry<T: HashComponent + ?Sized>(entries: &mut Vec<HashEntry>, key: &str, value: &T) {
82    let mut key_hasher = ComponentHasher::new();
83    key_hasher.put_string(key);
84    let mut value_hasher = ComponentHasher::new();
85    value.hash_component(&mut value_hasher);
86    entries.push(HashEntry::new(key_hasher, value_hasher));
87}
88
89#[cfg(test)]
90mod tests {
91    use std::io::Cursor;
92
93    use simdnbt::FromNbtTag as _;
94    use simdnbt::ToNbtTag as _;
95    use simdnbt::borrow::read_tag;
96    use simdnbt::owned::NbtTag;
97    use steel_utils::Identifier;
98    use steel_utils::serial::{ReadFrom as _, WriteTo as _};
99
100    use super::BrewingFuel;
101
102    fn parse(tag: NbtTag) -> Option<BrewingFuel> {
103        let mut bytes = Vec::new();
104        tag.write(&mut bytes);
105        let borrowed = read_tag(&mut Cursor::new(bytes.as_slice())).ok()?;
106        BrewingFuel::from_nbt_tag(borrowed.as_tag())
107    }
108
109    #[test]
110    fn round_trips_both_codecs() {
111        let value = BrewingFuel::new(
112            Identifier::vanilla_static("brewing/uses_default"),
113            Identifier::vanilla_static("brewing/speed_default"),
114        );
115
116        let nbt = value.clone().to_nbt_tag();
117        assert_eq!(parse(nbt), Some(value.clone()));
118
119        let mut network = Vec::new();
120        value.write(&mut network).expect("fuel should encode");
121        assert_eq!(
122            BrewingFuel::read(&mut Cursor::new(network.as_slice())).expect("fuel should decode"),
123            value
124        );
125    }
126}