yog_formats/sound.rs
1//! `.ysound` — a sound event: what the game plays when it's played. The
2//! sounds themselves are `.yres` sounds (`sound: @Sounds.abacus1`) as given
3//! — any format, normalised by the build; this says which of them play,
4//! how loud and how high, and the subtitle shown. Its id is its path under
5//! `resources/sound/` with `/` as `.` (`resources/sound/casting/cast.ysound`
6//! is `<mod id>:casting.cast`), named elsewhere as `@sound:<id>`. Yog Data,
7//! like every source format; the build writes the game's `sounds.json`.
8
9use yog_data::{Res, Schema};
10
11/// Where `.ysound` files live, under `resources/`.
12pub const DIR: &str = yog_ids::kind::SOUND;
13
14/// A `.ysound`.
15#[derive(Schema, Debug, Clone, PartialEq)]
16pub struct SoundFile {
17 /// What plays: one of them, picked by weight.
18 pub sounds: Vec<Variant>,
19 /// The subtitle shown when it plays: a `.yres` text.
20 pub subtitle: Option<Res>,
21 /// Replaces the game's own sounds of the same event (another mod's, a resource pack's).
22 #[data(default)]
23 pub replace: bool,
24}
25
26/// One sound an event may play.
27#[derive(Schema, Debug, Clone, PartialEq)]
28pub struct Variant {
29 /// The sound: a `.yres` sound.
30 pub sound: Res,
31 /// 1 if not given.
32 pub volume: Option<f32>,
33 /// 1 if not given.
34 pub pitch: Option<f32>,
35 /// How often it's picked against the others (1 if not given).
36 pub weight: Option<u32>,
37 /// Streamed, not loaded whole: long sounds (music, ambience).
38 #[data(default)]
39 pub stream: bool,
40 /// Loaded with the resources, not when first played.
41 #[data(default)]
42 pub preload: bool,
43 /// Blocks it carries (16 if not given).
44 pub attenuation_distance: Option<u32>,
45}
46
47/// An event's id from its file's path under `resources/` (`sound/casting/cast.ysound`)
48/// and the mod's id; none for a file outside `resources/sound/`.
49#[must_use]
50pub fn id_of(mod_id: &str, rel: &str) -> Option<String> {
51 let path = rel
52 .strip_suffix(yog_ids::Format::Sound.ext())?
53 .strip_suffix(yog_ids::sep::DOT)?
54 .strip_prefix(DIR)?
55 .strip_prefix(yog_ids::sep::PATH)?;
56 Some(yog_ids::join(mod_id, &path.replace(yog_ids::sep::PATH, yog_ids::sep::DOT)))
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62
63 #[test]
64 fn an_event_is_named_by_its_path_under_sound() {
65 assert_eq!(
66 id_of("hex", "sound/casting/cast.ysound").as_deref(),
67 Some("hex:casting.cast")
68 );
69 assert_eq!(id_of("hex", "sound/abacus.ysound").as_deref(), Some("hex:abacus"));
70 assert_eq!(id_of("hex", "block/abacus.ysound"), None);
71 assert_eq!(id_of("hex", "sound/abacus.ytexture"), None);
72 }
73}