mojira.dev
MC-279308

Untamable mobs keep attacking grown-up turtles

Steps to Reproduce:

  1. Summon a baby turtle via command: /summon minecraft:turtle ~ ~ ~ {Age:-600}

  2. Give turtle resistance V effect to avoid its death via command: /effect give @n[type=minecraft:turtle] minecraft:resistance infinite 4

  3. Summon an ocelot via command: /summon ocelot

  4. Keep feeding the turtle with seagrass to accelerate its growth until it grows up.

  5. Replace ocelot with other (un)tamable mobs to compare the difference, such as wolf, cat, skeleton, etc.

Observed Results: Untamable mobs, such as ocelot and skeleton, keep attacking the turtle, while tamable mobs, such as wolf and cat, stop attacking the turtle.

Expected Results: All mobs should stop attacking the turtle.

Additional information: Although mobs behave differently in Bedrock Edition as well, it doesn't depend on whether its tamable. I'll try to figure it out and create a new ticket in MCPE.

Comments 2

Code analysis:

Mob attacking turtle behavior uses NearestAttackableTargetGoal and its subclasses. The behavior can only keep active when the method canContinueToUse returns true.

For untamable mobs, they use NearestAttackableTargetGoal. They use following method:

// TargetGoal::canContinueToUse
@Override
public boolean canContinueToUse() {
    LivingEntity livingEntity = this.mob.getTarget();
    if (livingEntity == null) {
        livingEntity = this.targetMob;
    }
    if (livingEntity == null) {
        return false;
    }
    if (!this.mob.canAttack(livingEntity)) {
        return false;
    }
    PlayerTeam playerTeam = this.mob.getTeam();
    PlayerTeam playerTeam2 = livingEntity.getTeam();
    if (playerTeam != null && playerTeam2 == playerTeam) {
        return false;
    }
    double d = this.getFollowDistance();
    if (this.mob.distanceToSqr(livingEntity) > d * d) {
        return false;
    }
    if (this.mustSee) {
        if (this.mob.getSensing().hasLineOfSight(livingEntity)) {
            this.unseenTicks = 0;
        } else if (++this.unseenTicks > TargetGoal.reducedTickDelay(this.unseenMemoryTicks)) {
            return false;
        }
    }
    this.mob.setTarget(livingEntity);
    return true;
}

Untamable mobs don't check the target condition in canContinueToUse, so they can't stop attacking immediately when the turtle grows up.

For tamable animals, they use NonTameRandomTargetGoal. They use following method:

// NonTameRandomTargetGoal::canContinueToUse
@Override
public boolean canContinueToUse() {
    if (this.targetConditions != null) {
        return this.targetConditions.test(NonTameRandomTargetGoal.getServerLevel(this.mob), this.mob, this.target);
    }
    return super.canContinueToUse(); // TargetGoal::canContinueToUse
}

Tamable mobs check the target condition in canContinueToUse, so they can stop attacking immediately when the turtle grows up.

Fix:

Override canContinueToUse in NearestAttackableTargetGoal

@Override
public boolean canContinueToUse() {
    if (this.targetConditions != null) {
        return this.targetConditions.test(getServerLevel(this.mob), this.mob, this.target);
    }
    return super.canContinueToUse();
}

 

Remove canContinueToUse in NonTameRandomTargetGoal

Wilf233

(Unassigned)

Community Consensus

Gameplay

Low

Mob behaviour

mob-behavior, turtle

1.21.4, 25w02a, 25w03a, 25w05a

Retrieved