Skip to main content

azalea_entity/
effects.rs

1use std::{
2    collections::HashMap,
3    io::{self, Cursor, Write},
4};
5
6use azalea_buf::{AzBuf, BufReadError};
7use azalea_core::bitset::FixedBitSet;
8use azalea_registry::builtin::MobEffect;
9
10/// Data about an active mob effect.
11#[derive(AzBuf, Clone, Debug, Default, PartialEq)]
12pub struct MobEffectData {
13    /// The effect's amplifier level, starting at 0 if present.
14    #[var]
15    pub amplifier: u32,
16    #[var]
17    pub duration_ticks: u32,
18
19    pub flags: MobEffectFlags,
20}
21
22#[derive(Clone, Debug, Default, PartialEq)]
23pub struct MobEffectFlags {
24    pub ambient: bool,
25    pub show_particles: bool,
26    pub show_icon: bool,
27    pub blend: bool,
28}
29
30impl AzBuf for MobEffectFlags {
31    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
32        let bitset = FixedBitSet::<8>::azalea_read(buf)?;
33        let ambient = bitset.index(0);
34        let show_particles = bitset.index(1);
35        let show_icon = bitset.index(2);
36        let blend = bitset.index(3);
37        Ok(Self {
38            ambient,
39            show_particles,
40            show_icon,
41            blend,
42        })
43    }
44    fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
45        let mut bitset = FixedBitSet::<8>::new();
46        if self.ambient {
47            bitset.set(0);
48        }
49        if self.show_particles {
50            bitset.set(1);
51        }
52        if self.show_icon {
53            bitset.set(2);
54        }
55        if self.blend {
56            bitset.set(3);
57        }
58        bitset.azalea_write(buf)
59    }
60}
61
62/// The active mob effects on an entity.
63#[cfg_attr(feature = "bevy_ecs", derive(bevy_ecs::component::Component))]
64#[derive(Clone, Debug, Default)]
65pub struct ActiveEffects(pub HashMap<MobEffect, MobEffectData>);
66impl ActiveEffects {
67    pub fn insert(&mut self, effect: MobEffect, data: MobEffectData) {
68        self.0.insert(effect, data);
69    }
70
71    pub fn remove(&mut self, effect: MobEffect) -> Option<MobEffectData> {
72        self.0.remove(&effect)
73    }
74
75    /// Get the amplifier level for the effect, starting at 0.
76    pub fn get_level(&self, effect: MobEffect) -> Option<u32> {
77        self.0.get(&effect).map(|data| data.amplifier)
78    }
79
80    pub fn get(&self, effect: MobEffect) -> Option<&MobEffectData> {
81        self.0.get(&effect)
82    }
83
84    /// Returns the amplifier for dig speed (haste / conduit power), if present.
85    pub fn get_dig_speed_amplifier(&self) -> Option<u32> {
86        let haste_level = self
87            .get_level(MobEffect::Haste)
88            .map(|level| level + 1)
89            .unwrap_or_default();
90        let conduit_power_level = self
91            .get_level(MobEffect::ConduitPower)
92            .map(|level| level + 1)
93            .unwrap_or_default();
94
95        let effect_plus_one = u32::max(haste_level, conduit_power_level);
96        if effect_plus_one > 0 {
97            Some(effect_plus_one - 1)
98        } else {
99            None
100        }
101    }
102}