1use yog_sync::LazyLock;
5
6#[derive(yog_data::Schema, Debug, Clone, PartialEq)]
8pub struct Atlas {
9 pub id: String,
11 pub description: String,
12 pub since: Option<String>,
14 #[data(default)]
16 pub dirs: Vec<String>,
17 #[data(default)]
19 pub bare: bool,
20 pub moved_to: Option<String>,
23}
24
25static ATLASES: LazyLock<Vec<Atlas>> = LazyLock::new(|| {
26 yog_data::built_in::<Vec<Atlas>>(
27 "yog-registry's atlases",
28 include_str!("../assets/atlases.ydata"),
29 )
30});
31
32impl Atlas {
33 pub fn game() -> &'static [Atlas] {
35 &ATLASES
36 }
37
38 pub fn of_path(path: &str) -> Option<&'static Atlas> {
40 ATLASES.iter().find(|a| a.dir_of(path).is_some())
41 }
42
43 fn dir_of<'p>(&self, path: &'p str) -> Option<&'p str> {
45 self.dirs.iter().find_map(|d| {
46 path.strip_prefix(d.as_str())?
47 .strip_prefix(yog_ids::sep::PATH)
48 })
49 }
50
51 pub fn sprite<'p>(&self, path: &'p str) -> &'p str {
54 if self.bare {
55 self.dir_of(path).unwrap_or(path)
56 } else {
57 path
58 }
59 }
60
61 pub fn find(id: &str) -> Option<&'static Atlas> {
63 let id = yog_ids::qualify(id);
64 ATLASES.iter().find(|a| a.id == id)
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 #[test]
71 fn the_games_atlases_read() {
72 assert!(super::Atlas::find("blocks").is_some());
73 assert_eq!(
74 super::Atlas::find("minecraft:gui").and_then(|a| a.since.as_deref()),
75 Some("1.20.2")
76 );
77 assert_eq!(
78 super::Atlas::of_path("item/staff/oak").map(|a| a.id.as_str()),
79 Some("minecraft:blocks")
80 );
81 assert!(super::Atlas::of_path("entity/wisp").is_none());
82 let effects = super::Atlas::of_path("mob_effect/clarity").unwrap();
83 assert_eq!(effects.sprite("mob_effect/clarity"), "clarity");
84 assert_eq!(
85 super::Atlas::find("blocks").unwrap().sprite("block/ruby"),
86 "block/ruby"
87 );
88 assert_eq!(
89 super::Atlas::of_path("gui/sprites/hud/x").map(|a| a.id.as_str()),
90 Some("minecraft:gui")
91 );
92 }
93}