Removing one occurrence of item in an inventory

Discussion in 'Spigot Plugin Development' started by yakovliam, Dec 4, 2019 at 10:50 PM.

  1. Supposed to happen: Even if the player has more than one item with the enchantment called "test", only ONE occurrence of the item is removed from the inventory.
    What happens: If the player has more than one item with the enchantment called "test", ALL occurrences are removed from the inventory.
    Code (Java):
    ItemStack enchantedItem = Arrays.stream(player.getInventory().getContents())
                    .filter(itemStack -> EnchantmentManager.getInstance().getEnchantmentLevel(itemStack, EnchantmentManager.TEST) >= 1)
                    .collect(Collectors.toList()).get(0);// filter items to find the enchanted item

    player.getInventory().remove(enchantedItem); // remove the item from their inventory
    I have tried to set the `amount` of the ItemStack to 1, but that does not make a difference.

    Any ideas?
    (EDIT: This needs to be very efficient as it is going to be used on a server with possible hundreds of players online simultaneously)
     
  2. Try using
    Code (Java):
    .findFirst().ifPresent(enchantedItem -> {
      player.getInventory().remove(enchantedItem);
    });
    (instead of collectors.toList)
     
  3. If I understand the method correctly, this will do the exact same as just executing the method once, which will remove all occurrences. Another thing: I can't use `enchantedItem` in a lamda because it has already been defined earlier in the scope. Where are you telling me to apply this to; the inventory contents...?

    EDIT: Is this what you mean?
    Code (Java):
    List<ItemStack> enchantedItems = Arrays.stream(player.getInventory().getContents())
                    .filter(itemStack -> EnchantmentManager.getInstance().getEnchantmentLevel(itemStack, EnchantmentManager.WARD) >= 1)
                    .collect(Collectors.toList());// filter items to find the enchanted item

    enchantedItems.stream().findFirst().ifPresent(item -> {
        player.getInventory().remove(item); // remove the item from their inventory
    });
     
    EDIT 2: Tested, same result as in original post.
     
    #3 yakovliam, Dec 4, 2019 at 10:57 PM
    Last edited: Dec 4, 2019 at 11:10 PM
  4. Strahan

    Benefactor

    Instead of removing the item, try getting the item and doing .setAmount(getAmount-1) perhaps?
     
  5. If you read the javadoc, you can see that it does exactly the opposite of what I say I need it to do.
    "Removes the given ItemStacks from the inventory." -> ItemStack(s), not ItemStack.
     
    • Agree Agree x 1
  6. Something like this might work, I haven't tested it though

    Code (Java):
    ItemStack[] contents = p.getInventory().getContents();

    IntStream.range(0, contents.length)
           .filter(i -> EnchantmentManager.getInstance().getEnchantmentLevel(contents[i], EnchantmentManager.TEST) >= 1)
           .findFirst()
           .ifPresent(p.getInventory()::clear);
     
  7. I'm not sure exactly under what circumstances you are trying to evade here.
    Why not just refuse any identical item(s) from being added to the inventory.
    Pseudo
    if (specialItem && specialItem.getAmount >1) {
    specialItem.setAmount = 1
    // One or more special items were confiscated by the server
    }
     
  8. It says ItemStacks because it's a varargs method where you can give a variable number of ItemStacks as arguments. If you only give one ItemStack it only removes that one ItemStack.
     
  9. Then, repeat for each ItemStack.