Skip to main content

yog_registry/
item_looks.rs

1//! How the game draws items whose look isn't their textures alone — heads,
2//! spawn eggs, tinted potions and leather — as data
3//! (`assets/item_looks.ydata`), for tools that show items as the game does.
4
5use yog_sync::LazyLock;
6
7use yog_data::Ordered;
8use yog_graphics::Color;
9
10/// The models items are drawn through in a GUI.
11#[derive(yog_data::Schema, Debug, Clone, PartialEq, Default)]
12pub struct LookModels {
13    /// A potion's (Yog's potion aliases are drawn through it).
14    pub potion: String,
15    /// The template every spawn egg's model is.
16    pub spawn_egg: String,
17    /// Models drawn as their mob's head.
18    pub heads: Vec<String>,
19}
20
21/// A colour the game tints an item's first layer with: these items, or
22/// every item whose id starts with `prefix`.
23#[derive(yog_data::Schema, Debug, Clone, PartialEq)]
24pub struct ItemTint {
25    pub color: Color,
26    #[data(default)]
27    pub items: Vec<String>,
28    #[data(default)]
29    pub prefix: String,
30}
31
32/// The game's item looks.
33#[derive(yog_data::Schema, Debug, Clone, PartialEq, Default)]
34pub struct ItemLooks {
35    pub models: LookModels,
36    /// Items drawn as a mob's head, by item path: the mob's texture.
37    pub heads: Ordered<String>,
38    pub tints: Vec<ItemTint>,
39    /// Spawn eggs' colours (base, spots), by mob.
40    pub spawn_eggs: Ordered<Vec<Color>>,
41}
42
43static ITEM_LOOKS: LazyLock<ItemLooks> = LazyLock::new(|| {
44    yog_data::built_in::<ItemLooks>(
45        "yog-registry's item looks",
46        include_str!("../assets/item_looks.ydata"),
47    )
48});
49
50impl ItemLooks {
51    /// The game's.
52    pub fn game() -> &'static ItemLooks {
53        &ITEM_LOOKS
54    }
55
56    /// The texture of the mob whose head item `path` (`zombie_head`) is.
57    pub fn head(&self, path: &str) -> Option<&str> {
58        self.heads
59            .0
60            .iter()
61            .find(|(p, _)| p == path)
62            .map(|(_, t)| t.as_str())
63    }
64
65    /// Mob `mob`'s spawn egg colours: base, spots.
66    pub fn spawn_egg(&self, mob: &str) -> Option<(Color, Color)> {
67        match self
68            .spawn_eggs
69            .0
70            .iter()
71            .find(|(m, _)| m == mob)?
72            .1
73            .as_slice()
74        {
75            [base, spots] => Some((*base, *spots)),
76            _ => None,
77        }
78    }
79
80    /// The tint of item `id`'s first layer.
81    pub fn tint(&self, id: &str) -> Option<Color> {
82        self.tints
83            .iter()
84            .find(|t| {
85                t.items.iter().any(|i| i == id)
86                    || (!t.prefix.is_empty() && id.starts_with(&t.prefix))
87            })
88            .map(|t| t.color)
89    }
90}
91
92#[cfg(test)]
93mod tests {
94    use super::*;
95
96    #[test]
97    fn the_game_looks_read() {
98        let l = ItemLooks::game();
99        assert_eq!(
100            l.head("zombie_head"),
101            Some("minecraft:entity/zombie/zombie")
102        );
103        assert_eq!(
104            l.spawn_egg("creeper"),
105            Some((Color(0xFF0D_A70B), Color(0xFF00_0000)))
106        );
107        assert_eq!(l.tint("minecraft:potion"), Some(Color(0xFF38_5DC6)));
108        assert_eq!(l.tint("minecraft:leather_boots"), Some(Color(0xFFA0_6540)));
109    }
110}