steel_core/entity/
ticking.rs1use std::sync::Arc;
4
5use smallvec::SmallVec;
6
7use super::{Entity, SharedEntity};
8
9pub(crate) type VehicleChain = SmallVec<[i32; 8]>;
11
12pub(crate) fn snapshot_old_pos_and_rot_for_tick(entity: &dyn Entity) {
14 entity.set_old_position_to_current();
15 entity.base().set_old_rotation_to_current();
16}
17
18pub(crate) fn tick_vehicle_passengers_if(
23 vehicle: &dyn Entity,
24 post_tick: &mut impl FnMut(&SharedEntity),
25 can_tick: &mut impl FnMut(&SharedEntity) -> bool,
26) {
27 let passengers = vehicle.passengers();
28 if passengers.is_empty() {
29 return;
30 }
31
32 let mut visited = VehicleChain::new();
33 visited.push(vehicle.id());
34
35 for passenger in passengers {
36 tick_passenger(vehicle, &passenger, post_tick, can_tick, &mut visited);
37 }
38}
39
40fn tick_passenger(
41 vehicle: &dyn Entity,
42 entity: &SharedEntity,
43 post_tick: &mut impl FnMut(&SharedEntity),
44 can_tick: &mut impl FnMut(&SharedEntity) -> bool,
45 visited: &mut VehicleChain,
46) {
47 let entity_id = entity.id();
48 assert!(
49 !visited.contains(&entity_id),
50 "cyclic passenger relationship involving entity {entity_id}"
51 );
52 visited.push(entity_id);
53
54 if entity.is_removed()
55 || entity
56 .vehicle()
57 .is_none_or(|current_vehicle| current_vehicle.id() != vehicle.id())
58 {
59 entity.stop_riding();
60 visited.pop();
61 return;
62 }
63
64 if can_tick(entity) {
65 snapshot_old_pos_and_rot_for_tick(entity.as_ref());
66 entity.advance_tick_count();
67 Arc::clone(entity).ride_tick();
68 post_tick(entity);
69
70 for passenger in entity.passengers() {
71 tick_passenger(entity.as_ref(), &passenger, post_tick, can_tick, visited);
72 }
73 }
74
75 visited.pop();
76}