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