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