Uploaded image for project: 'Spigot'
  1. Spigot
  2. SPIGOT-5720

Cancelling PlayerDropItemEvent With a Full Inventory Causes Item to Be Lost

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: Minor Minor
    • None
    • None
    • None
    • Mac OS, Linux

    • git-Spigot-2040c4c-94cb030 (MC: 1.15.2) (Implementing API version 1.15.2-R0.1-SNAPSHOT)
    • Yes

      Items can be lost of a player tries to drop one while their inventory is full, and the drop event is cancelled.

      Steps to reproduce:

      1. Install this test plugin: https://github.com/NathanWolf/Bukkit-Unit-Tests/releases/tag/DropCancel which will cancel the drop event for any diamond pickaxe
      2. Give yourself 1 diamond pickaxe (/give @p diamond_pickaxe) [note: you'll get two, I am going to open a separate bug for this]
      3. Give yourself 35 diamond axes (/give @p diamond_axe 35), noting that one falls on the ground
      4. You should now have a full inventory, with one axe on the ground. Stand over that axe.
      5. Open your inventory and grab a diamond pickaxe and hold it on your cursor
      6. Wait for the diamond axe to get picked up so your inventory is full again
      7. Drag the diamond pickaxe outside of your inventory and click to drop it
      8. Note that the diamond pickaxe disappears

      Expected behavior: Ideally the item would stick to the player's cursor and not let them drop it. If that's not possible then I honestly don't know what the "right" solution is. I don't like items disappearing, but I can also understand if a plugin cancels the drop event then the item should not go to the ground.

      The relevant code is here, you can see how the case where Inventory.addItem returning the dropped item back is not handled:

      // EntityHuman, ~ line 600
      if (event.isCancelled()) {
          org.bukkit.inventory.ItemStack cur = player.getInventory().getItemInHand();
          if (flag1 && (cur == null || cur.getAmount() == 0)) {
              // The complete stack was dropped
              player.getInventory().setItemInHand(drop.getItemStack());
          } else if (flag1 && cur.isSimilar(drop.getItemStack()) && cur.getAmount() < cur.getMaxStackSize() && drop.getItemStack().getAmount() == 1) {
              // Only one item is dropped
              cur.setAmount(cur.getAmount() + 1);
              player.getInventory().setItemInHand(cur);
          } else {
              // Fallback
              // ** If addItem returns the dropped item back here, it is gone forever
              player.getInventory().addItem(drop.getItemStack());
          }
          return null;
      }
      

       

            Unassigned Unassigned
            NathanWolf Nathan Wolf
            Votes:
            3 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated: