How do I remove a specific amount of items from inventory?

Discussion in 'Plugin Development' started by victor2748, Sep 18, 2014.

Thread Status:
Not open for further replies.
  1. Offline

    victor2748

    Hello, I am making a plugin, and i need to take 128 cobblestone from a player-s inventory. However, there is one issue: Inventory class only has methods to remove all items of specific material, or to remove an itemstack. the 128 blocks of cobblestone can be in any itemstacks of any size. Please help me!

    My current code:

    Code:java
    1. Player player;
    2. // ...
    3. player.getInventory().remove(new ItemStack(Material.COBBLESTONE, 128));


    Thanks.
     
  2. Offline

    blablubbabc

    Code:java
    1.  
    2. public static void removeItems(Inventory inventory, Material type, int amount) {
    3. if (amount <= 0) return;
    4. int size = inventory.getSize();
    5. for (int slot = 0; slot < size; slot++) {
    6. ItemStack is = inventory.getItem(slot);
    7. if (is == null) continue;
    8. if (type == is.getType()) {
    9. int newAmount = is.getAmount() - amount;
    10. if (newAmount > 0) {
    11. is.setAmount(newAmount);
    12. break;
    13. } else {
    14. inventory.clear(slot);
    15. amount = -newAmount;
    16. if (amount == 0) break;
    17. }
    18. }
    19. }
    20. }
    21.  
     
    BladeFireTurtle and victor2748 like this.
  3. Offline

    victor2748

    Thanks bro, u helped me!
     
  4. Offline

    mythbusterma

    blablubbabc

    All hail the spoon-feeder. How about you explain next time, instead of writing the code for them.
     
    Shortninja66 and dsouzamatt like this.
  5. Offline

    blablubbabc

    I think this code is self-explaining.
     
    victor2748 likes this.
  6. Offline

    fireblast709

  7. Offline

    blablubbabc

    Hm? I am not aware of any method in Bukkit which does exactly this..
     
    victor2748 likes this.
  8. Offline

    mythbusterma

    blablubbabc

    You could instead actually utilise the interface they provide, with methods like all() or first(). Also, I think fireblast709 is referring to removeItem(), unless I missed something?
     
  9. Offline

    victor2748

    I can understand the code fine. Code is the best explanation for me. ;)
     
  10. and that's why you couldn't write it on your own, right? because you know everything what's going on there exactly... Also you should set the thread to solved
     
  11. Offline

    mythbusterma

    Shmobi

    I wouldn't call this "solved" at all, all he did was spoonfeed some suboptimal code.
     
  12. Offline

    blablubbabc

    Could you please share then how you would improve this code? Would be helpful for me as well as I am using this code in my plugins as well and I am always on the lookout for improvements.
     
  13. Offline

    mythbusterma

    blablubbabc

    Well I suppose the inherent static-ness of the method is fine as long as you actually use it in multiple classes. I would recommend this instead:

    Code:java
    1. /**
    2.   * Removes the items of type from an inventory.
    3.   * @param inventory Inventory to modify
    4.   * @param type The type of Material to remove
    5.   * @param amount The amount to remove, or {@link Integer.MAX_VALUE} to remove all
    6.   * @return The amount of items that could not be removed, 0 for success, or -1 for failures
    7.   */
    8. public static int removeItems(Inventory inventory, Material type, int amount) {
    9.  
    10. if(type == null || inventory == null)
    11. return -1;
    12. if (amount <= 0)
    13. return -1;
    14.  
    15. if (amount == Integer.MAX_VALUE) {
    16. inventory.remove(type);
    17. return 0;
    18. }
    19.  
    20. HashMap<Integer,ItemStack> retVal = inventory.removeItem(new ItemStack(type,amount));
    21.  
    22. int notRemoved = 0;
    23. for(ItemStack item: retVal.values()) {
    24. notRemoved+=item.getAmount();
    25. }
    26. return notRemoved;
    27. }


    Alternatively, if you don't care if the items were actually removed, or the amount:
    Code:
    /**
        * Removes the items of type from an inventory.
        * @param inventory Inventory to modify
        * @param type The type of Material to remove
        * @param amount The amount to remove, or {@link Integer.MAX_VALUE} to remove all
        * @return 0 for success, otherwise -1
        */
        public static int removeItems(Inventory inventory, Material type, int amount) {
           
            if(type == null || inventory == null)
                return -1;       
            if (amount <= 0)
                return -1;
           
            if (amount == Integer.MAX_VALUE) {
                inventory.remove(type);
                return 0;
            }
           
            inventory.removeItem(new ItemStack(type,amount));
            return 0;
        }
     
  14. Offline

    blablubbabc

    mythbusterma

    Alright, I wasn't aware that the 'HashMap<Integer, ItemStack> removeItem(ItemStack... items)' method actually continued searching until the full amount was removed (I was only aware of the 'void remove(ItemStack item)' method, which only removes exactly matching item stacks).
    Note however that this method creates a new HashMap and a new ItemStack every time it's called (obviously), and continues to search for the remaining amount of to-removing items from the beginning of the whole inventory after each found item stack, resulting in slightly worse performance, especially if you have to remove multiple item stacks.

    I respect your solution, however I will probably keep using my version for the time being. Though I like the addition with the Integer.MAX_VALUE and the returning of the remaining amount. :)
     
  15. Offline

    mythbusterma

    blablubbabc

    I would assume the Bukkit implementation is faster, so I would say it's actually faster, but I could test it if you really think your solution is better.
     
  16. Offline

    victor2748

    Look n00b, I don't think u know alot about coding, thats why you thought that I was asking "for someone to write the code for me because I don't know". In this thread, I was trying to find a method in the Bukkit API that does the job, NOT FOR SOMEONE ELSE to write it for me. But if they did, oh well, they saved 5 minutes of my lifetime, and I appreciate that. Actually, an answer "Bukkit does not have that feature" would be enough for me. I hope I made it pretty clear for you. ;)
     
  17. Look noob, I'm working as a javadeveloper. And what you did ask for is some code to insert between your given code. you've never been asking if there is a method in the bukkit api, you said ItemStack does not have one for this and you also said "the 128 blocks of cobblestone can be in any itemstacks of any size. Please help me!" which says that you just want a method which does that for you, how doesn't matter. That's why i thought you are asking for someone to write the code for your because you don't know. ;)
     
Thread Status:
Not open for further replies.

Share This Page