Skip to main content

steel_registry/
damage_type.rs

1use rustc_hash::FxHashMap;
2use simdnbt::ToNbtTag;
3use simdnbt::owned::NbtTag;
4use steel_utils::Identifier;
5
6use crate::RegistryTags;
7
8/// Represents a damage type definition from a data pack JSON file.
9#[derive(Debug)]
10pub struct DamageType {
11    pub key: Identifier,
12    pub message_id: &'static str,
13    pub scaling: DamageScaling,
14    pub exhaustion: f32,
15    pub effects: DamageEffects,
16    pub death_message_type: DeathMessageType,
17}
18
19/// How the damage scales with difficulty.
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21pub enum DamageScaling {
22    Always,
23    WhenCausedByLivingNonPlayer,
24    Never,
25}
26
27/// The sound effects played when an entity is damaged.
28#[derive(Debug, Clone, Copy, PartialEq, Eq)]
29pub enum DamageEffects {
30    Hurt,
31    Thorns,
32    Drowning,
33    Burning,
34    Poking,
35    Freezing,
36}
37
38/// How the death message is formatted.
39#[derive(Debug, Clone, Copy, PartialEq, Eq)]
40pub enum DeathMessageType {
41    Default,
42    FallVariants,
43    IntentionalGameDesign,
44}
45
46impl ToNbtTag for &DamageType {
47    fn to_nbt_tag(self) -> NbtTag {
48        use simdnbt::owned::NbtCompound;
49        let mut compound = NbtCompound::new();
50        compound.insert("message_id", self.message_id);
51        compound.insert(
52            "scaling",
53            match self.scaling {
54                DamageScaling::Always => "always",
55                DamageScaling::WhenCausedByLivingNonPlayer => "when_caused_by_living_non_player",
56                DamageScaling::Never => "never",
57            },
58        );
59        compound.insert("exhaustion", self.exhaustion);
60        compound.insert(
61            "effects",
62            match self.effects {
63                DamageEffects::Hurt => "hurt",
64                DamageEffects::Thorns => "thorns",
65                DamageEffects::Drowning => "drowning",
66                DamageEffects::Burning => "burning",
67                DamageEffects::Poking => "poking",
68                DamageEffects::Freezing => "freezing",
69            },
70        );
71        compound.insert(
72            "death_message_type",
73            match self.death_message_type {
74                DeathMessageType::Default => "default",
75                DeathMessageType::FallVariants => "fall_variants",
76                DeathMessageType::IntentionalGameDesign => "intentional_game_design",
77            },
78        );
79        NbtTag::Compound(compound)
80    }
81}
82
83pub type DamageTypeRef = &'static DamageType;
84
85pub struct DamageTypeRegistry {
86    damage_types_by_id: Vec<DamageTypeRef>,
87    damage_types_by_key: FxHashMap<Identifier, usize>,
88    tags: RegistryTags,
89    allows_registering: bool,
90}
91
92impl DamageTypeRegistry {
93    #[must_use]
94    pub fn new() -> Self {
95        Self {
96            damage_types_by_id: Vec::new(),
97            damage_types_by_key: FxHashMap::default(),
98            allows_registering: true,
99            tags: RegistryTags::default(),
100        }
101    }
102}
103
104crate::impl_standard_methods!(
105    DamageTypeRegistry,
106    DamageTypeRef,
107    damage_types_by_id,
108    damage_types_by_key,
109    allows_registering
110);
111
112crate::impl_registry!(
113    DamageTypeRegistry,
114    DamageType,
115    damage_types_by_id,
116    damage_types_by_key,
117    damage_types
118);
119crate::impl_tagged_registry!(DamageTypeRegistry, damage_types_by_key, "damage type");