The bug
If a zombie is provoked by a second zombie using commands, the second zombie will join in the fight against itself, causing it to attack itself repeatedly.
Originally reported by @unknown. See also this discussion on Reddit.
Affected mobs
Bees, blazes, endermites, husks, pandas, ravagers, silverfish, witches, wolves, zombies, zombie villagers, zombified piglins.
How to reproduce
Summon two zombies that cannot move, with unbreakable helmets for sun protection:
/summon minecraft:zombie ~-2 ~ ~ {Tags:["z1"],CustomName:"z1",CustomNameVisible:1b,ArmorItems:[{},{},{},{id:"minecraft:leather_helmet",components:{"minecraft:unbreakable":{}}}],attributes:[{id:"minecraft:generic.movement_speed",base:0d}]}
/summon minecraft:zombie ~2 ~ ~ {Tags:["z2"],CustomName:"z2",CustomNameVisible:1b,ArmorItems:[{},{},{},{id:"minecraft:leather_helmet",components:{"minecraft:unbreakable":{}}}],attributes:[{id:"minecraft:generic.movement_speed",base:0d}]}
Have the first zombie provoke the second zombie:
/damage @n[type=zombie,tag=z2] 0 minecraft:mob_attack by @n[type=zombie,tag=z1]
→ ❌ The first zombie begins to attack itself
Code analysis
Code analysis can be found in this comment.
Linked issues
is duplicated by 7
relates to 2
Attachments
Comments 11
Confirmed in 1.16.1 and 20w29a. Steps to reproduce:
Summon two zombies that cannot move:
/summon zombie ~ ~ ~ {UUID:[I;0,0,0,1],Attributes:[{Name:generic.movement_speed,Base:0}]} /summon zombie ~5 ~ ~ {UUID:[I;0,0,0,2],Attributes:[{Name:generic.movement_speed,Base:0}]}
Summon a snowball, belonging to the first zombie, above the second zombie:
/execute at @e[nbt={UUID:[I;0,0,0,2]}] run summon snowball ~ ~3 ~ {Motion:[0.0,-0.5],Owner:[I;0,0,0,1]}
→ ❌ The first zombie begins to attack itself
This occurs because after the second zombie becomes hostile towards the first zombie, the first zombie "joins in the fight" against itself.
This also affects blazes (MC-227157).
If you hit a zombie with a snowball, the second mob hitting itself doesn't have to be a zombie either. I found that hitting a zombie with a snowball shot from a zombie villager, husk, or drowned yields the same results.
This is based on an observation by @unknown on this comment.
Code analysis (Mojang mappings, 21w11a): The issue seems to stem from implementations of HurtByTargetGoal#alertOther(Mob, LivingEntity)
. These mobs are programmed to alert other mobs of the same type when hurt (either with a custom hurt goal that extends HurtByTargetGoal
, like aggressive pandas and bees, or by adding a HurtByTargetGoal(this, new Class[0]).setAlertOthers(class))
to its target selector). When this happens, the mob sets its attack target to the first mob's target, ignoring the fact that it might be itself.
net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal
{
...
protected void alertOthers() {
double $$0 = this.getFollowDistance();
AABB $$1 = AABB.unitCubeFromLowerCorner(this.mob.position()).inflate($$0, 10.0, $$0);
List<Entity> $$2 = this.mob.level.getEntitiesOfClass(this.mob.getClass(), $$1, EntitySelector.NO_SPECTATORS);
for (Mob ayr2 : $$2) {
if (this.mob == ayr2 || ayr2.getTarget() != null || this.mob instanceof TamableAnimal && ((TamableAnimal)this.mob).getOwner() != ((TamableAnimal)ayr2).getOwner() || ayr2.isAlliedTo(this.mob.getLastHurtByMob())) continue;
if (this.toIgnoreAlert != null) {
boolean $$4 = false;
for (Class<?> $$5 : this.toIgnoreAlert) {
if (ayr2.getClass() != $$5) continue;
$$4 = true;
break;
}
if ($$4) continue;
}
this.alertOther(ayr2, this.mob.getLastHurtByMob());
}
}
protected void alertOther(Mob $$0, LivingEntity $$1) {
$$0.setTarget($$1);
}
}
There needs to be a check in alertOther(...)
to verify if the mob is not setting the target to itself.
Obviously there's ten billion other issues at hand, and this is probably low on the priority list, but what is the likelyhood of this getting fixed relatively soon?
Less than 10%? I just miss my mob arena 😞