71 lines
4.0 KiB
Diff
71 lines
4.0 KiB
Diff
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||
|
From: Alphaesia <creepashadowz@gmail.com>
|
||
|
Date: Fri, 23 Apr 2021 09:57:56 +1200
|
||
|
Subject: [PATCH] Fix duplicating /give items on item drop cancel
|
||
|
|
||
|
Fixes SPIGOT-2942 (Give command fires PlayerDropItemEvent, cancelling it causes item duplication).
|
||
|
|
||
|
For every stack of items to give, /give puts the item stack straight
|
||
|
into the player's inventory. However, it also summons a "fake item"
|
||
|
at the player's location. When the PlayerDropItemEvent for this fake
|
||
|
item is cancelled, the server attempts to put the item back into the
|
||
|
player's inventory. The result is that the fake item, which is never
|
||
|
meant to be obtained, is combined with the real items injected directly
|
||
|
into the player's inventory. This means more items than the amount
|
||
|
specified in /give are given to the player - one for every stack of
|
||
|
items given. (e.g. /give @s dirt 1 gives you 2 dirt).
|
||
|
|
||
|
While this isn't a big issue for general building usage, it can affect
|
||
|
e.g. adventure maps where the number of items the player receives is
|
||
|
important (and you want to restrict the player from throwing items).
|
||
|
|
||
|
If there are any overflow items that didn't make it into the inventory
|
||
|
(insufficient space), those items are dropped as a real item instead
|
||
|
of a fake one. While cancelling this drop would also result in the
|
||
|
server attempting to put those items into the inventory, since it is
|
||
|
full this has no effect.
|
||
|
|
||
|
Just ignoring cancellation of the PlayerDropItemEvent seems like the
|
||
|
cleanest and least intrusive way to fix it.
|
||
|
|
||
|
diff --git a/src/main/java/net/minecraft/server/commands/GiveCommand.java b/src/main/java/net/minecraft/server/commands/GiveCommand.java
|
||
|
index 58941830a4bd024fcdb97df47783c82062e9167f..a0dc380e90415de9068ea408d62a1605c82631df 100644
|
||
|
--- a/src/main/java/net/minecraft/server/commands/GiveCommand.java
|
||
|
+++ b/src/main/java/net/minecraft/server/commands/GiveCommand.java
|
||
|
@@ -47,7 +47,7 @@ public class GiveCommand {
|
||
|
boolean bl = serverPlayer.getInventory().add(itemStack);
|
||
|
if (bl && itemStack.isEmpty()) {
|
||
|
itemStack.setCount(1);
|
||
|
- ItemEntity itemEntity2 = serverPlayer.drop(itemStack, false);
|
||
|
+ ItemEntity itemEntity2 = serverPlayer.drop(itemStack, false, false, true); // Paper - Fix duplicating /give items on item drop cancel
|
||
|
if (itemEntity2 != null) {
|
||
|
itemEntity2.makeFakeItem();
|
||
|
}
|
||
|
diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java
|
||
|
index b916f629c2a0fb018cba19aaa612cbbcbb597dc1..c0b18656637cdc1ee6938c70aa281a71551e75dd 100644
|
||
|
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
|
||
|
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
|
||
|
@@ -689,6 +689,13 @@ public abstract class Player extends LivingEntity {
|
||
|
|
||
|
@Nullable
|
||
|
public ItemEntity drop(ItemStack stack, boolean throwRandomly, boolean retainOwnership) {
|
||
|
+ // Paper start - Fix duplicating /give items on item drop cancel
|
||
|
+ return this.drop(stack, throwRandomly, retainOwnership, false);
|
||
|
+ }
|
||
|
+
|
||
|
+ @Nullable
|
||
|
+ public ItemEntity drop(ItemStack stack, boolean throwRandomly, boolean retainOwnership, boolean alwaysSucceed) {
|
||
|
+ // Paper end
|
||
|
if (stack.isEmpty()) {
|
||
|
return null;
|
||
|
} else {
|
||
|
@@ -730,7 +737,7 @@ public abstract class Player extends LivingEntity {
|
||
|
PlayerDropItemEvent event = new PlayerDropItemEvent(player, drop);
|
||
|
this.level.getCraftServer().getPluginManager().callEvent(event);
|
||
|
|
||
|
- if (event.isCancelled()) {
|
||
|
+ if (event.isCancelled() && !alwaysSucceed) { // Paper - Fix duplicating /give items on item drop cancel
|
||
|
org.bukkit.inventory.ItemStack cur = player.getInventory().getItemInHand();
|
||
|
if (retainOwnership && (cur == null || cur.getAmount() == 0)) {
|
||
|
// The complete stack was dropped
|