PaperMC / PaperMC/Paper

Fourth end crystal placement for respawning the ender dragon triggers BlockPlaceEvent due to regeneration of end portal

Open
#12,576 0 comments 0 reactions 0 assignees View on GitHub

@TehManu is already working on this.

Since Dec 30, 2025.

status: accepted version: 1.21.11 version: 1.21.4
Dominant language
Java
Stars
12.7k
Forks
3.5k
Avg merge
3d 13h
Merged PRs (30d)
11

Description

Expected behavior

After placing the fourth end crystal the ender dragon respawns and the BlockPlaceEvent is not being called because of the end portal regeneration.

Observed/Actual behavior

After placing the fourth end crystal to respawn the ender dragon while also having the following listener enabled, it gets really strange. The player gets back one end crystal because a BlockPlacEvent was triggerd due to end portal regeneration.

public class BlockPlaceListener implements Listener {

    @EventHandler
    public void onBlockPlace(BlockPlaceEvent event) {
        final Player player = event.getPlayer();

        if (player.getGameMode() != GameMode.CREATIVE && event.getBlock().getType() == Material.BEDROCK) {
            event.setCancelled(true);
        }
    }
}
Steps/models to reproduce

Register the following listener in your plugin.

public class BlockPlaceListener implements Listener {

    @EventHandler
    public void onBlockPlace(BlockPlaceEvent event) {
        final Player player = event.getPlayer();

        if (player.getGameMode() != GameMode.CREATIVE && event.getBlock().getType() == Material.BEDROCK) {
            event.setCancelled(true);
        }
    }
}

Place the four end crystals to respawn the ender dragon and look at the hotbar there should be now an end crystal.

Plugin and Datapack List

Image

Paper version

Image

Other

So i tried also digging deeper into this issue and it seems like the problem is caused due to the end crystal item useOn context calls the regeneration process of the end portal what causes blocks to be first replaced and than being placed again. I have found out, that before the useOn context of an itemstack interaction starts there is an boolean serverLevel.captureBlockStates that indicates if blocks that are getting placed should be saved for later to determine what BlockPlaceEvent should be called if there are any blocks that were placed. The problem is that while the fourth end crystal is getting placed this triggers the end portal regeneration which causes the blocks that are getting placed to be captured because the boolean is still true for this context and this should not be the case because the end crystal is an entity and should only trigger an EntityPlaceEvent.

I have come to the following solution https://github.com/TehManu/cheetah/commit/a163783c1eb9c8c4060b061a898a5cfe7537cee8 but maybe there is a better solution to fix this.

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

Reproduce the issue with the provided BlockPlaceEvent listener by placing four end crystals, then trace the ItemStack useOn context and ServerLevel.captureBlockStates during end portal regeneration. Review the linked pull request and verify that portal regeneration no longer produces an unintended BlockPlaceEvent while the end crystal placement behavior remains correct.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.