mojira.dev
MC-255080

Parrots imitate hostile mobs in their death animation

The bug

Parrots are designed to imitate hostile mobs like zombies or skeletons, but they also seem to continue to imitate them in their death animation. This doesn't make sense as all mobs are meant to ignore other mobs in their death animation like if a zombie and skeleton fight each other and for say the skeleton dies, the zombie will immediately lose aggro on that skeleton when in its death animation. This makes an exception for parrots as they still will imitate the hostile mob in their death animation. Parrots are meant to imitate hostile mobs as a "warning" for players and if they can imitate them in their death animation, you may just kill a creeper and your nearby parrot will imitate that creeper, making you think there might be another one nearby.

To reproduce

To replicate this, spawn a few parrots then use the following command to summon a zombie in its death state and see that the parrots will go over and imitate that zombie.

/summon zombie ~ ~ ~ {Health:0b,DeathTime:-500s}

You will hear that the parrots make a zombie groan noise and if you have subtitles on, you will see Parrot Groans.

Code analysis

Code analysis by @unknown can be found in this comment.

Attachments

Comments 3

Here's a code analysis of this issue along with a fix.

Code Analysis:

The following is based on a decompiled version of Minecraft 1.19.2 using MCP-Reborn.

net.minecraft.world.entity.animal.Parrot.java

public class Parrot extends ShoulderRidingEntity implements FlyingAnimal {
   ...
   public static boolean imitateNearbyMobs(Level level, Entity entity) {
      if (entity.isAlive() && !entity.isSilent() && level.random.nextInt(2) == 0) {
         List<Mob> list = level.getEntitiesOfClass(Mob.class, entity.getBoundingBox().inflate(20.0D), NOT_PARROT_PREDICATE);
         if (!list.isEmpty()) {
            Mob mob = list.get(level.random.nextInt(list.size()));
            if (!mob.isSilent()) {
               SoundEvent soundevent = getImitatedSound(mob.getType());
               level.playSound((Player)null, entity.getX(), entity.getY(), entity.getZ(), soundevent, entity.getSoundSource(), 0.7F, getPitch(level.random));
               return true;
            }
         }

         return false;
      } else {
         return false;
      }
   }
   ...
public class Parrot extends ShoulderRidingEntity implements FlyingAnimal {
   ...
   public static boolean imitateNearbyMobs(Level level, Entity entity) {
      if (entity.isAlive() && !entity.isSilent() && level.random.nextInt(2) == 0) {
         List<Mob> list = level.getEntitiesOfClass(Mob.class, entity.getBoundingBox().inflate(20.0D), NOT_PARROT_PREDICATE);
         if (!list.isEmpty()) {
            Mob mob = list.get(level.random.nextInt(list.size()));
            if (!mob.isSilent()) {
               SoundEvent soundevent = getImitatedSound(mob.getType());
               level.playSound((Player)null, entity.getX(), entity.getY(), entity.getZ(), soundevent, entity.getSoundSource(), 0.7F, getPitch(level.random));
               return true;
            }
         }

         return false;
      } else {
         return false;
      }
   }
   ...

If we look at the above class, we can see that there is only one check that is carried out in terms of the mob that the parrot can imitate, before allowing parrots to imitate mobs. This check is to see if the mob is silent. The game doesn't check if the mob is currently alive, therefore allowing parrots to imitate the sounds of mobs that are in their death animation.

Fix:

Simply altering the appropriate existing "if" statement within this piece of code to check if the mob is alive before allowing parrots to imitate them will resolve this problem. We can achieve this through the use of the isAlive() boolean.

Current "if" statement:

if (!mob.isSilent())
if (!mob.isSilent())

Fixed "if" statement:

if (!mob.isSilent() && mob.isAlive())
if (!mob.isSilent() && mob.isAlive())

Following on from my code analysis, I've double-checked my proposed fix and I can confidently confirm that it's fully functioning and works as expected, so I've attached two screenshots to this report, one of which shows the current code and the other that shows the fixed code. I feel this information may be quite insightful hence my reasoning for providing it. 🙂

[media][media]

matthewdog6

(Unassigned)

Confirmed

Gameplay

Low

Mob behaviour, Sound

1.19.2, 22w42a, 22w43a, 22w44a, 22w45a, ..., 1.20.6, 1.21 Pre-Release 1, 1.21 Pre-Release 4, 1.21, 1.21 Release Candidate 1

Retrieved