Skip to main content

steel_registry/
instrument.rs

1use rustc_hash::FxHashMap;
2use simdnbt::ToNbtTag;
3use simdnbt::owned::NbtTag;
4use steel_utils::Identifier;
5use text_components::TextComponent;
6
7use crate::sound_event::SoundEventRef;
8
9/// Represents a musical instrument definition from a data pack JSON file,
10/// primarily used for Goat Horns.
11#[derive(Debug)]
12pub struct Instrument {
13    pub key: Identifier,
14    pub sound_event: SoundEventRef,
15    pub use_duration: f32,
16    pub range: f32,
17    pub description: TextComponent,
18}
19
20impl ToNbtTag for &Instrument {
21    fn to_nbt_tag(self) -> NbtTag {
22        use simdnbt::owned::NbtCompound;
23        let mut compound = NbtCompound::new();
24        let sound_event = self.sound_event.key.to_string();
25        compound.insert("sound_event", sound_event.as_str());
26        compound.insert("use_duration", self.use_duration);
27        compound.insert("range", self.range);
28        compound.insert("description", (&self.description).to_nbt_tag());
29        NbtTag::Compound(compound)
30    }
31}
32
33pub type InstrumentRef = &'static Instrument;
34
35pub struct InstrumentRegistry {
36    instruments_by_id: Vec<InstrumentRef>,
37    instruments_by_key: FxHashMap<Identifier, usize>,
38    tags: FxHashMap<Identifier, Vec<Identifier>>,
39    allows_registering: bool,
40}
41
42impl InstrumentRegistry {
43    #[must_use]
44    pub fn new() -> Self {
45        Self {
46            instruments_by_id: Vec::new(),
47            instruments_by_key: FxHashMap::default(),
48            tags: FxHashMap::default(),
49            allows_registering: true,
50        }
51    }
52}
53
54crate::impl_standard_methods!(
55    InstrumentRegistry,
56    InstrumentRef,
57    instruments_by_id,
58    instruments_by_key,
59    allows_registering
60);
61
62crate::impl_registry!(
63    InstrumentRegistry,
64    Instrument,
65    instruments_by_id,
66    instruments_by_key,
67    instruments
68);
69
70crate::impl_tagged_registry!(InstrumentRegistry, instruments_by_key, "instrument");
71
72#[cfg(test)]
73mod tests {
74    use simdnbt::ToNbtTag;
75    use simdnbt::owned::NbtTag;
76
77    use crate::{test_support::init_test_registry, vanilla_instruments};
78
79    #[test]
80    fn nbt_uses_sound_event_registry_key() {
81        init_test_registry();
82
83        let NbtTag::Compound(compound) = (&vanilla_instruments::PONDER_GOAT_HORN).to_nbt_tag()
84        else {
85            panic!("instrument did not serialize to a compound tag");
86        };
87
88        let Some(sound_event) = compound.string("sound_event") else {
89            panic!("instrument NBT is missing sound_event string");
90        };
91
92        assert_eq!(
93            sound_event.to_str().as_ref(),
94            "minecraft:item.goat_horn.sound.0"
95        );
96    }
97}