mojira.dev
MC-198469

Ender Dragon destroys shulker boxes without dropping them

The bug

If an Ender Dragon flies through a shulker box, the shulker box will be destroyed without dropping anything, leading to the loss of items inside. This is inconsistent as shulker boxes always drop from explosions (though the item may be destroyed by subsequent explosions), and breaking a shulker box with items in Creative mode drops it. In addition, chests destroyed by the Ender Dragon still drop their contents.

To reproduce

  • Ensure that gamerules doTileDrops and mobGriefing are enabled

  • Summon an Ender Dragon, or visit the End and spawn it

  • Place shulker boxes with items inside

  • Teleport the dragon to yourself with /tp @e[type=minecraft:ender_dragon] @s

Linked issues

Comments

migrated

Can confirm, lost a shulker box due to this.

migrated

ender dragons always destroy block tagged w/o #minecraft:dragon_immune, shulker boxes are not #minecraft:dragon_immune and the ender dragon will always destroy and not drop the block that it destroyed

Avoma

I can confirm for 20w46a.

muzikbike

Relates to MC-165218

Avoma

Can confirm in 20w51a.

Avoma

Can confirm in 21w03a.

Avoma

Can confirm in 21w05a.

Avoma

Can confirm in 21w06a.

Avoma

Can confirm in 21w07a.

Avoma

I can confirm this behavior in 1.18.1 and 22w06a. This ticket is indeed very similar to MC-220519 and I believe this problem stems from the same piece of code. Here's a code analysis regarding this issue.

Code Analysis:

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

net.minecraft.world.entity.boss.enderdragon.EnderDragon.java

public class EnderDragon extends Mob implements Enemy {
   ...
   private boolean checkWalls(AABB $aabb) {
      int i = Mth.floor($aabb.minX);
      int j = Mth.floor($aabb.minY);
      int k = Mth.floor($aabb.minZ);
      int l = Mth.floor($aabb.maxX);
      int i1 = Mth.floor($aabb.maxY);
      int j1 = Mth.floor($aabb.maxZ);
      boolean flag = false;
      boolean flag1 = false;

      for(int k1 = i; k1 <= l; ++k1) {
         for(int l1 = j; l1 <= i1; ++l1) {
            for(int i2 = k; i2 <= j1; ++i2) {
               BlockPos blockpos = new BlockPos(k1, l1, i2);
               BlockState blockstate = this.level.getBlockState(blockpos);
               if (!blockstate.isAir() && blockstate.getMaterial() != Material.FIRE) {
                  if (this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && !blockstate.is(BlockTags.DRAGON_IMMUNE)) {
                     flag1 = this.level.removeBlock(blockpos, false) || flag1;
                  } else {
                     flag = true;
                  }
               }
            }
         }
      }
      ...

If we look at the above class, we can see that the removeBlock() method is called and is responsible for removing blocks that can be destroyed by the ender dragon, if this boss were to get close to them. This is evident through the following line of code:

flag1 = this.level.removeBlock(blockpos, false) || flag1;

The problem here is that the removeBlock() method is simply designed to remove the desired block and not drop it, nor the contents within it. In other words, because the block is removed and not destroyed, no block drops are created.

Sonicwave

(Unassigned)

Confirmed

Mob behaviour

1.16.2, 1.16.4, 20w46a, 20w51a, 21w03a, ..., 1.18 Pre-release 5, 1.18.1, 22w06a, 1.19.4, 23w14a

Retrieved