Fourth end crystal placement for respawning the ender dragon triggers BlockPlaceEvent due to regeneration of end portal
- 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
Paper version
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
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
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