EntityExplodeEvent / BlockExplodeEvent is handled inappropriately
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 12.7k
- Forks
- 3.5k
- Avg merge
- 3d 13h
- Merged PRs (30d)
- 11
Description
Explanation
When I was working on my Paper fork, I noticed that the logic for handling Bukkit's EntityExplodeEvent / BlockExplodeEvent has flaws.
This is the current code of the relevant part in net.minecraft.world.level.ServerExplosion:
public void explode() {
/* ... some code ... */
this.level.gameEvent(this.source, GameEvent.EXPLODE, this.center);
List<BlockPos> list = this.calculateExplodedPositions();
this.hurtEntities(); // problem 1: entities are hurt before the explosion event triggers
if (this.interactsWithBlocks()) { // problem 2: explosion events don't fire for explosions that don't modify blocks (Explosion.BlockInteraction.KEEP)
ProfilerFiller profilerFiller = Profiler.get();
profilerFiller.push("explosion_blocks");
this.interactWithBlocks(list); // explosion events are triggered inside this method
profilerFiller.pop();
}
if (this.fire) { // problem 3: explosions can create fire even if they are cancelled
this.createFire(list);
}
// Paper start - collision optimisations
this.blockCache = null;
/* ... the code continues ... */
}
In this code, Bukkit's explosion events are triggered inside the interactWithBlocks method, just before the server starts destroying blocks. However, there are multiple problems with the current implementation:
hurtEntitiesis called before explosion events are handled, so cancelling an explosion would remove particles and sounds but still hurts entities- Since there is a
interactsWithBlockscheck before the part that handles explosion events, the events will not trigger if the explosion is set to not interact with blocks createFireis called regardless of whether the explosion was cancelled.
In my own Paper fork, I improved the logic slightly by moving the part that fires explosion events before the hurtEntities call, and wrapping the block interaction and fire spawning logic inside a wasCanceled check. This is my patch for the ServerExplosion class: ServerExplosion.java.patch
However, my fix is most likely breaking for some existing plugins as it will change the behavior of the explosion events. A better solution by Paper team may be required. (Such as adding a new event and deprecating the current one)
Paper version
Paper Commit Ref: b1b88cd31687c5b3f80c4b0b51fd93a63b3e2498
Version: 1.21.4-R0.1-SNAPSHOT
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the explosion flow in net.minecraft.world.level.ServerExplosion and compare it with the attached ServerExplosion.java.patch. Trace where EntityExplodeEvent and BlockExplodeEvent are fired relative to entity damage, block interaction, and fire creation. Done means the team has an agreed-compatible behavior for cancellation and non-block-interacting explosions, with the three reported flaws addressed.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- backend, game-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100