steel_protocol/packets/game/
c_add_entity.rs1use glam::DVec3;
4use steel_macros::ClientPacket;
5use steel_registry::packets::play::C_ADD_ENTITY;
6use steel_utils::codec::{LpVec3, VarInt};
7use steel_utils::serial::WriteTo;
8use uuid::Uuid;
9
10#[derive(ClientPacket, Clone, Debug)]
12#[packet_id(Play = C_ADD_ENTITY)]
13pub struct CAddEntity {
14 pub id: i32,
16 pub uuid: Uuid,
18 pub entity_type: i32,
20 pub position: DVec3,
22 pub velocity: DVec3,
24 pub x_rot: i8,
26 pub y_rot: i8,
28 pub head_y_rot: i8,
30 pub data: i32,
32}
33
34impl WriteTo for CAddEntity {
35 fn write(&self, writer: &mut impl std::io::Write) -> std::io::Result<()> {
36 VarInt(self.id).write(writer)?;
37 self.uuid.write(writer)?;
38 VarInt(self.entity_type).write(writer)?;
39 writer.write_all(&self.position.x.to_be_bytes())?;
40 writer.write_all(&self.position.y.to_be_bytes())?;
41 writer.write_all(&self.position.z.to_be_bytes())?;
42
43 write_lp_vec3(writer, self.velocity)?;
45
46 self.x_rot.write(writer)?;
47 self.y_rot.write(writer)?;
48 self.head_y_rot.write(writer)?;
49 VarInt(self.data).write(writer)
50 }
51}
52
53pub fn write_lp_vec3(writer: &mut impl std::io::Write, velocity: DVec3) -> std::io::Result<()> {
58 LpVec3(velocity).write(writer)
59}
60
61impl CAddEntity {
62 #[must_use]
64 pub const fn player(
65 id: i32,
66 uuid: Uuid,
67 entity_type_id: i32,
68 position: DVec3,
69 yaw: f32,
70 pitch: f32,
71 ) -> Self {
72 Self {
73 id,
74 uuid,
75 entity_type: entity_type_id,
76 position,
77 velocity: DVec3::ZERO,
78 x_rot: super::to_angle_byte(pitch),
79 y_rot: super::to_angle_byte(yaw),
80 head_y_rot: super::to_angle_byte(yaw),
81 data: 0,
82 }
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89
90 #[test]
91 fn test_zero_velocity() {
92 let mut buf = Vec::new();
93 write_lp_vec3(&mut buf, DVec3::ZERO).unwrap();
94 assert_eq!(buf, vec![0]);
95 }
96
97 #[test]
98 fn test_tiny_velocity_is_zero() {
99 let mut buf = Vec::new();
100 write_lp_vec3(&mut buf, DVec3::splat(1e-6)).unwrap();
101 assert_eq!(buf, vec![0]);
102 }
103
104 #[test]
105 fn test_non_zero_velocity() {
106 let mut buf = Vec::new();
107 write_lp_vec3(&mut buf, DVec3::ZERO.with_x(1.0)).unwrap();
108 assert_eq!(buf.len(), 6);
110 }
111
112 #[test]
113 fn test_negative_velocity_uses_absolute_scale() {
114 let mut buf = Vec::new();
115 write_lp_vec3(&mut buf, DVec3::ZERO.with_x(-1.0)).unwrap();
116 assert_eq!(buf.len(), 6);
117 }
118
119 #[test]
120 fn test_velocity_with_scale() {
121 let mut buf = Vec::new();
123 write_lp_vec3(&mut buf, DVec3::ZERO.with_x(5.0)).unwrap();
124 assert_eq!(buf[0] & 0x04, 0x04, "Continuation flag should be set");
127 assert!(buf.len() > 6, "Should have continuation VarInt");
129 }
130}