Skip to main content

steel_core/behavior/
mob_effect.rs

1//! Mob-effect behavior registry.
2
3use std::ops::Deref;
4use std::sync::OnceLock;
5
6use steel_registry::mob_effect::MobEffectRef;
7use steel_registry::{REGISTRY, RegistryEntry, RegistryExt};
8
9use crate::entity::mob_effect::MobEffectBehavior;
10
11/// Default vanilla `MobEffect` behavior for effects with no custom tick or
12/// instantaneous logic — pure duration/amplifier/attribute-modifier data,
13/// matching vanilla effects registered as plain `MobEffect` instances.
14struct DefaultMobEffect;
15
16impl MobEffectBehavior for DefaultMobEffect {}
17
18/// Wrapper for the global mob-effect behavior registry that implements `Deref`.
19pub struct MobEffectBehaviorLock(pub OnceLock<MobEffectBehaviorRegistry>);
20
21impl Deref for MobEffectBehaviorLock {
22    type Target = MobEffectBehaviorRegistry;
23
24    fn deref(&self) -> &Self::Target {
25        self.0.get().expect("Mob effect behaviors not initialized")
26    }
27}
28
29/// Global mob-effect behavior registry.
30///
31/// Access behaviors directly via deref: `MOB_EFFECT_BEHAVIORS.get_behavior(effect)`
32pub static MOB_EFFECT_BEHAVIORS: MobEffectBehaviorLock = MobEffectBehaviorLock(OnceLock::new());
33
34/// Registry for mob-effect behaviors.
35///
36/// Created after the main registry is frozen. All mob effects are
37/// initialized with a default behavior matching a bare vanilla `MobEffect`
38/// instance, then custom behaviors are registered.
39pub struct MobEffectBehaviorRegistry {
40    behaviors: Vec<Box<dyn MobEffectBehavior>>,
41}
42
43impl MobEffectBehaviorRegistry {
44    /// Creates a new behavior registry with default behaviors for all mob effects.
45    #[must_use]
46    pub fn new() -> Self {
47        let count = REGISTRY.mob_effects.len();
48        let mut behaviors: Vec<Box<dyn MobEffectBehavior>> = Vec::with_capacity(count);
49
50        for _ in 0..count {
51            behaviors.push(Box::new(DefaultMobEffect));
52        }
53
54        Self { behaviors }
55    }
56
57    /// Sets a custom behavior for a mob effect.
58    ///
59    /// # Panics
60    /// Panics if `effect` is not registered in the global registry.
61    pub fn set_behavior(&mut self, effect: MobEffectRef, behavior: Box<dyn MobEffectBehavior>) {
62        self.behaviors[effect.id()] = behavior;
63    }
64
65    /// Gets the behavior for a mob effect.
66    ///
67    /// # Panics
68    /// Panics if `effect` is not registered in the global registry.
69    #[must_use]
70    pub fn get_behavior(&self, effect: MobEffectRef) -> &dyn MobEffectBehavior {
71        self.behaviors[effect.id()].as_ref()
72    }
73}
74
75impl Default for MobEffectBehaviorRegistry {
76    fn default() -> Self {
77        Self::new()
78    }
79}