mojira.dev
MC-186909

Flint and steel / fire charge is used/consumed when right-clicking on an ignited creeper / charged creeper

The bug

Player can keep right-clicking on a creeper (with a flint and steel) even after the first time, even though the creeper is going to blow up anyway, losing durability for each hand swing.

How to reproduce

  1. Spawn a creeper or a charged creeper

  2. Go into survival mode (creative mode works too but it won't lower flint and steel's durability)

  3. Start right-clicking on a creeper with a flint and steel
    → ❌ Player is still able to use flint and steel even after the first time while creeper blows up, making player use more durability than 1

Expected behavior would be that the player should only be able to right-click on a creeper once.

Code analysis and fix

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

Linked issues

Attachments

Comments 17

Relates to... a whole bunch of other hand animation-related issues

Confirmed on latest pre-release

Can confirm in 21w08a

Can confirm in 21w17a

7 more comments

Can confirm in 1.18.

Can confirm in 1.19.

Can confirm in 1.19.2. Here's a code analysis of this issue.

Code Analysis:

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

net.minecraft.world.entity.monster.Creeper.java

public class Creeper extends Monster implements PowerableMob {
   ...
   @Override
   protected InteractionResult mobInteract(Player player2, InteractionHand interactionHand) {
      ItemStack itemStack = player2.getItemInHand(interactionHand);
      if (itemStack.is(Items.FLINT_AND_STEEL)) {
         this.level.playSound(player2, this.getX(), this.getY(), this.getZ(), SoundEvents.FLINTANDSTEEL_USE, this.getSoundSource(), 1.0f, this.random.nextFloat() * 0.4f + 0.8f);
         if (!this.level.isClientSide) {
            this.ignite();
            itemStack.hurtAndBreak(1, player2, player -> player.broadcastBreakEvent(interactionHand));
         }
         return InteractionResult.sidedSuccess(this.level.isClientSide);
      }
      return super.mobInteract(player2, interactionHand);
   }
   ...

If we look at the above class, we can see that there are two checks that are carried out before allowing a creeper to be ignited using flint and steel. One of them is to make sure the action is carried out server-side and not client-side and the other is to check if the player is actually holding flint and steel at the time of the interaction. The game doesn't check if the creeper is already ignited before allowing it to be ignited again, therefore resulting in this problem occurring.

Fix:

Simply altering an existing "if" statement within this piece of code to check if the creeper is already ignited before allowing it to be ignited again, should resolve this problem. We can achieve this through the use of the isIgnited() boolean.

Current "if" statement:

if (!this.level.isClientSide)

Fixed "if" statement:

if (!this.level.isClientSide && !this.isIgnited())

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]

Dmitry Konev

(Unassigned)

Confirmed

Items, Player Animation

creeper, flint_and_steel, hand, hand-animation

1.15.2, 20w22a, 1.16 Pre-release 2, 1.16 Pre-release 5, 1.16 Pre-release 7, ..., 1.19.4, 23w16a, 1.20.1, 23w45a, 1.21

Retrieved