Skip to content

Commit

Permalink
Fix Drop2Inventory dupe
Browse files Browse the repository at this point in the history
  • Loading branch information
erikzimmermann committed Dec 30, 2023
1 parent 5d5037f commit 3ab572c
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 62 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package de.codingair.tradesystem.spigot.trade.gui;

import de.codingair.codingapi.server.specification.Version;
import de.codingair.codingapi.utils.Value;
import de.codingair.tradesystem.spigot.utils.EntityItemUtils;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Material;
Expand Down Expand Up @@ -347,67 +350,79 @@ private static boolean handleDrop(@NotNull InventoryClickEvent event, @NotNull I
// 3. cancel or apply changes

ItemStack currentItem = topInventory ? inventory.getItem(slot) : event.getCurrentItem();
Item dropped = null;
Value<Boolean> hasBeenDropped = new Value<>(false);

// drop item
switch (event.getAction()) {
case DROP_ALL_CURSOR: {
ItemStack item = event.getCursor();
if (nullOrAir(item)) break;
Function<Item, Boolean> accessor = dropped -> {
// check if drop event is canceled
PlayerDropItemEvent dropEvent = new PlayerDropItemEvent((Player) event.getWhoClicked(), dropped);
Bukkit.getPluginManager().callEvent(dropEvent);

dropped = dropItem((Player) event.getWhoClicked(), item);
break;
// remove dropped item if canceled
if (dropEvent.isCancelled()) {
dropped.remove();
return false;
}

case DROP_ONE_CURSOR: {
ItemStack item = event.getCursor();
if (nullOrAir(item)) break;
// apply changes
switch (event.getAction()) {
case DROP_ALL_CURSOR: {
ItemStack item = event.getCursor();
if (nullOrAir(item)) break;

ItemStack copy = item.clone();
copy.setAmount(1);
event.getView().setCursor(null);
break;
}

dropped = dropItem((Player) event.getWhoClicked(), copy);
break;
}
case DROP_ONE_CURSOR: {
ItemStack item = event.getCursor();
if (nullOrAir(item)) break;

case DROP_ALL_SLOT: {
if (nullOrAir(currentItem)) break;
ItemStack copy = item.clone();
copy.setAmount(1);

dropped = dropItem((Player) event.getWhoClicked(), currentItem);
break;
}
item.setAmount(item.getAmount() - 1);
if (item.getAmount() == 0) event.getView().setCursor(null);
break;
}

case DROP_ONE_SLOT: {
if (nullOrAir(currentItem)) break;
case DROP_ALL_SLOT: {
if (nullOrAir(currentItem)) break;

ItemStack copy = currentItem.clone();
copy.setAmount(1);
if (topInventory) {
inventory.setItem(slot, null);
} else event.setCurrentItem(null);
break;
}

dropped = dropItem((Player) event.getWhoClicked(), copy);
break;
}
}
case DROP_ONE_SLOT: {
if (nullOrAir(currentItem)) break;

if (dropped == null) return false;
ItemStack copy = currentItem.clone();
copy.setAmount(1);

// check if drop event is canceled
PlayerDropItemEvent dropEvent = new PlayerDropItemEvent((Player) event.getWhoClicked(), dropped);
Bukkit.getPluginManager().callEvent(dropEvent);
currentItem.setAmount(currentItem.getAmount() - 1);
if (currentItem.getAmount() == 0) {
if (topInventory) {
inventory.setItem(slot, null);
} else event.setCurrentItem(null);
}
break;
}
}

// remove dropped item if canceled
if (dropEvent.isCancelled()) {
dropped.remove();
return false;
}
hasBeenDropped.setValue(true);
return true;
};

// apply changes
boolean changed = false;
// drop item
// DUPE FIX: check the drop event before actually spawning the item
// Context: Drop2Inventory instantly adds the dropped item to the inventory
switch (event.getAction()) {
case DROP_ALL_CURSOR: {
ItemStack item = event.getCursor();
if (nullOrAir(item)) break;

event.getView().setCursor(null);
dropItem((Player) event.getWhoClicked(), item, accessor);
break;
}

Expand All @@ -418,18 +433,14 @@ private static boolean handleDrop(@NotNull InventoryClickEvent event, @NotNull I
ItemStack copy = item.clone();
copy.setAmount(1);

item.setAmount(item.getAmount() - 1);
if (item.getAmount() == 0) event.getView().setCursor(null);
dropItem((Player) event.getWhoClicked(), copy, accessor);
break;
}

case DROP_ALL_SLOT: {
if (nullOrAir(currentItem)) break;

if (topInventory) {
inventory.setItem(slot, null);
changed = true;
} else event.setCurrentItem(null);
dropItem((Player) event.getWhoClicked(), currentItem, accessor);
break;
}

Expand All @@ -439,19 +450,17 @@ private static boolean handleDrop(@NotNull InventoryClickEvent event, @NotNull I
ItemStack copy = currentItem.clone();
copy.setAmount(1);

currentItem.setAmount(currentItem.getAmount() - 1);
if (currentItem.getAmount() == 0) {
if (topInventory) {
inventory.setItem(slot, null);
changed = true;
} else event.setCurrentItem(null);
} else changed = topInventory;
dropItem((Player) event.getWhoClicked(), copy, accessor);
break;
}

default:
return false;
}

if (changed) inventory.update(slot);
return changed;
if (!hasBeenDropped.getValue()) return false;
if (topInventory) inventory.update(slot);
return topInventory;
}

private static boolean handleCollect(@NotNull InventoryClickEvent event, @NotNull InventoryMask inventory, @NotNull Configuration configuration) {
Expand Down Expand Up @@ -673,12 +682,25 @@ private static boolean place(@NotNull ItemStack to, @NotNull ItemStack from, int
return true;
}

@NotNull
private static Item dropItem(@NotNull Player player, @NotNull ItemStack item) {
Item i = player.getWorld().dropItem(player.getEyeLocation(), item);
i.setVelocity(player.getEyeLocation().getDirection().multiply(0.3D));
i.setPickupDelay(40);
return i;
private static void dropItem(@NotNull Player player, @NotNull ItemStack item, @NotNull Function<Item, Boolean> access) {
if (Version.atLeast(17)) {
player.getWorld().dropItem(player.getEyeLocation(), item, i -> {
i.setVelocity(player.getEyeLocation().getDirection().multiply(0.3D));
i.setPickupDelay(40);

boolean spawn = access.apply(i);
if (!spawn) i.remove();
});
} else {
Item dummy = EntityItemUtils.create(player.getEyeLocation(), item);
boolean spawn = access.apply(dummy);

if (spawn) {
Item i = player.getWorld().dropItem(player.getEyeLocation(), item);
i.setVelocity(player.getEyeLocation().getDirection().multiply(0.3D));
i.setPickupDelay(40);
}
}
}

private static boolean nullOrAir(@Nullable ItemStack item) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package de.codingair.tradesystem.spigot.utils;

import de.codingair.codingapi.server.reflections.IReflection;
import de.codingair.codingapi.server.reflections.PacketUtils;
import org.bukkit.Location;
import org.bukkit.entity.Item;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;

public class EntityItemUtils {
private static final Class<?> ENTITY_ITEM_CLASS = IReflection.getClass(IReflection.ServerPacket.MINECRAFT_PACKAGE("net.minecraft.world.entity.item"), "EntityItem");
private static final IReflection.ConstructorAccessor ENTITY_ITEM = IReflection.getConstructor(ENTITY_ITEM_CLASS, PacketUtils.WorldClass, double.class, double.class, double.class, PacketUtils.ItemStackClass);

@NotNull
public static Item create(@NotNull Location location, @NotNull ItemStack item) {
assert ENTITY_ITEM != null;
Object entityItem = ENTITY_ITEM.newInstance(PacketUtils.getWorldServer(location.getWorld()), location.getX(), location.getY(), location.getZ(), PacketUtils.getItemStack(item));
return (Item) PacketUtils.getBukkitEntity(entityItem);
}

}

0 comments on commit 3ab572c

Please sign in to comment.