mojira.dev
MC-114105

Cleaning leather armor and shulker boxes in Creative lowers cauldron water level and modifies item

The bug

Cleaning leather armor and shulker boxes using a cauldron in Creative behaves like it does in Survival: The water level of the cauldron is lowered and the item is replaced.

Expected behavior

The expected behavior is that it acts like banners: Right clicking a cauldron only gives the player a new cleaned item (see MC-114104), and everything else remains unchanged.

How to reproduce

  1. Change your gamemode to Creative

    /gamemode creative
  2. Place a cauldron with water

    /setblock ~1 ~ ~ water_cauldron[level=3]
  3. Right click the cauldron with dyed leather armor

    /give @p leather_chestplate{display:{color:0}}

    → ❌ The color was removed from the leather armor and the water level of the cauldron was lowered

Linked issues

Attachments

Comments

JUE13

Confirmed for 1.12-pre2

bemoty

Can confirm for MC 1.12.1.

qwerty23495

Can confirm in 1.13-pre3.

anthony cicinelli

Can confirm for MC 1.15.1-pre1

bluecrab2

Can confirm in 20w48a (1.17 snapshot)

Avoma

Can confirm in 21w05a. Update the second reproduction step to the following command, as the current one no longer works.

/setblock ~1 ~ ~ water_cauldron[level=3]
Avoma

Can confirm in 21w06a.

Avoma

Can confirm in 21w11a.

Avoma

Can confirm in 21w13a.

Avoma

Can confirm in 21w17a.

Avoma

Can confirm in 1.17.

Avoma

Can confirm in 1.17.1.

Avoma

Can confirm in 1.18.2.

pulpetti

In 1.19 Pre-1.

Avoma

Can confirm in 1.19.

Avoma

Can confirm in 1.19.2.

Avoma

Here's a code analysis regarding this issue.

Code Analysis:

The following is based on a decompiled version of Minecraft 1.19.2 using Mojang mappings.

net.minecraft.core.cauldron.CauldronInteraction.java

public interface CauldronInteraction {
   ...
   public static final CauldronInteraction SHULKER_BOX = (blockState, level, blockPos, player, interactionHand, itemStack) -> {
      Block block = Block.byItem(itemStack.getItem());
      if (!(block instanceof ShulkerBoxBlock)) {
         return InteractionResult.PASS;
      }
      if (!level.isClientSide) {
         ItemStack itemStack2 = new ItemStack(Blocks.SHULKER_BOX);
         if (itemStack.hasTag()) {
            itemStack2.setTag(itemStack.getTag().copy());
         }
         player.setItemInHand(interactionHand, itemStack2);
         player.awardStat(Stats.CLEAN_SHULKER_BOX);
         LayeredCauldronBlock.lowerFillLevel(blockState, level, blockPos);
      }
      return InteractionResult.sidedSuccess(level.isClientSide);
   };
   ...
   public static final CauldronInteraction DYED_ITEM = (blockState, level, blockPos, player, interactionHand, itemStack) -> {
      Item item = itemStack.getItem();
      if (!(item instanceof DyeableLeatherItem)) {
         return InteractionResult.PASS;
      }
      DyeableLeatherItem dyeableLeatherItem = (DyeableLeatherItem)((Object)item);
      if (!dyeableLeatherItem.hasCustomColor(itemStack)) {
         return InteractionResult.PASS;
      }
      if (!level.isClientSide) {
         dyeableLeatherItem.clearColor(itemStack);
         player.awardStat(Stats.CLEAN_ARMOR);
         LayeredCauldronBlock.lowerFillLevel(blockState, level, blockPos);
      }
      return InteractionResult.sidedSuccess(level.isClientSide);
   };
   ...

If we look at the above class, we can see that no checks are carried out to see what gamemode the player is in before modifying the water level of the cauldron along with the dyed item/shulker box that the player is holding. Because of this, when players in creative mode clean dyed items (leather armor) and/or shulker boxes, the water level of the cauldron decreases, and the item that they're cleaning is replaced with the cleaned variant. This shouldn't be the case. Instead, the water level of the cauldron should remain unchanged, and the player should be given a new, cleaned piece of leather armor or shulker box.

Potential Fix:

Adding some "if" statements (such as the one provided below) where appropriate within these pieces of code, to check what abilities the player possesses before allowing the cauldron and the player's held item to be modified, should resolve this problem.

if (!player.getAbilities().instabuild)
RicTheCoder

Still happening in 1.21.4, however while Leather items get replaced by the cleaned version, shulker boxes seem to be giving you the result as an extra item instead of replacing.

Most likely because the way the code works, it gives you a shulker_box item instead of changing the component/nbt, while the leather items only replace the those values on the same item.

marcono1234

(Unassigned)

Confirmed

Block states, Items

cauldron, dye, dyed-armor, leather, leather-armor, shulker_box, water

Minecraft 1.11.2, Minecraft 17w06a, Minecraft 1.12 Pre-Release 2, Minecraft 1.12.1, Minecraft 1.12.2, ..., 1.19, 1.19.2, 1.19.3, 1.20.6, 1.21.4

Retrieved