-
Type:
Bug
-
Resolution: Fixed
-
Priority:
Minor
-
None
-
Affects Version/s: None
-
None
-
Environment:
Tested in paper, bug is confirmed to exist in spigot
-
Paper 1.21.11-127-main@bd74bf6 (2026-03-10T02:55:23Z)
-
PGM
-
Yes
Formerly, you could deny the two parts of PlayerInteractEvent seprately and they'd work as intended, take this plugin code as example:
@EventHandler public void onPlayerInteract(PlayerInteractEvent pie) { if (pie.getAction() != Action.RIGHT_CLICK_BLOCK) return; pie.setCancelled(false); pie.setUseItemInHand(Event.Result.ALLOW); pie.setUseInteractedBlock(Event.Result.DENY); }
This would make it so if you right click with blocks in your hand, it would never interact with the clicked block (eg: no opening chests, no flipping trapdoors) but would always allow the block place itself. This behavior changed in 1.20.5 where now this same code, will result in no interaction with the block but also no block being placed.
The root cause code responsible for this behavior change was introduced in spigot/craftbukkit 1.20.5
https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/commits/735b2d0d7f10bc3b3a816e103cc86af8cb1ec645#nms-patches%2Fnet%2Fminecraft%2Fserver%2Flevel%2FPlayerInteractManager.patch?t=316
Notice that prior to this diff, the code would enuminteractionresult = ... (and set the interaction result to PASS) but let the execution continue and the code below, as long as the previous interaction wasn't SUCCESS, would do the block placing. Since it now directly returns the PASS result, it will never attempt to place the block.
Testing for this has been conducted in 1.8 and (paper) 1.21.11 where the former works fine and the later has the described bug, but i have researched the root cause and found it to be in spigot's 1.20.5 update, and that latest version of this code in spigot still has this bug too:
Original patch that introduced this issue: https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/commits/735b2d0d7f10bc3b3a816e103cc86af8cb1ec645#nms-patches%2Fnet%2Fminecraft%2Fserver%2Flevel%2FPlayerInteractManager.patch?t=316
Latest version of the code still having the same issue: https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/browse/nms-patches/net/minecraft/server/level/ServerPlayerGameMode.patch#343
A minimal patch that seems to fix this is the following (ontop of latest paper):
diff --git a/net/minecraft/server/level/ServerPlayerGameMode.java b/net/minecraft/server/level/ServerPlayerGameMode.java index 84d19d79e77cec6a5d64f59fbcce703e467b2407..87bb20f74716342e504c0cecfab616dc367818b3 100755 --- a/net/minecraft/server/level/ServerPlayerGameMode.java +++ b/net/minecraft/server/level/ServerPlayerGameMode.java @@ -526,7 +526,7 @@ public class ServerPlayerGameMode { } // Paper end - Fix inventory desync this.player.resyncUsingItem(this.player); // Properly cancel usable items - return (event.useItemInHand() != org.bukkit.event.Event.Result.ALLOW) ? InteractionResult.SUCCESS : InteractionResult.PASS; + if (event.useItemInHand() != org.bukkit.event.Event.Result.ALLOW) return InteractionResult.SUCCESS; // handle useInteractedBlock and useItemInHand separately } else if (this.gameModeForPlayer == GameType.SPECTATOR) { MenuProvider menuProvider = blockState.getMenuProvider(level, blockPos); if (menuProvider != null && player.openMenu(menuProvider).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation @@ -553,9 +553,10 @@ public class ServerPlayerGameMode { } } } - + } { // handle useInteractedBlock and useItemInHand separately if (!stack.isEmpty() && !this.interactResult) { // add !interactResult SPIGOT-764 UseOnContext useOnContext = new UseOnContext(player, hand, hitResult); + ItemStack itemStack = stack.copy(); // handle useInteractedBlock and useItemInHand separately InteractionResult interactionResult1; if (player.hasInfiniteMaterials()) { int count = stack.getCount();
Do note: this patch results in unneeded itemstack resyncs on the client so the place is a bit weird (although that may be a paper-only thing), but the behavior serverside works as intended.