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
Spawn a creeper or a charged creeper
Go into survival mode (creative mode works too but it won't lower flint and steel's durability)
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
is duplicated by 2
Attachments
Comments 17
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]Related to MC-105591
Relates to... a whole bunch of other hand animation-related issues