Skip to main content

yog_registry/
sounds.rs

1//! Sound groups: what a block sounds like.
2
3use crate::equipment::built_in;
4
5/// What a block sounds like: the sound events it plays when broken,
6/// stepped on, placed, hit while mining and fallen on. The game's groups
7/// are built in ([`SoundGroup::built_in`]); a mod registers its own
8/// (`Registry::register_sound_group`, or a `.ydef` of kind `sound_group`)
9/// and names it in `BlockDef::sound`.
10#[derive(yog_data::Schema, Debug, Clone, PartialEq)]
11pub struct SoundGroup {
12    pub id: String,
13    /// Sound event ids (`minecraft:block.stone.break`, `mymod:crystal.break`).
14    #[data(rename = "break")]
15    pub break_sound: String,
16    pub step: String,
17    pub place: String,
18    pub hit: String,
19    pub fall: String,
20    #[data(default = "one")]
21    #[data(range = "0..=10")]
22    pub volume: f32,
23    #[data(default = "one")]
24    #[data(range = "0..=10")]
25    pub pitch: f32,
26}
27
28fn one() -> f32 {
29    1.0
30}
31
32static BUILT_IN_SOUND_GROUPS: yog_sync::LazyLock<Vec<SoundGroup>> = yog_sync::LazyLock::new(|| {
33    yog_data::built_in::<Vec<SoundGroup>>(
34        "yog-registry's built-in sound groups",
35        include_str!("../assets/sound_groups.ydata"),
36    )
37});
38
39impl SoundGroup {
40    /// `mymod:crystal`, its sounds `mymod:crystal.break`, `.step`, `.place`,
41    /// `.hit`, `.fall`; volume and pitch 1.
42    pub fn new(id: impl Into<String>) -> Self {
43        let id = id.into();
44        let ev = |s: &str| format!("{id}.{s}");
45        Self {
46            break_sound: ev("break"),
47            step: ev("step"),
48            place: ev("place"),
49            hit: ev("hit"),
50            fall: ev("fall"),
51            volume: 1.0,
52            pitch: 1.0,
53            id,
54        }
55    }
56
57    /// The five sound events: break, step, place, hit, fall.
58    pub fn sounds(
59        mut self,
60        break_sound: &str,
61        step: &str,
62        place: &str,
63        hit: &str,
64        fall: &str,
65    ) -> Self {
66        [self.break_sound, self.step, self.place, self.hit, self.fall] =
67            [break_sound, step, place, hit, fall].map(String::from);
68        self
69    }
70
71    pub fn volume(mut self, volume: f32) -> Self {
72        self.volume = volume;
73        self
74    }
75
76    pub fn pitch(mut self, pitch: f32) -> Self {
77        self.pitch = pitch;
78        self
79    }
80
81    /// The game's groups (`minecraft:stone`, `minecraft:amethyst`…, from
82    /// Minecraft's `SoundType`), as data.
83    pub fn built_ins() -> &'static [SoundGroup] {
84        &BUILT_IN_SOUND_GROUPS
85    }
86
87    /// One of the game's groups, by short name or id (`stone` = `minecraft:stone`).
88    pub fn built_in(name: &str) -> Option<&'static SoundGroup> {
89        built_in(Self::built_ins(), |g| &g.id, name)
90    }
91}