PaperMC / PaperMC/Paper

EntityExplodeEvent / BlockExplodeEvent is handled inappropriately

Open
#12,441 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

status: needs triage
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:

  1. hurtEntities is called before explosion events are handled, so cancelling an explosion would remove particles and sounds but still hurts entities
  2. Since there is a interactsWithBlocks check before the part that handles explosion events, the events will not trigger if the explosion is set to not interact with blocks
  3. createFire is 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.