yog_registry/
item_looks.rs1use std::sync::LazyLock;
6
7use yog_data::Ordered;
8use yog_graphics::Color;
9
10#[derive(yog_data::Schema, Debug, Clone, PartialEq)]
12pub struct LookModels {
13 pub potion: String,
15 pub spawn_egg: String,
17 pub heads: Vec<String>,
19}
20
21#[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#[derive(yog_data::Schema, Debug, Clone, PartialEq)]
34pub struct ItemLooks {
35 pub models: LookModels,
36 pub heads: Ordered<String>,
38 pub tints: Vec<ItemTint>,
39 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 pub fn game() -> &'static ItemLooks {
52 &ITEM_LOOKS
53 }
54
55 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 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 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}