• Hello Guest! Did you know that ProjectKorra has an official Discord server? A lot of discussion about the official server, development process, and community discussion happens over there. Feel free to join now by clicking the link below.

    Join the Discord Server

Item checkup

OmniCypher

Staff member
Lead Developer
Administrator
Plugin Developer
Firstly, take a look at some of the Spigot JavaDocs. They are very helpful and will show you what you have access to.
https://hub.spigotmc.org/javadocs/spigot/org/bukkit/entity/HumanEntity.html#getInventory--
https://hub.spigotmc.org/javadocs/spigot/org/bukkit/inventory/PlayerInventory.html

Accessing an Inventory can be a little different between an Entity, like a Player, and a Tile Entity, like a chest. I assume you want to do something with an ability and therefore are looking to access a Player's Inventory. It is fairly easy to do and is shown below.
Code:
// Nothing too crazy.
PlayerInventory playerInventory = player.getInventory();
The overall process for removing an item from an inventory is as follows
- Get the players inventory.
- Look through that inventory for the first occurrence of your target item.
- Remove that item from the inventory.

Ok, now that we have the overall process defined let's think of what we need to keep track of
- A Player to get the inventory of.
- A PlayerInventory to store the player's inventory.
- An ItemStack to store our target item.
- An ItemStack to store our current item as we loop through the PlayerInventory.
- An int to store our loops index.
- An int to store the current item's amount.

Great, if that all makes sense then let's look at the implementation.
Code:
// Get the player's inventory and establish our desired target item.
PlayerInventory playerInventory = player.getInventory();
ItemStack targetItem = new ItemStack(Material.STONE);
      
// Loop through the player's inventory to find the target item.
for (int x = 0; x < playerInventory.getSize(); x++) {
    // The current item in the player's inventory.
    ItemStack currentItem = playerInventory.getItem(x);
          
    // Check if the current item is equal to our target item.
    if (currentItem != null && currentItem.isSimilar(targetItem)) {
              
        // It is, Store what the current item's amount will be after removing one item.
        int itemAmount = currentItem.getAmount() - 1;
              
        // Check if the current item's amount will be less than zero after removing one item.
        if (itemAmount > 0) {
            // It will not, set the new amount.
            currentItem.setAmount(itemAmount);
        } else {
            // It will, remove the item from the player's inventory.
            playerInventory.setItem(x, null);
        }

        // Update the player's inventory and stop looping.
        player.updateInventory();
        break;
    }
}

Sidenote: To search for a specific item you will need to have that item defined somewhere in your code to make comparisons with. For now, I will assume you have that defined and I will refer to that ItemStack as the "targetItem".
 

xNuminousx

Member
Firstly, take a look at some of the Spigot JavaDocs. They are very helpful and will show you what you have access to.
https://hub.spigotmc.org/javadocs/spigot/org/bukkit/entity/HumanEntity.html#getInventory--
https://hub.spigotmc.org/javadocs/spigot/org/bukkit/inventory/PlayerInventory.html

Accessing an Inventory can be a little different between an Entity, like a Player, and a Tile Entity, like a chest. I assume you want to do something with an ability and therefore are looking to access a Player's Inventory. It is fairly easy to do and is shown below.
Code:
// Nothing too crazy.
PlayerInventory playerInventory = player.getInventory();
The overall process for removing an item from an inventory is as follows
- Get the players inventory.
- Look through that inventory for the first occurrence of your target item.
- Remove that item from the inventory.

Ok, now that we have the overall process defined let's think of what we need to keep track of
- A Player to get the inventory of.
- A PlayerInventory to store the player's inventory.
- An ItemStack to store our target item.
- An ItemStack to store our current item as we loop through the PlayerInventory.
- An int to store our loops index.
- An int to store the current item's amount.

Great, if that all makes sense then let's look at the implementation.
Code:
// Get the player's inventory and establish our desired target item.
PlayerInventory playerInventory = player.getInventory();
ItemStack targetItem = new ItemStack(Material.STONE);
     
// Loop through the player's inventory to find the target item.
for (int x = 0; x < playerInventory.getSize(); x++) {
    // The current item in the player's inventory.
    ItemStack currentItem = playerInventory.getItem(x);
         
    // Check if the current item is equal to our target item.
    if (currentItem != null && currentItem.isSimilar(targetItem)) {
             
        // It is, Store what the current item's amount will be after removing one item.
        int itemAmount = currentItem.getAmount() - 1;
             
        // Check if the current item's amount will be less than zero after removing one item.
        if (itemAmount > 0) {
            // It will not, set the new amount.
            currentItem.setAmount(itemAmount);
        } else {
            // It will, remove the item from the player's inventory.
            playerInventory.setItem(x, null);
        }

        // Update the player's inventory and stop looping.
        player.updateInventory();
        break;
    }
}

Sidenote: To search for a specific item you will need to have that item defined somewhere in your code to make comparisons with. For now, I will assume you have that defined and I will refer to that ItemStack as the "targetItem".
THIS is how to properly help somebody. *cough* ;3;

Very helpful information Omni, great job.
 
Code:
// Get the player's inventory and establish our desired target item.
PlayerInventory playerInventory = player.getInventory();
ItemStack targetItem = new ItemStack(Material.STONE);
    
// Loop through the player's inventory to find the target item.
for (int x = 0; x < playerInventory.getSize(); x++) {
    // The current item in the player's inventory.
    ItemStack currentItem = playerInventory.getItem(x);
        
    // Check if the current item is equal to our target item.
    if (currentItem != null && currentItem.isSimilar(targetItem)) {
            
        // It is, Store what the current item's amount will be after removing one item.
        int itemAmount = currentItem.getAmount() - 1;
            
        // Check if the current item's amount will be less than zero after removing one item.
        if (itemAmount > 0) {
            // It will not, set the new amount.
            currentItem.setAmount(itemAmount);
        } else {
            // It will, remove the item from the player's inventory.
            playerInventory.setItem(x, null);
        }

        // Update the player's inventory and stop looping.
        player.updateInventory();
        break;
    }
}
I probably skip through the bunch of what you said, because right now my eyes to lazy to read. So If there is alreadya question to my following question, I apologize in advance: That looks like it loops through the quantity of the item per its stack, doesn't it? If so, I don't wanna spend my time on it when I'm checking for a item that can't be stacked. Is there another way of simply removing that item?

ETA Oh nevermind. I think it ignores stack, but counts the stuf in general regardless if the item is stacked/stackable or not.
 

OmniCypher

Staff member
Lead Developer
Administrator
Plugin Developer
What about using player.getInventory().contains ? Does that do any wonders?
If you think about it, contains is doing almost exactly the same thing we are doing above. Let's compare the logic path of both.

Contains: Loop through a collection, as we loop we check if we find a given Object, return true if found, return false if we reach the end.
Search and Remove: Loop through a collection, as we loop we check if we find a given Object, remove one if found.

We could easily add a contains check before our for loop but doing so makes our code slower because we are essentially doing two of the three steps over again. Remember, just because a method is built in does not mean it is faster or possibly better than something you could do on your own. You want to look at a method as what it does and how it does it.

Code:
if (player.getInventory().contains(targetItem)) {
    // Code
}

// Same as above //

boolean hasItem = false;

for (int x = 0; x < playerInventory.getSize(); x++) {
   ItemStack currentItem = playerInventory.getItem(x);
   if ((currentItem == null && targetItem == null) || (currentItem != null && currentItem.isSimilar(targetItem))) {
       hasItem = true;
   }
}

if (hasItem) {
    // Code
}
 

xNuminousx

Member
If you think about it, contains is doing almost exactly the same thing we are doing above. Let's compare the logic path of both.

Contains: Loop through a collection, as we loop we check if we find a given Object, return true if found, return false if we reach the end.
Search and Remove: Loop through a collection, as we loop we check if we find a given Object, remove one if found.

We could easily add a contains check before our for loop but doing so makes our code slower because we are essentially doing two of the three steps over again. Remember, just because a method is built in does not mean it is faster or possibly better than something you could do on your own. You want to look at a method as what it does and how it does it.

Code:
if (player.getInventory().contains(targetItem)) {
    // Code
}

// Same as above //

boolean hasItem = false;

for (int x = 0; x < playerInventory.getSize(); x++) {
   ItemStack currentItem = playerInventory.getItem(x);
   if ((currentItem == null && targetItem == null) || (currentItem != null && currentItem.isSimilar(targetItem))) {
       hasItem = true;
   }
}

if (hasItem) {
    // Code
}
Wow.... Such an inspiration <3
 
Ok, so I'm not making an ability, but a command plugin.

Another question unrelated, but how would I go about the loop adding enchantments to the items? Would I have to use targetItem.addEnchantment(**) where the substraction should take place and skip the rest with the if statement?
 

OmniCypher

Staff member
Lead Developer
Administrator
Plugin Developer
Ok, so I'm not making an ability, but a command plugin.

Another question unrelated, but how would I go about the loop adding enchantments to the items? Would I have to use targetItem.addEnchantment(**) where the substraction should take place and skip the rest with the if statement?
Close, you would want to use currentItem. The targetItem variable is only used to compare against the player's inventory items.
 
Nice it works. Though I can't figure out how to remove multiple simultaniously, or probably only how to check for multiple quantity of the same item. :/
 
Top