steel_core/entity/pushing/
snapshot.rs1use glam::DVec3;
2
3use super::EntityPush;
4use crate::entity::{Entity, LivingEntity};
5
6pub trait DefaultEntityPush: Entity {
10 fn push_snapshot(&self, known_pushable: bool) -> Option<EntityPushSnapshot> {
13 let state = self.base().unmounted_push_state()?;
14
15 Some(EntityPushSnapshot {
16 position: state.position,
17 no_physics: state.no_physics,
18 receives_impulse: !state.is_vehicle && (known_pushable || self.is_pushable()),
19 sleeping: self
20 .as_living_entity()
21 .is_some_and(LivingEntity::is_sleeping),
22 })
23 }
24}
25
26#[derive(Clone, Copy, Debug)]
28pub struct EntityPushSnapshot {
29 position: DVec3,
30 no_physics: bool,
31 receives_impulse: bool,
32 sleeping: bool,
33}
34
35impl EntityPush {
36 pub(super) fn apply_contact(
37 source: &dyn Entity,
38 source_state: EntityPushSnapshot,
39 target: &dyn Entity,
40 target_state: EntityPushSnapshot,
41 ) {
42 if source_state.sleeping || source_state.no_physics || target_state.no_physics {
43 return;
44 }
45
46 let Some(impulse) = Self::impulse(source_state.position, target_state.position) else {
47 return;
48 };
49
50 if source_state.receives_impulse {
51 source
52 .base()
53 .push_impulse(DVec3::new(-impulse.x, 0.0, -impulse.z));
54 }
55
56 if target_state.receives_impulse {
57 target.base().push_impulse(impulse);
58 }
59 }
60}