Solved Replace an item if a Player interacts with it in their inventory

Discussion in 'Spigot Plugin Development' started by PieCrafted, Sep 11, 2019.

  1. I'm trying to make an event that will detect if a player interacts (drops, clicks with cursor, uses shift+click, dies with item equipped, attempts to put the item into a chest/furnace/crafting table, etc.) with certain "special" items and will remove the item from the player if they attempt to do anything with the item besides leave it in their inventory in the spot where it was given to them by a kit command.

    Here is what I have so far:

    Code (Java):
    @EventHandler(priority = EventPriority.HIGHEST)
        public void onKitItemPickup(InventoryClickEvent event) {
           
            if(event.getCurrentItem().equals(Material.CHAINMAIL_BOOTS)) {
               
                event.setCurrentItem(new ItemStack(Material.IRON_BOOTS).setDurability(1));
               
            } else if(event.getCurrentItem().getItemMeta().getLore().contains("Red Team")) {
               
                event.setCurrentItem(new ItemStack(Material.AIR));
               
            }
           
        }
    Here is what is supposed to happen:
    1. Player runs a /kit-like command that will automatically equip specially enchanted chain-mail boots into the "boots" slot of their inventory.
    2. Player clicks on the item in their inventory.
    3. Item is replaced with a pair of iron boots with only 1 health point.
    4. Player learns not to try to remove special equipment from inventory
    5. Profit ;)
    Here is what actually happens:
    1. Player runs a /kit-like command that will automatically equip specially enchanted chain-mail boots into the "boots" slot of their inventory.
    2. Player clicks on the item in their inventory.
    3. An error is thrown with reference to the "event.setCurrentItem(new ItemStack(Material.IRON_BOOTS).setDurability(1));" line.
    4. Player gets to keep special equipment.
    5. Server economy is ruined :(
    Any help would be greatly appreciated! Thank you!
     
  2. The setDurability method doesn't return an ItemStack. Try creating the ItemStack, then set the durability, then setCurrentItem. Also, I'm not sure what Spigot version you're using, but in newer versions (I think 1.13+) the setDurability method is deprecated. You should use the ItemMeta to set the damage instead.
     
    #2 SavageAvocado, Sep 11, 2019
    Last edited: Sep 11, 2019
  3. I would give any item that should not be interacted with an NBT-Tag (or if you are not using stone age versions of Spigot a PersistentDataContainer entry) and check for it on every interaction event. Done. :coffee:

    like (pseudocode)
    Code (Text):
    nbtItem.addSection("__NONINTERACTABLE");

    onEvent(SomeInventoryEvent event){
        if(nbtItem.hasKey("__NONINTERACTABLE"){
             event.getInventory().setItem(event.getSlot(), null);
        }
    }
     
  4. Thank you both for your advice. I'll implement these changes later today and let you know the result.
     
  5. Alright, I am trying to implement the changes but my compiler keeps throwing an error:

    Code (Text):
    ItemStack boots = new ItemStack(Material.IRON_BOOTS);
                Damageable im = (Damageable) boots.getItemMeta();
                im.setDamage(195);
                boots.setItemMeta(im);
    "The method setItemMeta(ItemMeta) in the type ItemStack is not applicable for the arguments (Damageable)"

    What am I screwing up?
     
  6. You are importing the wrong Damageable. Import org.bukkit.inventory.meta.Damageable.
     
  7. These are my imports as of the above post:
    Code (Java):
    import org.bukkit.Material;
    import org.bukkit.configuration.file.FileConfiguration;
    //import org.bukkit.entity.Damageable;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.EventPriority;
    import org.bukkit.event.Listener;
    import org.bukkit.event.inventory.InventoryClickEvent;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.inventory.meta.Damageable;
    import org.bukkit.inventory.meta.ItemMeta;
     
  8. Nice!
     
  9. Sorry if I didn't make this clearer.

    Even with the import you suggested, I am still receiving the error. Do you happen to know why? Thank you.

    [​IMG]
     
  10. That is strange.. Try to remove the lines completely so there is not an error anymore, restart your IDE and readd these lines. You can also remove the commented import.
     
  11. By taking one more look at the Javadocs, org.bukkit.inventory.meta.Damageable does not extend org.bukkit.inventory.meta.ItemMeta (anymore?). That is very odd. Maybe someone else can help and explain it. I think some weeks ago, this was not the case and it also does not make any sense.
     
  12. I complied the plugin and receive the same error message in my console. "The method setItemMeta(ItemMeta) in the type ItemStack is not applicable for the arguments (Damageable)"

    Thanks for your help!
     
  13. Cast the damageable to ItemMeta.
     
  14. Did you even read what I wrote? That would cause a ClassCastException.
     
  15. I did read what you wrote. I also tried it before suggestion it to make sure it would work, because you're right, it should throw a ClassCastException. But for whatever reason, it just works. I don't know why.
     
  16. Got it to work!

    Thank you all for your help. Here is the final code in case anyone else stumbles upon this thread:

    Code (Java):
    @EventHandler(priority = EventPriority.HIGHEST)
        public void onKitPickup(InventoryClickEvent event) {
           
            if(event.getWhoClicked() instanceof Player){
           
                Player p = (Player) event.getWhoClicked();
               
                if(event.getCurrentItem().getType() == Material.CHAINMAIL_BOOTS && p.getGameMode().equals(GameMode.SURVIVAL)) {
                   
                    ItemStack boots = new ItemStack(Material.IRON_BOOTS);
                    Damageable im = (Damageable) boots.getItemMeta();
                    im.setDamage(195);
                    boots.setItemMeta((ItemMeta) im);
                   
                    event.setCurrentItem(boots);
                   
                    p.playSound(p.getLocation(), Sound.ENTITY_ITEM_BREAK, 1F, 1F);
                   
                }
           
            }
           
        }