Check if player has 4 or more of an Item Stack then give the player an Item on right click in GUI.

Discussion in 'Plugin Development' started by Gladiator, Jun 14, 2022.

  1. Offline

    Gladiator

    Hello I am trying to check if player has 4 or more of an Item Stack then let them click an item in the GUI and get it. The GUI works. My if statement for checking is not working and I don't know what to do. Please help. Thank you

    My code:

    Code:
    package me.gladiator.betraysmp.events;
    
    import org.bukkit.ChatColor;
    import org.bukkit.Material;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.inventory.ClickType;
    import org.bukkit.event.inventory.InventoryClickEvent;
    import org.bukkit.inventory.Inventory;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.inventory.meta.ItemMeta;
    import java.util.Arrays;
    
    public class IngotGUIMain implements Listener {
    @EventHandler
    public void IngotGUIFunctions(InventoryClickEvent event) {
    
    ItemStack BetrayIngot = new ItemStack(Material.NETHERITE_INGOT);
    ItemMeta meta = BetrayIngot.getItemMeta();
    meta.setDisplayName(ChatColor.LIGHT_PURPLE + "" + ChatColor.BOLD + "Betray Ingot");
    meta.setLore(Arrays.asList("The Betray Ingot.", "Use 4 of these to craft a Ban Token."));
    
    BetrayIngot.setItemMeta(meta);
    
    ItemStack shell = new ItemStack(Material.NAUTILUS_SHELL);
    ItemMeta shellmeta = shell.getItemMeta();shellmeta.setDisplayName(ChatColor.YELLOW + "" + ChatColor.BOLD + "Ban Token");
    shellmeta.setLore(Arrays.asList("The Ban Token.", "Bans any player for 24 hours."));
    
    shell.setItemMeta(shellmeta);
    
    ItemStack sea = new ItemStack(Material.HEART_OF_THE_SEA);
    ItemMeta seameta = sea.getItemMeta();
    seameta.setDisplayName(ChatColor.BLUE + "" + ChatColor.BOLD + "Revive Token");
    seameta.setLore(Arrays.asList("The Revive Token.", "Revives any player that is banned."));
    
    sea.setItemMeta(seameta);
    
    Player player = (Player) event.getWhoClicked();
    ClickType click = event.getClick();
    ItemStack item = event.getCurrentItem();
    Inventory inventory = event.getInventory();
    if (event.getView().getTitle().equalsIgnoreCase(ChatColor.GOLD + "" + ChatColor.BOLD + "Betray Ingot Craft")) {
    
    if(BetrayIngot.getAmount() >= 4){
    
    if (item.isSimilar(sea)) {
    event.setCancelled(true);
    player.closeInventory();
    player.getInventory().addItem(sea);
    player.getInventory().removeItem(BetrayIngot);
    player.getInventory().removeItem(BetrayIngot);
    player.getInventory().removeItem(BetrayIngot);
    player.getInventory().removeItem(BetrayIngot);
    }
    if (item.isSimilar(shell)) {
    event.setCancelled(true);
    player.closeInventory();player.getInventory().addItem(shell);
    player.getInventory().removeItem(BetrayIngot);
    player.getInventory().removeItem(BetrayIngot);
    player.getInventory().removeItem(BetrayIngot);
    player.getInventory().removeItem(BetrayIngot);}
    }
    else if(BetrayIngot.getAmount() < 4){
    player.sendMessage(ChatColor.RED + "You need 4 Betray Ingots to craft a token.");
    player.closeInventory();}
    }
    }
     
    Last edited by a moderator: Jun 14, 2022
  2. Offline

    DopeBrot

    you are checking if "BetrayIngot" the Itemstack you just created is more or equal to 4
    you need to check if "item" is more or equal to 4
     
  3. Offline

    Gladiator

    I did that but it still says gives me the message, "You need 4 Betray Ingots to craft a token."
     
  4. Offline

    DopeBrot

    if i understand you correctly you want check if a player has 1 item with the amount of 4 or more?
    if yes then you would need to check every slot in the player inventory and search for this itemstack
    if yes check if the itemstack has the amount you want and after that do what you want with it

    Code:
    if (event.getWhoClicked().getInventory().contains(BetrayIngot)) { // checks if player even has itemstack
        for (int i = 0; i < event.getInventory().getSize(); i++) { // loops through every slot
            if (event.getInventory().getItem(i).isSimilar(BetrayIngot)) { // if the slot is Similar to the itemstack
                if (event.getInventory().getItem(i).getAmount() >= 4) { // if the itemstack of the slot is equal or more than 4
                    event.getInventory().getItem(i).setAmount(event.getInventory().getItem(i).getAmount() - 4); // remove 4 from the itemstack
                    // code here
                }
            }
        }
    }
    what you did here is check if the itemstack has the amount of 4
    and even when you change BetrayIngot.getAmount() to click.getAmount()
    it won't work because you only look at the amount of the itemstack you clicked on
    i hope i don't miss something here
     
  5. Offline

    Gladiator

    When I use this code it doesn't even check if you have 4 ingots or not. Here is my code:
    Code:
    package me.gladiator.betraysmp.events;
    
            import org.bukkit.ChatColor;
            import org.bukkit.Material;
            import org.bukkit.entity.Player;
            import org.bukkit.event.EventHandler;
            import org.bukkit.event.Listener;
            import org.bukkit.event.inventory.ClickType;
            import org.bukkit.event.inventory.InventoryClickEvent;
            import org.bukkit.inventory.Inventory;
            import org.bukkit.inventory.ItemStack;
            import org.bukkit.inventory.meta.ItemMeta;
    
            import java.util.Arrays;
    
    public class IngotGUIMain implements Listener {
        @EventHandler
        public void IngotGUIFunctions(InventoryClickEvent event) {
            ItemStack BetrayIngot = new ItemStack(Material.NETHERITE_INGOT);
            ItemMeta meta = BetrayIngot.getItemMeta();
            meta.setDisplayName(ChatColor.LIGHT_PURPLE + "" + ChatColor.BOLD + "Betray Ingot");
            meta.setLore(Arrays.asList("The Betray Ingot.", "Use 4 of these to craft a Ban Token."));
            BetrayIngot.setItemMeta(meta);
    
            ItemStack shell = new ItemStack(Material.NAUTILUS_SHELL);
            ItemMeta shellmeta = shell.getItemMeta();
            shellmeta.setDisplayName(ChatColor.YELLOW + "" + ChatColor.BOLD + "Ban Token");
            shellmeta.setLore(Arrays.asList("The Ban Token.", "Bans any player for 24 hours."));
            shell.setItemMeta(shellmeta);
    
            ItemStack sea = new ItemStack(Material.HEART_OF_THE_SEA);
            ItemMeta seameta = sea.getItemMeta();
            seameta.setDisplayName(ChatColor.BLUE + "" + ChatColor.BOLD + "Revive Token");
            seameta.setLore(Arrays.asList("The Revive Token.", "Revives any player that is banned."));
            sea.setItemMeta(seameta);
    
            Player player = (Player) event.getWhoClicked();
            ClickType click = event.getClick();
            ItemStack item = event.getCurrentItem();
            Inventory inventory = event.getInventory();
    
            if (event.getView().getTitle().equalsIgnoreCase(ChatColor.GOLD + "" + ChatColor.BOLD + "Betray Ingot Craft")) {
                if (event.getWhoClicked().getInventory().contains(BetrayIngot)) {
                    for (int i = 0; i < event.getInventory().getSize(); i++) {
                        if (event.getInventory().getItem(i).isSimilar(BetrayIngot)) {
                            if (event.getInventory().getItem(i).getAmount() >= 4) {
                                event.getInventory().getItem(i).setAmount(event.getInventory().getItem(i).getAmount() - 4);
                                if (item.isSimilar(sea)) {
                                    event.setCancelled(true);
                                    player.closeInventory();
                                    player.getInventory().addItem(sea);
                                }
                                if (item.isSimilar(shell)) {
                                    event.setCancelled(true);
                                    player.closeInventory();
                                    player.getInventory().addItem(shell);
                                }
                            }
                        }
                        else if (event.getInventory().getItem(i).getAmount() <= 4) {
                            player.sendMessage(ChatColor.RED + "You need 4 Betray Ingots to craft a token.");
                            player.closeInventory();
                        }
                    }
                }
            }
        }
    }
    
    
     
  6. Offline

    gochi9

    This is wrong, read edit.-----------------------------(The method getInventory().contains() won't trigger since you are you are creating a new ItemStack object every time on click so even though they have the same name/material/lore etc. contains() method won't trigger since they are different objects. So in your case the code doesn't get to the loop.------------------------------------

    EDIT: I am wrong, I thought that the class for ItemStack does not override equals() and hashCode() but it does. Your problem here is that when you do contains() it uses the method equals() from the respective object which in our case (ItemStack) looks like this.
    Code:
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof ItemStack)) {
            return false;
        }
    
        ItemStack stack = (ItemStack) obj;
            return getAmount() == stack.getAmount() && isSimilar(stack);
    }
    
    As you can see it also checks for amount, so when you create BetrayIngot it has it's default amount value set to 1 and if you have 4 ingot stacked together in your inventory than contains(BetrayIngot) returns false but if you were to only have 1 ingot it will return true;

    So this check is useless in your case
    Code:
    if (event.getWhoClicked().getInventory().contains(BetrayIngot))
    
    What you want to do is to create a new int variable and loop though the contents of the player's inventory and then check if the item isn't null and the item.isSimilar(yourItem) if it is then add the amount of the respective item to your newly created variable and also check if the value if >= 4 and if it than you can break the loop and continue your code. Here is an example

    Code:
            ItemStack[] contents = player.getInventory().getContents();
            int value = 0;
                  
            for(ItemStack item : contents) {
                if(item == null || !item.isSimilar(yourItem))
                    continue;
                      
                value += item.getAmount();
                      
                if(value >= 4)
                    break;
            }
                  
            if(value < 4)
                return;
                  
            //Your code
    
    Also I recommend that you don't create the items every single time on click and that you create them in a separate class once at the start of the server and use the same ItemStack for everything else.)
     
    Last edited: Jun 22, 2022 at 5:00 AM
  7. Offline

    Strahan

    If you use a stream, you can distill all that down:
    Code:
    int total = player.getInventory().all(BetrayIngot.getType()).entrySet().stream()
                .filter(o -> o.getValue().isSimilar(BetrayIngot))
                .mapToInt(o -> o.getValue().getAmount()).sum();
     

Share This Page