Paper/patches/server/0927-Properly-cancel-usable-items.patch

64 lines
4.0 KiB
Diff
Raw Normal View History

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 6c415090035fdbba6e0e3533aa2f1c3b401ab9ff..41c647c46585d454f3b10a860a2b6d979d1199a3 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 - Properly cancel usable items
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 - Properly cancel usable items; 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 - Properly cancel usable items
}
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 a6870c5f386905a4a2f4b884683aff7640649a50..ead7c202ba8ed11ee180767f3acaa003f60c2b28 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 - Properly cancel usable items
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 202819877d5920e8d0429a8c1bf06af4b9af950f..e9839d0dc8339ce62a6eb01c7094a2a3cf0fa816 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -3814,6 +3814,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 - Properly cancel usable items
+ public void resyncUsingItem(ServerPlayer serverPlayer) {
+ this.getEntityData().resendPossiblyDesyncedDataValues(java.util.List.of(DATA_LIVING_ENTITY_FLAGS), serverPlayer);
+ }
+ // Paper end - Properly cancel usable items
private void updatingUsingItem() {
if (this.isUsingItem()) {
if (ItemStack.isSameItem(this.getItemInHand(this.getUsedItemHand()), this.useItem)) {