Skip to main content

steel_protocol/packets/game/
s_interact.rs

1use glam::DVec3;
2use steel_macros::ServerPacket;
3use steel_utils::codec::{LpVec3, VarInt};
4use steel_utils::serial::ReadFrom;
5use steel_utils::types::InteractionHand;
6
7/// Serverbound packet sent when a player right-clicks an entity.
8#[derive(ServerPacket, Clone, Debug)]
9pub struct SInteract {
10    pub entity_id: i32,
11    pub hand: InteractionHand,
12    pub location: DVec3,
13    pub using_secondary_action: bool,
14}
15
16impl ReadFrom for SInteract {
17    fn read(data: &mut std::io::Cursor<&[u8]>) -> std::io::Result<Self> {
18        Ok(Self {
19            entity_id: VarInt::read(data)?.0,
20            hand: InteractionHand::read(data)?,
21            location: LpVec3::read(data)?.0,
22            using_secondary_action: bool::read(data)?,
23        })
24    }
25}
26
27#[cfg(test)]
28mod tests {
29    use std::io::Cursor;
30
31    use steel_utils::serial::WriteTo as _;
32
33    use super::*;
34
35    #[test]
36    fn interact_packet_reads_vanilla_field_order() {
37        let mut bytes = Vec::new();
38        bytes.push(42);
39        bytes.push(1);
40        LpVec3(DVec3::new(0.25, 0.5, 0.75))
41            .write(&mut bytes)
42            .unwrap();
43        bytes.push(1);
44
45        let packet = SInteract::read(&mut Cursor::new(&bytes))
46            .unwrap_or_else(|error| panic!("interact packet should parse: {error}"));
47
48        assert_eq!(packet.entity_id, 42);
49        assert_eq!(packet.hand, InteractionHand::OffHand);
50        assert!((packet.location.x - 0.25).abs() < 0.0001);
51        assert!((packet.location.y - 0.5).abs() < 0.0001);
52        assert!((packet.location.z - 0.75).abs() < 0.0001);
53        assert!(packet.using_secondary_action);
54    }
55}