steel_core/entity/ai/goal/
restrict_sun.rs1use super::selector::{Goal, GoalControls};
2use crate::entity::PathfinderMob;
3use crate::inventory::equipment::EquipmentSlot;
4
5pub struct RestrictSunGoal;
6
7impl RestrictSunGoal {
8 #[must_use]
9 pub(crate) const fn new() -> Self {
10 Self
11 }
12}
13
14impl Goal for RestrictSunGoal {
15 fn controls(&self) -> GoalControls {
16 GoalControls::EMPTY
17 }
18
19 fn can_use(&mut self, mob: &dyn PathfinderMob) -> bool {
20 let Some(world) = mob.level() else {
21 return false;
22 };
23
24 world.is_bright_outside() && !mob.has_item_in_slot(EquipmentSlot::Head)
25 }
26
27 fn start(&mut self, mob: &dyn PathfinderMob) {
28 mob.mob_base().navigation().lock().set_avoid_sun(true);
29 }
30
31 fn stop(&mut self, mob: &dyn PathfinderMob) {
32 mob.mob_base().navigation().lock().set_avoid_sun(false);
33 }
34}
35
36#[cfg(test)]
37mod tests {
38 use std::sync::Weak;
39
40 use glam::DVec3;
41 use steel_registry::{init_vanilla_registry, vanilla_entities};
42
43 use super::*;
44 use crate::entity::Mob as _;
45 use crate::entity::entities::PigEntity;
46
47 fn pig() -> PigEntity {
48 PigEntity::new(&vanilla_entities::PIG, 1, DVec3::ZERO, Weak::new())
49 }
50
51 #[test]
52 fn restrict_sun_goal_claims_no_controls_like_vanilla() {
53 let goal = RestrictSunGoal::new();
54
55 assert_eq!(goal.controls(), GoalControls::EMPTY);
56 }
57
58 #[test]
59 fn restrict_sun_goal_requires_world() {
60 init_vanilla_registry();
61 let mut goal = RestrictSunGoal::new();
62
63 assert!(!goal.can_use(&pig()));
64 }
65
66 #[test]
67 fn restrict_sun_goal_toggles_navigation_avoid_sun() {
68 init_vanilla_registry();
69 let mut goal = RestrictSunGoal::new();
70 let pig = pig();
71
72 assert!(!pig.mob_base().navigation().lock().avoid_sun());
73
74 goal.start(&pig);
75 assert!(pig.mob_base().navigation().lock().avoid_sun());
76
77 goal.stop(&pig);
78 assert!(!pig.mob_base().navigation().lock().avoid_sun());
79 }
80}