Skip to main content

steel_core/entity/ai/goal/
open_door.rs

1use super::door_interact::DoorInteractGoal;
2use super::selector::{Goal, GoalControls};
3use crate::entity::PathfinderMob;
4use crate::entity::SharedEntity;
5
6const FORGET_TICKS: i32 = 20;
7
8pub struct OpenDoorGoal {
9    door_interact: DoorInteractGoal,
10    close_door: bool,
11    forget_time: i32,
12}
13
14impl OpenDoorGoal {
15    #[must_use]
16    pub(crate) const fn new(close_door_after: bool) -> Self {
17        Self {
18            door_interact: DoorInteractGoal::new(),
19            close_door: close_door_after,
20            forget_time: 0,
21        }
22    }
23}
24
25impl Goal for OpenDoorGoal {
26    fn controls(&self) -> GoalControls {
27        GoalControls::EMPTY
28    }
29
30    fn can_use(&mut self, mob: &dyn PathfinderMob) -> bool {
31        self.door_interact.can_use(mob)
32    }
33
34    fn can_continue_to_use(&mut self, _mob: &dyn PathfinderMob) -> bool {
35        self.close_door && self.forget_time > 0 && self.door_interact.can_continue_to_use()
36    }
37
38    fn start(&mut self, mob: &dyn PathfinderMob) {
39        self.forget_time = FORGET_TICKS;
40        self.door_interact.set_open(mob, true);
41    }
42
43    fn stop(&mut self, mob: &dyn PathfinderMob) {
44        self.door_interact.set_open(mob, false);
45    }
46
47    fn requires_update_every_tick(&self) -> bool {
48        true
49    }
50
51    fn tick(&mut self, mob: &dyn PathfinderMob, _entity: &SharedEntity) {
52        self.forget_time -= 1;
53        self.door_interact.tick(mob);
54    }
55}
56
57#[cfg(test)]
58mod tests {
59    use std::sync::Arc;
60
61    use std::sync::Weak;
62
63    use glam::DVec3;
64    use steel_registry::{init_vanilla_registry, vanilla_entities};
65
66    use super::*;
67    use crate::entity::entities::PigEntity;
68
69    fn pig() -> PigEntity {
70        PigEntity::new(&vanilla_entities::PIG, 1, DVec3::ZERO, Weak::new())
71    }
72
73    #[test]
74    fn open_door_goal_claims_no_controls_like_vanilla() {
75        let goal = OpenDoorGoal::new(true);
76
77        assert_eq!(goal.controls(), GoalControls::EMPTY);
78        assert!(goal.requires_update_every_tick());
79    }
80
81    #[test]
82    fn open_door_goal_continue_requires_close_door_flag() {
83        init_vanilla_registry();
84        let mut goal = OpenDoorGoal::new(false);
85        goal.forget_time = 1;
86
87        assert!(!goal.can_continue_to_use(&pig()));
88    }
89
90    #[test]
91    fn open_door_goal_uses_vanilla_forget_time() {
92        init_vanilla_registry();
93        let mut goal = OpenDoorGoal::new(true);
94        let mob = Arc::new(pig());
95        let mob_entity: SharedEntity = Arc::<PigEntity>::clone(&mob);
96
97        goal.start(mob.as_ref());
98
99        assert_eq!(goal.forget_time, FORGET_TICKS);
100        assert!(goal.can_continue_to_use(mob.as_ref()));
101
102        goal.tick(mob.as_ref(), &mob_entity);
103
104        assert_eq!(goal.forget_time, FORGET_TICKS - 1);
105    }
106}