Skip to main content

steel_registry/
cow_variant.rs

1use steel_utils::random::Random;
2
3use crate::biome::BiomeRef;
4use crate::shared_structs::pick_spawn_conditioned_entry;
5use crate::shared_structs::{SpawnConditionEntry, insert_spawn_conditions};
6use rustc_hash::FxHashMap;
7use simdnbt::ToNbtTag;
8use simdnbt::owned::NbtTag;
9use steel_utils::Identifier;
10
11/// Represents a full cow variant definition from a data pack JSON file.
12#[derive(Debug)]
13pub struct CowVariant {
14    pub key: Identifier,
15    pub asset_id: Identifier,
16    pub baby_asset_id: Identifier,
17    pub model: CowModelType,
18    pub spawn_conditions: &'static [SpawnConditionEntry],
19}
20
21/// The model type for the cow, which can affect its shape.
22#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
23pub enum CowModelType {
24    #[default]
25    Normal,
26    Cold,
27    Warm,
28}
29
30impl ToNbtTag for &CowVariant {
31    fn to_nbt_tag(self) -> NbtTag {
32        use simdnbt::owned::{NbtCompound, NbtTag};
33        let mut compound = NbtCompound::new();
34        compound.insert("asset_id", self.asset_id.clone());
35        compound.insert("baby_asset_id", self.baby_asset_id.clone());
36        compound.insert(
37            "model",
38            match self.model {
39                CowModelType::Normal => "normal",
40                CowModelType::Cold => "cold",
41                CowModelType::Warm => "warm",
42            },
43        );
44        insert_spawn_conditions(&mut compound, self.spawn_conditions);
45        NbtTag::Compound(compound)
46    }
47}
48
49pub type CowVariantRef = &'static CowVariant;
50
51pub struct CowVariantRegistry {
52    cow_variants_by_id: Vec<CowVariantRef>,
53    cow_variants_by_key: FxHashMap<Identifier, usize>,
54    allows_registering: bool,
55}
56
57impl CowVariantRegistry {
58    #[must_use]
59    pub fn new() -> Self {
60        Self {
61            cow_variants_by_id: Vec::new(),
62            cow_variants_by_key: FxHashMap::default(),
63            allows_registering: true,
64        }
65    }
66
67    #[must_use]
68    pub fn select_spawn_variant(
69        &self,
70        biome: BiomeRef,
71        random: &mut impl Random,
72    ) -> Option<CowVariantRef> {
73        // Mirrors vanilla conditioned variant selection against the spawn biome.
74        pick_spawn_conditioned_entry(
75            self.iter().map(|(_, variant)| variant),
76            |variant| variant.spawn_conditions,
77            biome,
78            random,
79        )
80    }
81}
82
83crate::impl_standard_methods!(
84    CowVariantRegistry,
85    CowVariantRef,
86    cow_variants_by_id,
87    cow_variants_by_key,
88    allows_registering
89);
90
91crate::impl_registry!(
92    CowVariantRegistry,
93    CowVariant,
94    cow_variants_by_id,
95    cow_variants_by_key,
96    cow_variants
97);