Merge pull request #1537 from ludovic111/fix/mob-path-max-visited

This commit is contained in:
Ludovic Marie authored and GitHub committed 2026-10-24 07:52:25 +02:00
commit f67b2b3204
12 files changed
+45 -9

No files matched your search

+1
View File
@@ -1054,6 +1054,7 @@ impl Game<'_> {
let r = &mut self.world.random;
let bonus = r.triangle(0.0, 0.11485000000000001);
mob.attrs.follow_range += mob.kind.follow_range * bonus;
mob.update_max_visited_nodes();
let _left_handed = r.next_float() < 0.05;
if !self.warden_fits(&mob) {
continue;
+2
View File
@@ -1602,6 +1602,8 @@ impl Mob {
| Species::Fox
| Species::Panda
);
// The PathNavigation constructor: the base follow range.
mob.ai.nav.max_visited_nodes = (mob.kind.follow_range * 16.0).floor() as i32;
ai::register(&mut mob);
mob
}
+1 -1
View File
@@ -26,7 +26,7 @@ pub fn register(m: &mut Mob) {
};
m.ai.nav.kind = NavKind::Flying;
// FlyingPathNavigation.setRequiredPathLength(48).
m.ai.nav.required_path_length = 48.0;
m.set_required_path_length(48.0);
let g = &mut m.ai.goals;
g.add(0, Panic::new(2.5));
g.add(1, Fetch);
+1 -1
View File
@@ -138,7 +138,7 @@ pub fn register(m: &mut Mob) {
};
m.ai.nav.kind = NavKind::Flying;
m.ai.nav.can_open_doors = false;
m.ai.nav.required_path_length = 48.0;
m.set_required_path_length(48.0);
m.set_malus(PathType::Fire, -1.0);
m.set_malus(PathType::Water, -1.0);
m.set_malus(PathType::WaterBorder, 16.0);
@@ -26,7 +26,7 @@ pub const DROPPING_NO_ITEM: u8 = 4;
pub const WEATHER: [&str; 4] = ["unaffected", "exposed", "weathered", "oxidized"];
pub fn register(m: &mut Mob) {
m.ai.nav.required_path_length = 48.0;
m.set_required_path_length(48.0);
m.ai.nav.can_open_doors = true;
m.persistent = true;
// nextWeatheringTick starts unset (-1); waxed is -2.
@@ -464,6 +464,7 @@ pub fn finalize_spawn(m: &mut Mob, lr: &mut LegacyRandom) {
let bonus = lr.triangle(0.0, 0.114_850_000_000_000_01);
// ADD_MULTIPLIED_BASE on the base value.
m.attrs.follow_range += m.kind.follow_range * bonus;
m.update_max_visited_nodes();
let _left_handed = lr.next_float() < 0.05;
}
fn wrap_degrees(angle: f32) -> f32 {
+4 -1
View File
@@ -559,7 +559,10 @@ fn refresh(m: &mut Mob, a: Attr) {
match a {
Attr::MaxHealth => m.attrs.max_health = value(m, a) as f32,
Attr::MovementSpeed => m.attrs.speed = base_with_modifiers(m, a),
Attr::FollowRange => m.attrs.follow_range = value(m, a),
Attr::FollowRange => {
m.attrs.follow_range = value(m, a);
m.update_max_visited_nodes();
}
Attr::AttackDamage => m.attrs.attack_damage = value(m, a) as f32,
Attr::KnockbackResistance => m.attrs.knockback_resistance = value(m, a),
Attr::SpawnReinforcements => m.attrs.spawn_reinforcements = value(m, a),
@@ -39,6 +39,10 @@ fn setup(m: &mut Mob, baby: bool) {
m.ai.look.wanted = [0.0; 3];
m.ai.look.cooldown = 0;
m.extra.counter2 = 0;
// The new navigation's PathNavigation constructor.
m.ai.nav.required_path_length = 16.0;
m.ai.nav.max_visited_nodes =
(super::finalize::base_value(m, super::finalize::Attr::FollowRange) * 16.0).floor() as i32;
if baby {
m.ai.look.kind = LookKind::Default;
m.ai.mov.kind = MoveKind::Flying {
@@ -48,7 +52,7 @@ fn setup(m: &mut Mob, baby: bool) {
// BabyFlyingPathNavigation.
m.ai.nav.kind = NavKind::Flying;
m.ai.nav.can_float = true;
m.ai.nav.required_path_length = 48.0;
m.set_required_path_length(48.0);
return;
}
if was == 1 {
+1 -1
View File
@@ -50,7 +50,7 @@ pub fn is_illager(s: &Seen) -> bool {
)
}
pub fn register(m: &mut Mob) {
m.ai.nav.required_path_length = 40.0;
m.set_required_path_length(40.0);
let tempt = m.kind.tempt.clone();
let trader = is_trader(m);
if trader {
+17 -2
View File
@@ -37,7 +37,11 @@ pub struct Navigation {
reach_range: i32,
pub max_visited_multiplier: f32,
pub stuck: bool,
/// Set through [`Mob::set_required_path_length`].
pub required_path_length: f32,
/// `PathFinder.maxVisitedNodes`: the base follow range times 16 when the
/// navigation is made, then [`Mob::update_max_visited_nodes`].
pub max_visited_nodes: i32,
pub can_float: bool,
pub can_open_doors: bool,
pub can_pass_doors: bool,
@@ -68,6 +72,7 @@ impl Default for Navigation {
max_visited_multiplier: 1.0,
stuck: false,
required_path_length: 16.0,
max_visited_nodes: 256,
can_float: false,
can_open_doors: false,
can_pass_doors: true,
@@ -147,6 +152,16 @@ impl Mob {
fn max_path_length(&self) -> f32 {
(self.attrs.follow_range as f32).max(self.ai.nav.required_path_length)
}
/// `PathNavigation.updatePathfinderMaxVisitedNodes`: after a follow range
/// change and a new required path length.
pub fn update_max_visited_nodes(&mut self) {
self.ai.nav.max_visited_nodes = (self.max_path_length() * 16.0).floor() as i32;
}
/// `PathNavigation.setRequiredPathLength`.
pub fn set_required_path_length(&mut self, length: f32) {
self.ai.nav.required_path_length = length;
self.update_max_visited_nodes();
}
fn can_update_path(&self) -> bool {
match self.ai.nav.kind {
NavKind::Ground | NavKind::WallClimber => self.on_ground || self.is_in_liquid(),
@@ -237,8 +252,8 @@ impl Mob {
return Some(path.clone());
}
let pm = self.path_mob();
let max_visited = ((self.attrs.follow_range * 16.0).floor() as f32
* self.ai.nav.max_visited_multiplier) as i32;
let max_visited =
(self.ai.nav.max_visited_nodes as f32 * self.ai.nav.max_visited_multiplier) as i32;
let finder = Finder::new(w, &pm, self.ai.nav.evaluator());
let path = finder.find(targets, max_len, reach, max_visited);
if let Some(p) = &path {
+1 -1
View File
@@ -46,7 +46,7 @@ pub fn register(m: &mut Mob) {
// Villager's constructor: its brain does everything, it has no goals.
m.ai.nav.can_open_doors = true;
m.ai.nav.can_float = true;
m.ai.nav.required_path_length = 48.0;
m.set_required_path_length(48.0);
}
/// `LivingEntity.addParticlesAroundSelf`: five particles about the body.
+10
View File
@@ -275,6 +275,16 @@ def scenarios():
'mob minecraft:cod 2.5 -62 0.5 0 13 persistent noai'])
add('axolotl_play_dead', 300, [POOL, 'player 12.5 -60 0.5', 'mob minecraft:axolotl 0.5 -62 0.5 0 28 persistent']
+ [f'hurt {t} 0' for t in range(4, 160, 12)])
# A jobless villager outside a stone box, its composter inside and the doorway on the far
# side: the path around needs more than the 256 nodes of the follow range (16 * 16); the
# villager's setRequiredPathLength(48) raises PathFinder.maxVisitedNodes to 768.
add('villager_job_in_box', 300, [
'fill -4 -60 -4 4 -58 4 minecraft:stone',
'fill -3 -60 -3 3 -58 3 minecraft:air',
'fill -4 -60 0 -4 -59 0 minecraft:air',
'block 0 -60 0 minecraft:composter',
'mob minecraft:villager 10.5 -60 0.5 90 54 persistent',
])
return s