Skip to main content

steel_core/entity/ai/walk/
settings.rs

1use super::{BlockPos, FluidState, Mob, PathType, PathfindingMalus, WorldAabb, fast_floor};
2
3#[derive(Debug, Clone)]
4pub struct MobPathSettings {
5    entity_width: i32,
6    entity_height: i32,
7    entity_depth: i32,
8    mob_position_vec: glam::DVec3,
9    mob_position: BlockPos,
10    bounding_box: WorldAabb,
11    on_ground: bool,
12    in_water: bool,
13    can_stand_on_fluid: fn(FluidState) -> bool,
14    max_up_step: f32,
15    max_fall_distance: i32,
16    malus: [f32; PathType::COUNT],
17    can_pass_doors: bool,
18    can_open_doors: bool,
19    can_float: bool,
20    can_walk_over_fences: bool,
21}
22
23impl MobPathSettings {
24    #[must_use]
25    pub fn from_mob<M: Mob + ?Sized>(mob: &M) -> Self {
26        let bounding_box = mob.bounding_box();
27        let mut malus = [0.0; PathType::COUNT];
28        for path_type in PathType::ALL {
29            malus[path_type.index()] = mob.get_pathfinding_malus(path_type);
30        }
31
32        let navigation = mob.mob_base().navigation().lock();
33        let can_float = navigation.can_float();
34        let can_open_doors = navigation.can_open_doors();
35        let can_walk_over_fences = navigation.can_walk_over_fences();
36        drop(navigation);
37
38        Self {
39            entity_width: fast_floor(bounding_box.width() + 1.0),
40            entity_height: fast_floor(bounding_box.height() + 1.0),
41            entity_depth: fast_floor(bounding_box.width() + 1.0),
42            mob_position_vec: mob.position(),
43            mob_position: mob.block_position(),
44            bounding_box,
45            on_ground: mob.on_ground(),
46            in_water: mob.is_in_water(),
47            can_stand_on_fluid: |_| false,
48            max_up_step: mob.max_up_step(),
49            max_fall_distance: mob.max_fall_distance(),
50            malus,
51            can_pass_doors: true,
52            can_open_doors,
53            can_float,
54            can_walk_over_fences,
55        }
56    }
57
58    #[must_use]
59    pub fn new(
60        entity_width: i32,
61        entity_height: i32,
62        entity_depth: i32,
63        mob_position: BlockPos,
64        pathfinding_malus: &PathfindingMalus,
65    ) -> Self {
66        let width = entity_width.max(1);
67        let height = entity_height.max(1);
68        let depth = entity_depth.max(1);
69        let center_x = f64::from(mob_position.x()) + 0.5;
70        let center_z = f64::from(mob_position.z()) + 0.5;
71        let bounding_box = WorldAabb::new(
72            center_x - f64::from(width) * 0.5,
73            f64::from(mob_position.y()),
74            center_z - f64::from(depth) * 0.5,
75            center_x + f64::from(width) * 0.5,
76            f64::from(mob_position.y()) + f64::from(height),
77            center_z + f64::from(depth) * 0.5,
78        );
79        let mut malus = [0.0; PathType::COUNT];
80        for path_type in PathType::ALL {
81            malus[path_type.index()] = pathfinding_malus.get(path_type);
82        }
83
84        Self {
85            entity_width: width,
86            entity_height: height,
87            entity_depth: depth,
88            mob_position_vec: glam::DVec3::new(center_x, f64::from(mob_position.y()), center_z),
89            mob_position,
90            bounding_box,
91            on_ground: true,
92            in_water: false,
93            can_stand_on_fluid: |_| false,
94            max_up_step: 0.6,
95            max_fall_distance: 3,
96            malus,
97            can_pass_doors: true,
98            can_open_doors: false,
99            can_float: false,
100            can_walk_over_fences: false,
101        }
102    }
103
104    #[must_use]
105    pub const fn with_can_pass_doors(mut self, can_pass_doors: bool) -> Self {
106        self.can_pass_doors = can_pass_doors;
107        self
108    }
109
110    #[must_use]
111    pub const fn with_can_open_doors(mut self, can_open_doors: bool) -> Self {
112        self.can_open_doors = can_open_doors;
113        self
114    }
115
116    #[must_use]
117    pub const fn with_can_float(mut self, can_float: bool) -> Self {
118        self.can_float = can_float;
119        self
120    }
121
122    #[must_use]
123    pub const fn with_can_walk_over_fences(mut self, can_walk_over_fences: bool) -> Self {
124        self.can_walk_over_fences = can_walk_over_fences;
125        self
126    }
127
128    #[must_use]
129    pub const fn with_max_up_step(mut self, max_up_step: f32) -> Self {
130        self.max_up_step = max_up_step;
131        self
132    }
133
134    #[must_use]
135    pub const fn with_max_fall_distance(mut self, max_fall_distance: i32) -> Self {
136        self.max_fall_distance = max_fall_distance;
137        self
138    }
139
140    #[must_use]
141    pub const fn with_on_ground(mut self, on_ground: bool) -> Self {
142        self.on_ground = on_ground;
143        self
144    }
145
146    #[must_use]
147    pub const fn with_in_water(mut self, in_water: bool) -> Self {
148        self.in_water = in_water;
149        self
150    }
151
152    #[must_use]
153    pub const fn with_can_stand_on_fluid(
154        mut self,
155        can_stand_on_fluid: fn(FluidState) -> bool,
156    ) -> Self {
157        self.can_stand_on_fluid = can_stand_on_fluid;
158        self
159    }
160
161    #[must_use]
162    pub const fn entity_width(&self) -> i32 {
163        self.entity_width
164    }
165
166    #[must_use]
167    pub const fn entity_height(&self) -> i32 {
168        self.entity_height
169    }
170
171    #[must_use]
172    pub const fn entity_depth(&self) -> i32 {
173        self.entity_depth
174    }
175
176    #[must_use]
177    pub const fn mob_position(&self) -> BlockPos {
178        self.mob_position
179    }
180
181    #[must_use]
182    pub const fn mob_position_vec(&self) -> glam::DVec3 {
183        self.mob_position_vec
184    }
185
186    #[must_use]
187    pub const fn bounding_box(&self) -> WorldAabb {
188        self.bounding_box
189    }
190
191    #[must_use]
192    pub const fn on_ground(&self) -> bool {
193        self.on_ground
194    }
195
196    #[must_use]
197    pub const fn in_water(&self) -> bool {
198        self.in_water
199    }
200
201    #[must_use]
202    pub fn can_stand_on_fluid(&self, fluid_state: FluidState) -> bool {
203        (self.can_stand_on_fluid)(fluid_state)
204    }
205
206    #[must_use]
207    pub const fn max_up_step(&self) -> f32 {
208        self.max_up_step
209    }
210
211    #[must_use]
212    pub const fn max_fall_distance(&self) -> i32 {
213        self.max_fall_distance
214    }
215
216    #[must_use]
217    pub const fn pathfinding_malus(&self, path_type: PathType) -> f32 {
218        self.malus[path_type.index()]
219    }
220
221    #[must_use]
222    pub const fn can_pass_doors(&self) -> bool {
223        self.can_pass_doors
224    }
225
226    #[must_use]
227    pub const fn can_open_doors(&self) -> bool {
228        self.can_open_doors
229    }
230
231    #[must_use]
232    pub const fn can_float(&self) -> bool {
233        self.can_float
234    }
235
236    #[must_use]
237    pub const fn can_walk_over_fences(&self) -> bool {
238        self.can_walk_over_fences
239    }
240}