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 4da0e937c18b0113d4f798233395dd7ea04d077c..fda3ac61206744d6366f0c5530815e3231581c52 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -1951,6 +1951,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 f359f63ac8cf3133b63096dad4e3142c6c4b1cbf..bed0a01be1703aad8fbfa549d5799e3f84759f32 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)) {