From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> Date: Tue, 23 May 2023 22:33:36 -0400 Subject: [PATCH] Properly Cancel Usable Items This fixes the bug causing cancelling PlayerInteractEvent to cause items to continue to be used despite being cancelled on the server. For example, items being consumed but never finishing, shields being put up, etc. The underlying issue of this is that the client modifies their synced data values, and so we have to (forcibly) resend them in order for the client to reset their using item state. diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java index f58386e952d29a16d160b628a23efbe102791277..82f26186156a487f29ad3abff3f68852e5b8a1f9 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java @@ -557,6 +557,7 @@ public class ServerPlayerGameMode { } // Paper end - extend Player Interact cancellation player.getBukkitEntity().updateInventory(); // SPIGOT-2867 + this.player.resyncUsingItem(this.player); // Paper - Resend player's using item status enuminteractionresult = (event.useItemInHand() != Event.Result.ALLOW) ? InteractionResult.SUCCESS : InteractionResult.PASS; } else if (this.gameModeForPlayer == GameType.SPECTATOR) { MenuProvider itileinventory = iblockdata.getMenuProvider(world, blockposition); @@ -600,6 +601,11 @@ public class ServerPlayerGameMode { return enuminteractionresult1; } + // Paper start - Cancel only if cancelled + if the interact result is different from default response + else if (this.interactResult && this.interactResult != cancelledItem) { + this.player.resyncUsingItem(this.player); + } + // Paper end } return enuminteractionresult; // CraftBukkit end diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java index 361d31a4a527c32ff3b8cd2e763e23963ec0a2b4..ab2fcbdd9567e18a59eb70b3557da7a3f4a91f38 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -1955,6 +1955,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl } if (cancelled) { + this.player.resyncUsingItem(this.player); // Paper - Resend player's using item status this.player.getBukkitEntity().updateInventory(); // SPIGOT-2524 return; } diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java index 070d9630af6d8c29de9df3b59ce14c57637ebf6d..3ce5c06a6c154c0b8c9f2aaaa0a2f9d092cc4551 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java @@ -3813,6 +3813,11 @@ public abstract class LivingEntity extends Entity implements Attackable { return ((Byte) this.entityData.get(LivingEntity.DATA_LIVING_ENTITY_FLAGS) & 2) > 0 ? InteractionHand.OFF_HAND : InteractionHand.MAIN_HAND; } + // Paper start + public void resyncUsingItem(ServerPlayer serverPlayer) { + this.getEntityData().resendPossiblyDesyncedDataValues(java.util.List.of(DATA_LIVING_ENTITY_FLAGS), serverPlayer); + } + // Paper end private void updatingUsingItem() { if (this.isUsingItem()) { if (ItemStack.isSameItem(this.getItemInHand(this.getUsedItemHand()), this.useItem)) {