Skip to main content

steel_core/entity/
ticking.rs

1//! Shared vanilla entity tick helpers.
2
3use rustc_hash::FxHashSet;
4
5use super::{Entity, SharedEntity};
6
7/// Snapshots vanilla old position and rotation before an entity tick.
8pub(crate) fn snapshot_old_pos_and_rot_for_tick(entity: &dyn Entity) {
9    entity.set_old_position_to_current();
10    entity.base().set_old_rotation_to_current();
11}
12
13/// Recursively ticks vehicle passengers that are eligible in the caller's tick context.
14///
15/// Mirrors vanilla `ServerLevel.tickPassenger`: invalid vehicle links are detached, and
16/// passengers only recurse when the server-level entity tick list says they may tick.
17pub(crate) fn tick_vehicle_passengers_with_ticked_if(
18    vehicle: &dyn Entity,
19    ticked_entities: &mut FxHashSet<i32>,
20    post_tick: &mut impl FnMut(&SharedEntity),
21    can_tick: &mut impl FnMut(&SharedEntity) -> bool,
22) {
23    let mut visited = FxHashSet::default();
24    visited.insert(vehicle.id());
25
26    for passenger in vehicle.passengers() {
27        tick_passenger(
28            vehicle,
29            &passenger,
30            ticked_entities,
31            post_tick,
32            can_tick,
33            &mut visited,
34        );
35    }
36}
37
38fn tick_passenger(
39    vehicle: &dyn Entity,
40    entity: &SharedEntity,
41    ticked_entities: &mut FxHashSet<i32>,
42    post_tick: &mut impl FnMut(&SharedEntity),
43    can_tick: &mut impl FnMut(&SharedEntity) -> bool,
44    visited: &mut FxHashSet<i32>,
45) {
46    assert!(
47        visited.insert(entity.id()),
48        "cyclic passenger relationship involving entity {}",
49        entity.id()
50    );
51
52    if entity.is_removed()
53        || entity
54            .vehicle()
55            .is_none_or(|current_vehicle| current_vehicle.id() != vehicle.id())
56    {
57        entity.stop_riding();
58        visited.remove(&entity.id());
59        return;
60    }
61
62    if can_tick(entity) && ticked_entities.insert(entity.id()) {
63        snapshot_old_pos_and_rot_for_tick(entity.as_ref());
64        entity.advance_tick_count();
65        entity.ride_tick();
66        post_tick(entity);
67
68        for passenger in entity.passengers() {
69            tick_passenger(
70                entity.as_ref(),
71                &passenger,
72                ticked_entities,
73                post_tick,
74                can_tick,
75                visited,
76            );
77        }
78    }
79
80    visited.remove(&entity.id());
81}