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