steel_core/entity/ai/goal/
open_door.rs1use 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}