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#[derive(AzBuf, Clone, Debug, Default, PartialEq)]
12pub struct MobEffectData {
13 #[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#[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 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 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}