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 std::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)]
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)]
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::from_text::<ItemLooks>(include_str!("../assets/item_looks.ydata"))
45        .unwrap_or_else(|e| panic!("yog-registry's item looks: {e}"))
46        .value
47});
48
49impl ItemLooks {
50    /// The game's.
51    pub fn game() -> &'static ItemLooks {
52        &ITEM_LOOKS
53    }
54
55    /// The texture of the mob whose head item `path` (`zombie_head`) is.
56    pub fn head(&self, path: &str) -> Option<&str> {
57        self.heads.0.iter().find(|(p, _)| p == path).map(|(_, t)| t.as_str())
58    }
59
60    /// Mob `mob`'s spawn egg colours: base, spots.
61    pub fn spawn_egg(&self, mob: &str) -> Option<(Color, Color)> {
62        match self.spawn_eggs.0.iter().find(|(m, _)| m == mob)?.1.as_slice() {
63            [base, spots] => Some((*base, *spots)),
64            _ => None,
65        }
66    }
67
68    /// The tint of item `id`'s first layer.
69    pub fn tint(&self, id: &str) -> Option<Color> {
70        self.tints
71            .iter()
72            .find(|t| t.items.iter().any(|i| i == id) || (!t.prefix.is_empty() && id.starts_with(&t.prefix)))
73            .map(|t| t.color)
74    }
75}
76
77#[cfg(test)]
78mod tests {
79    use super::*;
80
81    #[test]
82    fn the_game_looks_read() {
83        let l = ItemLooks::game();
84        assert_eq!(l.head("zombie_head"), Some("minecraft:entity/zombie/zombie"));
85        assert_eq!(l.spawn_egg("creeper"), Some((Color(0xFF0D_A70B), Color(0xFF00_0000))));
86        assert_eq!(l.tint("minecraft:potion"), Some(Color(0xFF38_5DC6)));
87        assert_eq!(l.tint("minecraft:leather_boots"), Some(Color(0xFFA0_6540)));
88    }
89}