Send a silverfish back into the stone it came from

Silverfish.getWalkTargetValue gives a position standing on an infested host block a value
of 10, so a silverfish wanders back toward stone rather than away from it. Horizon had no
silverfish case, so stone scored the same as any other floor and the goal was missing.
This commit is contained in:
MSedgeMC committed 2026-11-01 20:11:35 +00:00
1 parent 7221836b35
commit 0d3eb998ae
2 files changed
+71

No files matched your search

+56
View File
@@ -2187,6 +2187,13 @@ pub fn walk_target_value(m: &Mob, w: &MobWorld, p: [i32; 3]) -> f32 {
) {
return 0.0;
}
// Silverfish.getWalkTargetValue: a block sitting on an infested host is
// the best place to walk to, so it goes back into the stone.
if m.species() == Species::Silverfish
&& super::hostile::is_infested_host(w.block_name(p[0], p[1] - 1, p[2]))
{
return 10.0;
}
if m.hostile()
&& !matches!(
m.species(),
@@ -3537,3 +3544,52 @@ mod burn_and_rose_tests {
});
}
}
#[cfg(test)]
mod silverfish_walk_target_tests {
use super::*;
use crate::mobs::world::with_built_test_world;
/// `Silverfish.getWalkTargetValue`: a block standing on an infested host
/// (a stone-family block) is worth 10, and everywhere else falls through
/// to the monster's light value. Horizon treated stone like any other
/// block, so a silverfish had no reason to walk back into the wall.
#[test]
fn a_silverfish_prefers_a_block_on_an_infested_host() {
let build = |world: &mut crate::world::World,
registry: &horizon_world::registry::BlockRegistry| {
let stone = registry.default_state("minecraft:stone").unwrap();
let dirt = registry.default_state("minecraft:dirt").unwrap();
for cx in -1..1 {
for cz in -1..1 {
world.chunks.insert(
(cx, cz),
std::sync::Arc::new(crate::chunk::Chunk::empty(cx, cz)),
);
}
}
for x in -4..4 {
for z in -4..4 {
world.set(x, 64, z, stone).unwrap();
}
}
world.set(2, 64, 0, dirt).unwrap();
};
let ran = with_built_test_world(&[], build, |w, types| {
let m = Mob::new(
1,
std::sync::Arc::new(types.types["minecraft:silverfish"].clone()),
Vec3::new(0.5, 65.0, 0.5),
0.0,
);
assert_eq!(
walk_target_value(&m, w, [0, 65, 0]),
10.0,
"standing on stone"
);
let dirt = walk_target_value(&m, w, [2, 65, 0]);
assert!(dirt < 10.0, "standing on dirt falls through, got {dirt}");
});
let _ = ran;
}
}
+15
View File
@@ -80,6 +80,21 @@ pub fn register(m: &mut Mob) {
_ => {}
}
}
/// `InfestedBlock.isCompatibleHostBlock`: the blocks an infested block can
/// be hidden in, i.e. the host side of vanilla's host-to-infested map. A
/// silverfish prefers these as a walking target.
pub fn is_infested_host(name: &str) -> bool {
matches!(
name,
"minecraft:stone"
| "minecraft:cobblestone"
| "minecraft:stone_bricks"
| "minecraft:mossy_stone_bricks"
| "minecraft:cracked_stone_bricks"
| "minecraft:chiseled_stone_bricks"
| "minecraft:deepslate"
)
}
/// `Silverfish.hurtServer`: a hit by an entity (or magic damage) starts the
/// countdown of its wake-up goal, kept in `extra.counter`.
pub fn silverfish_hurt(m: &mut Mob, source: &Damage) {