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