Skip to main content

steel_core/entity/ai/goal/
move_towards_restriction.rs

1use std::f64::consts::FRAC_PI_2;
2
3use glam::DVec3;
4
5use super::random_pos::default_random_pos_towards;
6use super::selector::{Goal, GoalControls};
7use crate::entity::PathfinderMob;
8
9pub struct MoveTowardsRestrictionGoal {
10    wanted_position: Option<DVec3>,
11    speed_modifier: f64,
12}
13
14impl MoveTowardsRestrictionGoal {
15    #[must_use]
16    pub(crate) const fn new(speed_modifier: f64) -> Self {
17        Self {
18            wanted_position: None,
19            speed_modifier,
20        }
21    }
22}
23
24impl Goal for MoveTowardsRestrictionGoal {
25    fn controls(&self) -> GoalControls {
26        GoalControls::MOVE
27    }
28
29    fn can_use(&mut self, mob: &dyn PathfinderMob) -> bool {
30        if mob.is_within_home() {
31            return false;
32        }
33
34        let (x, y, z) = mob.home_position().get_bottom_center();
35        let Some(position) = default_random_pos_towards(mob, 16, 7, DVec3::new(x, y, z), FRAC_PI_2)
36        else {
37            return false;
38        };
39
40        self.wanted_position = Some(position);
41        true
42    }
43
44    fn can_continue_to_use(&mut self, mob: &dyn PathfinderMob) -> bool {
45        !mob.mob_base().navigation().lock().is_done()
46    }
47
48    fn start(&mut self, mob: &dyn PathfinderMob) {
49        if let Some(wanted_position) = self.wanted_position {
50            mob.move_to_pos(wanted_position, self.speed_modifier);
51        }
52    }
53}
54
55#[cfg(test)]
56mod tests {
57    use std::sync::Weak;
58
59    use steel_registry::{init_vanilla_registry, vanilla_entities};
60    use steel_utils::BlockPos;
61
62    use super::*;
63    use crate::entity::{Mob, entities::PigEntity};
64
65    #[test]
66    fn move_towards_restriction_goal_uses_move_control() {
67        let goal = MoveTowardsRestrictionGoal::new(1.0);
68
69        assert_eq!(goal.controls(), GoalControls::MOVE);
70    }
71
72    #[test]
73    fn move_towards_restriction_goal_requires_outside_home() {
74        init_vanilla_registry();
75        let mut goal = MoveTowardsRestrictionGoal::new(1.0);
76        let mob = PigEntity::new(&vanilla_entities::PIG, 1, DVec3::ZERO, Weak::new());
77        mob.set_home_to(BlockPos::ZERO, 4);
78
79        assert!(!goal.can_use(&mob));
80    }
81}