1use glam::DVec3;
2use steel_utils::BlockPos;
3
4#[derive(Debug, Clone, Copy, PartialEq)]
6pub struct EntityMovement {
7 from: DVec3,
8 to: DVec3,
9 axis_dependent_original_movement: Option<DVec3>,
10}
11
12impl EntityMovement {
13 #[must_use]
15 pub const fn new(from: DVec3, to: DVec3) -> Self {
16 Self {
17 from,
18 to,
19 axis_dependent_original_movement: None,
20 }
21 }
22
23 #[must_use]
25 pub const fn with_axis_dependent_original_movement(
26 from: DVec3,
27 to: DVec3,
28 axis_dependent_original_movement: DVec3,
29 ) -> Self {
30 Self {
31 from,
32 to,
33 axis_dependent_original_movement: Some(axis_dependent_original_movement),
34 }
35 }
36
37 #[must_use]
39 pub const fn from(self) -> DVec3 {
40 self.from
41 }
42
43 #[must_use]
45 pub const fn to(self) -> DVec3 {
46 self.to
47 }
48
49 #[must_use]
51 pub const fn axis_dependent_original_movement(self) -> Option<DVec3> {
52 self.axis_dependent_original_movement
53 }
54}
55
56#[derive(Debug, Clone, Copy, PartialEq, Eq)]
58pub enum EntityVerticalMovementStateUpdate {
59 Preserve,
61 Refresh,
63}
64
65impl EntityVerticalMovementStateUpdate {
66 #[must_use]
68 pub fn for_move(requested_delta: DVec3, server_driven_movement: bool) -> Self {
69 if requested_delta.y.abs() > 0.0 || server_driven_movement {
70 Self::Refresh
71 } else {
72 Self::Preserve
73 }
74 }
75
76 #[inline]
78 #[must_use]
79 pub const fn refreshes_state(self) -> bool {
80 matches!(self, Self::Refresh)
81 }
82}
83
84#[derive(Debug, Clone, Copy, PartialEq, Eq)]
86pub struct EntityMovementFlags {
87 on_ground: bool,
88 horizontal_collision: bool,
89 vertical_collision: bool,
90 vertical_collision_below: bool,
91}
92
93impl EntityMovementFlags {
94 #[must_use]
96 pub const fn new() -> Self {
97 Self {
98 on_ground: false,
99 horizontal_collision: false,
100 vertical_collision: false,
101 vertical_collision_below: false,
102 }
103 }
104
105 #[must_use]
107 pub fn after_move(
108 on_ground: bool,
109 horizontal_collision: bool,
110 vertical_collision: bool,
111 requested_delta: DVec3,
112 ) -> Self {
113 Self {
114 on_ground,
115 horizontal_collision,
116 vertical_collision,
117 vertical_collision_below: vertical_collision && requested_delta.y < 0.0,
118 }
119 }
120
121 #[must_use]
124 pub fn after_move_with_previous(
125 previous: Self,
126 vertical_state_update: EntityVerticalMovementStateUpdate,
127 on_ground: bool,
128 horizontal_collision: bool,
129 vertical_collision: bool,
130 requested_delta: DVec3,
131 ) -> Self {
132 let mut next = previous.with_horizontal_collision(horizontal_collision);
133 if vertical_state_update.refreshes_state() {
134 next.on_ground = on_ground;
135 next.vertical_collision = vertical_collision;
136 next.vertical_collision_below = vertical_collision && requested_delta.y < 0.0;
137 }
138 next
139 }
140
141 #[inline]
143 #[must_use]
144 pub const fn on_ground(self) -> bool {
145 self.on_ground
146 }
147
148 #[inline]
150 #[must_use]
151 pub const fn horizontal_collision(self) -> bool {
152 self.horizontal_collision
153 }
154
155 #[inline]
157 #[must_use]
158 pub const fn vertical_collision(self) -> bool {
159 self.vertical_collision
160 }
161
162 #[inline]
164 #[must_use]
165 pub const fn vertical_collision_below(self) -> bool {
166 self.vertical_collision_below
167 }
168
169 #[must_use]
171 pub const fn with_on_ground(mut self, on_ground: bool) -> Self {
172 self.on_ground = on_ground;
173 self
174 }
175
176 #[must_use]
178 pub const fn with_horizontal_collision(mut self, horizontal_collision: bool) -> Self {
179 self.horizontal_collision = horizontal_collision;
180 self
181 }
182
183 #[must_use]
185 pub const fn without_collisions(mut self) -> Self {
186 self.horizontal_collision = false;
187 self.vertical_collision = false;
188 self.vertical_collision_below = false;
189 self
190 }
191}
192
193impl Default for EntityMovementFlags {
194 fn default() -> Self {
195 Self::new()
196 }
197}
198
199#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
201pub struct EntityGroundContact {
202 supporting_block: Option<BlockPos>,
203 on_ground_no_blocks: bool,
204}
205
206impl EntityGroundContact {
207 #[must_use]
209 pub const fn airborne() -> Self {
210 Self {
211 supporting_block: None,
212 on_ground_no_blocks: false,
213 }
214 }
215
216 #[must_use]
218 pub const fn on_ground(supporting_block: Option<BlockPos>) -> Self {
219 Self {
220 supporting_block,
221 on_ground_no_blocks: supporting_block.is_none(),
222 }
223 }
224
225 #[must_use]
227 pub const fn supporting_block(self) -> Option<BlockPos> {
228 self.supporting_block
229 }
230
231 #[must_use]
233 pub const fn on_ground_no_blocks(self) -> bool {
234 self.on_ground_no_blocks
235 }
236}
237
238#[derive(Debug, Clone, Copy, PartialEq, Eq)]
240pub enum EntityMovementEmission {
241 None,
243 Sounds,
245 Events,
247 All,
249}
250
251impl EntityMovementEmission {
252 #[must_use]
254 pub const fn emits_anything(self) -> bool {
255 !matches!(self, Self::None)
256 }
257
258 #[must_use]
260 pub const fn emits_events(self) -> bool {
261 matches!(self, Self::Events | Self::All)
262 }
263
264 #[must_use]
266 pub const fn emits_sounds(self) -> bool {
267 matches!(self, Self::Sounds | Self::All)
268 }
269}
270
271#[derive(Debug, Clone, Copy, PartialEq)]
273pub struct EntityMovementProgress {
274 pub(super) move_dist: f32,
275 pub(super) fly_dist: f32,
276 pub(super) next_step: f32,
277 pub(super) crystal_sound_intensity: f32,
278 pub(super) last_crystal_sound_play_tick: i32,
279}
280
281impl EntityMovementProgress {
282 #[must_use]
284 pub const fn new() -> Self {
285 Self {
286 move_dist: 0.0,
287 fly_dist: 0.0,
288 next_step: 1.0,
289 crystal_sound_intensity: 0.0,
290 last_crystal_sound_play_tick: 0,
291 }
292 }
293
294 pub fn add_movement(&mut self, clipped_movement: DVec3, climbing: bool) {
296 let moved_distance = (clipped_movement.length() * 0.6) as f32;
297 let horizontal_moved_distance = ((clipped_movement.x * clipped_movement.x
298 + clipped_movement.z * clipped_movement.z)
299 .sqrt()
300 * 0.6) as f32;
301
302 self.move_dist += if climbing {
303 moved_distance
304 } else {
305 horizontal_moved_distance
306 };
307 self.fly_dist += moved_distance;
308 }
309
310 #[must_use]
312 pub const fn move_dist(self) -> f32 {
313 self.move_dist
314 }
315
316 #[must_use]
318 pub const fn fly_dist(self) -> f32 {
319 self.fly_dist
320 }
321
322 #[must_use]
324 pub const fn next_step(self) -> f32 {
325 self.next_step
326 }
327
328 #[must_use]
330 pub const fn crossed_next_step(self) -> bool {
331 self.move_dist > self.next_step
332 }
333}
334
335impl Default for EntityMovementProgress {
336 fn default() -> Self {
337 Self::new()
338 }
339}