From 26364341f4706aeb3b4bcb9517a1ce0696301787 Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 2 May 2026 17:30:13 -0700 Subject: [PATCH] fix: resync magic block to client after entity-spawn cancel When a magic-block roll produces a mob, handleEntitySpawn cancels the triggering BlockBreakEvent at EventPriority.HIGHEST. The client has already played the "block disappearing" animation by then and predicted the block as gone, but never receives a corrective block-update packet, so the magic block appears transparent until the chunk resyncs (e.g. on relog). Send a block change to the mining player immediately after the cancel so the client repaints the actual server-side block state. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../bentobox/aoneblock/listeners/BlockListener.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/world/bentobox/aoneblock/listeners/BlockListener.java b/src/main/java/world/bentobox/aoneblock/listeners/BlockListener.java index c066b98..d001f39 100644 --- a/src/main/java/world/bentobox/aoneblock/listeners/BlockListener.java +++ b/src/main/java/world/bentobox/aoneblock/listeners/BlockListener.java @@ -527,12 +527,18 @@ private void processNextBlock(Cancellable e, Island i, Player player, Block bloc * @param nextBlock - next block object containing entity info */ private void handleEntitySpawn(Cancellable e, Island i, Player player, Block block, OneBlockObject nextBlock) { - if (!(e instanceof EntitySpawnEvent)) { + boolean cancelled = !(e instanceof EntitySpawnEvent); + if (cancelled) { e.setCancelled(true); } spawnEntity(nextBlock, block); + // Cancelling BlockBreakEvent at HIGHEST priority leaves the client with a + // mispredicted "block gone" state; resync the actual block to clear it. + if (cancelled && player != null) { + player.sendBlockChange(block.getLocation(), block.getBlockData()); + } Bukkit.getPluginManager().callEvent(new MagicBlockEntityEvent(i, - player == null ? null : player.getUniqueId(), + player == null ? null : player.getUniqueId(), block, nextBlock.getEntityType())); }