Skip to content

Keep creeper target as cause after the target dies - #2322

Open
Almost10 wants to merge 1 commit into
EngineHub:version/7.0.xfrom
Almost10:fix/creeper-target-death
Open

Almost10 wants to merge 1 commit into
EngineHub:version/7.0.xfrom
Almost10:fix/creeper-target-death

Conversation

@Almost10

Copy link
Copy Markdown

Fixes #2284

If a creeper's explosion kills its target before blocks are broken, the creeper is used as the cause instead of the player, so non-members can blow up protected blocks. The creeper's player target is now tracked so it's still used as the cause after they die.

@me4502 me4502 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! I've left a few comments as I'm not sure this is actually the best solution for the given issue.

}

@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onEntityTarget(EntityTargetEvent event) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be in WorldGuardEntityListener, EventAbstractionListener isn't the right place for this one as it's not calling out to an internal event.


if (event.getTarget() instanceof Player player) {
Cause.trackParentCause(creeper, player);
} else if (event.getReason() != EntityTargetEvent.TargetReason.TARGET_DIED) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit concerned about the potential side effects this could have. The PR is made from the assumption that a player death is directly caused by the creeper itself, and therefore likely to trigger further block explosions afterwards. In most cases though, the creeper is likely to not actually die afterwards and therefore potentially forever have a stale reference around to a player.

Would potentially solving this in ExplosionPrimeEvent rather than the entity target event be a narrower approach? It still has the potential to leak a player if the explosion never occurs, but it at least is adding it at a more causally-linked location rather than for every random target action

@Almost10 Almost10 Nov 1, 2026 •

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call, the target event was too broad. I looked into this and found why it broke: on 26.x, Creeper#getTarget() returns null once the target is dead, so the player is already gone by the time the explode event runs.

I'm thinking of doing this:

  • In ExplosionPrimeEvent: If the creeper's target is a player, track them as the parent cause.

  • In EntityRemoveEvent: Clear the stored player reference. The creeper is removed right after it explodes, and this event also covers death, despawn, and chunk unloads—ensuring the player is only stored for that single explosion. (I'd rather avoid clearing in EntityExplodeEvent, since that never fires for creepers when mobGriefing is set to false.)

  • Handler location: Both handlers would go in WorldGuardEntityListener.

Does that sound good, or would you rather avoid metadata entirely (e.g., with a weak-key map in Cause)?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Creeper bypasses WorldGuard block protection when a player dies from explosion

2 participants