Skip to main content

steel_protocol/packets/game/
c_update_mob_effect.rs

1//! Clientbound update mob effect packet.
2
3use steel_macros::{ClientPacket, WriteTo};
4use steel_registry::mob_effect::MobEffectRef;
5use steel_registry::packets::play::C_UPDATE_MOB_EFFECT;
6
7const FLAG_AMBIENT: u8 = 0x01;
8const FLAG_VISIBLE: u8 = 0x02;
9const FLAG_SHOW_ICON: u8 = 0x04;
10const FLAG_BLEND: u8 = 0x08;
11
12/// Sent when the client should add or update an entity mob effect.
13///
14/// Vanilla: `ClientboundUpdateMobEffectPacket`.
15#[derive(ClientPacket, WriteTo, Clone, Debug)]
16#[packet_id(Play = C_UPDATE_MOB_EFFECT)]
17pub struct CUpdateMobEffect {
18    #[write(as = VarInt)]
19    pub entity_id: i32,
20    /// Holder-registry mob effect id.
21    #[write(as = VarInt)]
22    pub effect_id: i32,
23    #[write(as = VarInt)]
24    pub amplifier: i32,
25    #[write(as = VarInt)]
26    pub duration: i32,
27    pub flags: u8,
28}
29
30#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
31pub struct MobEffectPacketFlags {
32    pub ambient: bool,
33    pub visible: bool,
34    pub show_icon: bool,
35    pub blend: bool,
36}
37
38impl CUpdateMobEffect {
39    #[must_use]
40    pub fn new(
41        entity_id: i32,
42        effect: MobEffectRef,
43        amplifier: i32,
44        duration: i32,
45        flags: MobEffectPacketFlags,
46    ) -> Self {
47        Self {
48            entity_id,
49            effect_id: effect.packet_holder_id(),
50            amplifier,
51            duration,
52            flags: mob_effect_flags(flags),
53        }
54    }
55}
56
57const fn mob_effect_flags(packet_flags: MobEffectPacketFlags) -> u8 {
58    let mut flags = 0;
59    if packet_flags.ambient {
60        flags |= FLAG_AMBIENT;
61    }
62    if packet_flags.visible {
63        flags |= FLAG_VISIBLE;
64    }
65    if packet_flags.show_icon {
66        flags |= FLAG_SHOW_ICON;
67    }
68    if packet_flags.blend {
69        flags |= FLAG_BLEND;
70    }
71    flags
72}
73
74#[cfg(test)]
75mod tests {
76
77    use steel_registry::init_vanilla_registry;
78    use steel_registry::vanilla_mob_effects;
79
80    use super::*;
81
82    #[test]
83    fn update_mob_effect_uses_raw_holder_registry_id() {
84        init_vanilla_registry();
85
86        let packet = CUpdateMobEffect::new(
87            42,
88            vanilla_mob_effects::SPEED,
89            0,
90            100,
91            MobEffectPacketFlags::default(),
92        );
93
94        assert_eq!(packet.effect_id, 0);
95    }
96}