From 87807b2f5974ca14e6469e8dc7455602838ae8fb Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 25 Aug 2026 09:06:41 +0000 Subject: [PATCH] Fix red koopa shell homing without an owner RedKoopaShell.findTarget() searched for and locked onto a target even when the shell had no owner, contradicting the intended behaviour (a shell nobody threw has nothing to chase for) and failing KoopaShellGameTest.anownerlessRedShellGoesStraight on dev. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_018CgrnTJ5h1s22YS1BTCi8r --- .../world/entity/projectile/RedKoopaShell.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/world/entity/projectile/RedKoopaShell.java b/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/world/entity/projectile/RedKoopaShell.java index 2044d2920..be99b6333 100644 --- a/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/world/entity/projectile/RedKoopaShell.java +++ b/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/world/entity/projectile/RedKoopaShell.java @@ -6,7 +6,6 @@ import net.minecraft.resources.Identifier; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.Mth; -import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.ai.targeting.TargetingConditions; @@ -160,17 +159,19 @@ private LivingEntity findTarget() { if (!(this.level() instanceof ServerLevel serverLevel)) { return null; } - // an owner-less shell, thrown by a dispenser for instance, still homes in: it just has no one to spare - Entity owner = this.getOwner(); + // a shell nobody threw has no one to home in on behalf of, so it never looks for a target at all + if (!(this.getOwner() instanceof LivingEntity livingOwner)) { + return null; + } // the search box is a cube, so its corners reach further than the shell is willing to home in from: // filtering on the same conditions the target is later kept on avoids locking onto one of those, only // to drop it on the very next tick var candidates = serverLevel.getEntitiesOfClass(LivingEntity.class, this.getSearchBox(MAX_TARGET_DISTANCE), - candidate -> candidate != owner && this.isValidTarget(candidate)); + candidate -> candidate != livingOwner && this.isValidTarget(candidate)); return serverLevel.getNearestEntity( candidates, TARGET_PREDICATE, - owner instanceof LivingEntity livingOwner ? livingOwner : null, + livingOwner, this.getX(), this.getEyeY(), this.getZ());