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