steel_protocol/packets/game/
c_player_position.rs1use glam::DVec3;
6use steel_macros::{ClientPacket, WriteTo};
7use steel_registry::packets::play::C_PLAYER_POSITION;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
14pub struct RelativeMovement(pub i32);
15
16impl RelativeMovement {
17 pub const X: i32 = 1 << 0;
19 pub const Y: i32 = 1 << 1;
21 pub const Z: i32 = 1 << 2;
23 pub const Y_ROT: i32 = 1 << 3;
25 pub const X_ROT: i32 = 1 << 4;
27 pub const DELTA_X: i32 = 1 << 5;
29 pub const DELTA_Y: i32 = 1 << 6;
31 pub const DELTA_Z: i32 = 1 << 7;
33 pub const ROTATE_DELTA: i32 = 1 << 8;
35
36 pub const NONE: RelativeMovement = RelativeMovement(0);
38
39 pub const ROTATION: RelativeMovement = RelativeMovement(Self::Y_ROT | Self::X_ROT);
41
42 pub const DELTA: RelativeMovement =
44 RelativeMovement(Self::DELTA_X | Self::DELTA_Y | Self::DELTA_Z | Self::ROTATE_DELTA);
45
46 #[must_use]
48 pub const fn new(flags: i32) -> Self {
49 Self(flags)
50 }
51
52 #[must_use]
54 pub const fn union(self, other: Self) -> Self {
55 Self(self.0 | other.0)
56 }
57
58 #[must_use]
60 pub const fn is_x_relative(self) -> bool {
61 self.0 & Self::X != 0
62 }
63
64 #[must_use]
66 pub const fn is_y_relative(self) -> bool {
67 self.0 & Self::Y != 0
68 }
69
70 #[must_use]
72 pub const fn is_z_relative(self) -> bool {
73 self.0 & Self::Z != 0
74 }
75
76 #[must_use]
78 pub const fn is_y_rot_relative(self) -> bool {
79 self.0 & Self::Y_ROT != 0
80 }
81
82 #[must_use]
84 pub const fn is_x_rot_relative(self) -> bool {
85 self.0 & Self::X_ROT != 0
86 }
87
88 #[must_use]
90 pub const fn is_delta_x_relative(self) -> bool {
91 self.0 & Self::DELTA_X != 0
92 }
93
94 #[must_use]
96 pub const fn is_delta_y_relative(self) -> bool {
97 self.0 & Self::DELTA_Y != 0
98 }
99
100 #[must_use]
102 pub const fn is_delta_z_relative(self) -> bool {
103 self.0 & Self::DELTA_Z != 0
104 }
105
106 #[must_use]
108 pub const fn rotates_delta(self) -> bool {
109 self.0 & Self::ROTATE_DELTA != 0
110 }
111}
112
113impl steel_utils::serial::WriteTo for RelativeMovement {
114 fn write(&self, writer: &mut impl std::io::Write) -> std::io::Result<()> {
115 self.0.write(writer)
116 }
117}
118
119#[derive(ClientPacket, WriteTo, Clone, Debug)]
125#[packet_id(Play = C_PLAYER_POSITION)]
126pub struct CPlayerPosition {
127 #[write(as = VarInt)]
129 pub teleport_id: i32,
130 pub pos: DVec3,
132 pub vel: DVec3,
134 pub yaw: f32,
136 pub pitch: f32,
138 pub relatives: RelativeMovement,
140}
141
142impl CPlayerPosition {
143 #[must_use]
145 pub const fn new(
146 teleport_id: i32,
147 pos: DVec3,
148 vel: DVec3,
149 yaw: f32,
150 pitch: f32,
151 relatives: RelativeMovement,
152 ) -> Self {
153 Self {
154 teleport_id,
155 pos,
156 vel,
157 yaw,
158 pitch,
159 relatives,
160 }
161 }
162
163 #[must_use]
165 pub const fn absolute(teleport_id: i32, pos: DVec3, yaw: f32, pitch: f32) -> Self {
166 Self::absolute_with_velocity(teleport_id, pos, DVec3::ZERO, yaw, pitch)
167 }
168
169 #[must_use]
171 pub const fn absolute_with_velocity(
172 teleport_id: i32,
173 pos: DVec3,
174 vel: DVec3,
175 yaw: f32,
176 pitch: f32,
177 ) -> Self {
178 Self::new(teleport_id, pos, vel, yaw, pitch, RelativeMovement::NONE)
179 }
180
181 #[must_use]
183 pub const fn with_relative_rotation(teleport_id: i32, pos: DVec3) -> Self {
184 Self {
185 teleport_id,
186 pos,
187 vel: DVec3::ZERO,
188 yaw: 0.0,
189 pitch: 0.0,
190 relatives: RelativeMovement::ROTATION,
191 }
192 }
193}
194
195#[cfg(test)]
196mod tests {
197 use glam::DVec3;
198
199 use super::{CPlayerPosition, RelativeMovement};
200
201 #[test]
202 fn delta_matches_vanilla_relative_delta_set() {
203 assert_eq!(
204 RelativeMovement::DELTA.0,
205 RelativeMovement::DELTA_X
206 | RelativeMovement::DELTA_Y
207 | RelativeMovement::DELTA_Z
208 | RelativeMovement::ROTATE_DELTA
209 );
210 }
211
212 #[test]
213 fn absolute_with_velocity_preserves_delta_movement() {
214 let packet = CPlayerPosition::absolute_with_velocity(
215 12,
216 DVec3::new(1.0, 2.0, 3.0),
217 DVec3::new(0.1, 0.2, 0.3),
218 45.0,
219 -10.0,
220 );
221
222 assert_eq!(packet.teleport_id, 12);
223 assert_eq!(packet.pos, DVec3::new(1.0, 2.0, 3.0));
224 assert_eq!(packet.vel, DVec3::new(0.1, 0.2, 0.3));
225 assert_eq!(packet.yaw, 45.0);
226 assert_eq!(packet.pitch, -10.0);
227 assert_eq!(packet.relatives, RelativeMovement::NONE);
228 }
229}