[PLUGIN CODING] Problem with instanceof

Discussion in 'Spigot Plugin Development' started by LeHuuHoa, Jul 31, 2019.

  1. I'm pretty new to Bukkit Coding. I'm trying to code a fun plugin on my server for my friends to play but I have a problem

    PhantomChestplate Class:
    Code (Text):
    package me.waykillerz.phantom.PhantomGears;

    import java.util.ArrayList;
    import java.util.List;

    import org.bukkit.Color;
    import org.bukkit.Material;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.inventory.meta.LeatherArmorMeta;

    import me.waykillerz.phantom.ColorUlities;

    public class PhantomChestplate extends ItemStack{
    //  @SuppressWarnings("deprecation")
      public PhantomChestplate() {
        super(Material.LEATHER_CHESTPLATE, 1);
        LeatherArmorMeta meta = (LeatherArmorMeta) this.getItemMeta();
        meta.setDisplayName(ColorUlities.chat("&f&l[&aPhantom Chestplate&f&l]"));
        List<String> lores = new ArrayList<String>();
        lores.add(ColorUlities.chat("&r&eHello"));
        lores.add(ColorUlities.chat("&r&eThis is a phantom chestplate"));
        lores.add(ColorUlities.chat("&r&eWear this to be a phantom"));
        meta.setLore(lores);
        meta.setColor(Color.AQUA);
        this.setItemMeta(meta);
      }
    }
    Listener class
    Code (Text):
    package me.waykillerz.phantom.PhantomSkills;

    import org.bukkit.Bukkit;
    import org.bukkit.Material;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.block.Action;
    import org.bukkit.event.player.AsyncPlayerChatEvent;
    import org.bukkit.event.player.PlayerInteractEvent;
    import org.bukkit.inventory.ItemStack;

    import me.waykillerz.phantom.Main;
    import me.waykillerz.phantom.PhantomGears.PhantomChestplate;

    public class WindOfDeath implements Listener{
      Main pl;
      public WindOfDeath(Main pl) {
        this.pl = pl;
        Bukkit.getPluginManager().registerEvents(this, pl);
      }
     
      @EventHandler
      public void onActivate(PlayerInteractEvent e) {
        if(!(e.getAction() == Action.RIGHT_CLICK_AIR)) return;
        Player p = e.getPlayer();
        if(p.getInventory().getChestplate() == null) return;
        ItemStack i = p.getInventory().getChestplate();
        if(!(i instanceof PhantomChestplate)) return;
        /*
         * [SOMETHING]
         */
      }
     
      @EventHandler
      public void onChat(AsyncPlayerChatEvent e) {
        if(e.getMessage().equals("Hello")) {
          e.getPlayer().getInventory().addItem(new PhantomChestplate());
        }
      }
    }

    The problem here is when I have put on the Phantom Chestplate and right click air (with an item), the [SOMETHING] code does not work, means that variable i does not instance of Phantom Chestplate. I dont know why, the log does not print any error

    The part where I found the issue:
    Code (Text):
    @EventHandler
      public void onActivate(PlayerInteractEvent e) {
        if(!(e.getAction() == Action.RIGHT_CLICK_AIR)) return;
        Player p = e.getPlayer();
        if(p.getInventory().getChestplate() == null) return;
        ItemStack i = p.getInventory().getChestplate();
        if(!(i instanceof PhantomChestplate)) return;
        /*
         * [SOMETHING] <--- This never works
         */
      }

    Can some one help me. Thank you first

    Hope you understand what I wrote, I dont speak English
     
  2. Yeah, you can't really make a subclass of ItemStack like this. Whether it happens in .addItem or when loading the world on startup, the item will lose its identity and just be serialized and deserialized as a normal ItemStack. You will have to choose another way of identifying your chestplate, like checking the name
    Code (Java):
    if (i.getItemMeta().getDisplayName().equals("so and so")) {
    If you're using 1.14 you can use the new NBT api https://www.spigotmc.org/threads/a-guide-to-1-14-persistentdataholder-api.371200/ and just stick in a simple boolean data type that you can check against
     
  3. You can add NBT tag to your item aswell (doesn't matter if It's on 1.8 or 1.12)
     
  4. Theres no api for it in 1.8
     
  5. I use NMS for this on versions lower than 1.14
     
  6. SteelPhoenix

    Moderator

    Using NMS to look at NBT data may not be necessary. Have you considered using ItemStack#isSimilar(ItemStack) or ItemStack#equals(Object)?
     
  7. You may use
    Code (Text):
    ItemStack.isSimilar(ItemStack);
    EDIT: SteelPhoenix, ninja mode: on :ROFLMAO:
     
  8. I did test it before, and it did not work also.



    I'm not really sure how to use NBT on my item but I will check it out tonight. It's 10:12 PM in Vietnam
     
  9. Check if item hasItemMeta, get the item meta, get the displayname and check if the name is equal to the other ItemStack displayname.
     
  10. SteelPhoenix

    Moderator

    ItemStack#isSimilar(ItemStack) already compares ItemMeta completely and item type. It should work just fine, so I think the problem lies within OP's code.
     
  11. isSimilar is also comparing the durability of the item.
    So if the item gets damaged, this will not work.
     
    • Informative Informative x 1
  12. Try adding metadata to item and read it afterwards
     
  13. Metadata is not getting saved after server stopping.
     
  14. Why don't we clone each item, set durability values same and use itemStack.equals()
     
  15. When you do this ...
    Code (Text):
    e.getPlayer().getInventory().addItem(new PhantomChestplate());
    That is not adding the item to where you are trying to get the item from !
    Code (Text):
    if(p.getInventory().getChestplate() == null) return;
    Resulting in, the player has to manualy put the PhantomChestplate into their ChestPlate slot, to wear the item.
     
  16. I already said that I have put on the chestplate.


    Anyway, thank you guys for helping. I succeded in using NBT and now the plugin works. This is how I did it:

    Phantom Chestplate:
    Code (Text):
    package me.waykillerz.phantom.PhantomGears;

    import java.util.ArrayList;
    import java.util.List;

    import org.bukkit.Color;
    import org.bukkit.Material;
    import org.bukkit.NamespacedKey;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.inventory.meta.LeatherArmorMeta;
    import org.bukkit.persistence.PersistentDataContainer;
    import org.bukkit.persistence.PersistentDataType;
    import org.bukkit.plugin.Plugin;

    import me.waykillerz.phantom.ColorUlities;
    import me.waykillerz.phantom.Main;

    public class PhantomChestplate extends ItemStack{
     
      static Plugin pl = Main.getInstance();
     
      public static boolean is(ItemStack i) {
        PersistentDataContainer container = i.getItemMeta().getPersistentDataContainer();
        NamespacedKey key = new NamespacedKey(pl, "isPhantomChestplate");
        if(container.has(key , PersistentDataType.INTEGER)) {
          int v = container.get(key, PersistentDataType.INTEGER);
          if(v == 1) {
            return true;
          }else {
            return false;
          }
        }else
        return false;
      }
     
    //  @SuppressWarnings("deprecation")
      public PhantomChestplate() {
        super(Material.LEATHER_CHESTPLATE, 1);
        NamespacedKey key = new NamespacedKey(pl, "isPhantomChestplate");
        LeatherArmorMeta meta = (LeatherArmorMeta) this.getItemMeta();
        meta.getPersistentDataContainer().set(key, PersistentDataType.INTEGER, 1);
        meta.setDisplayName(ColorUlities.chat("&f&l[&aPhantom Chestplate&f&l]"));
        List<String> lores = new ArrayList<String>();
        lores.add(ColorUlities.chat("&r&eHello"));
        lores.add(ColorUlities.chat("&r&eThis is a phantom chestplate"));
        lores.add(ColorUlities.chat("&r&eWear this to be a phantom"));
        meta.setLore(lores);
        meta.setColor(Color.AQUA);
        this.setItemMeta(meta);
      }
    }
     
    Listener class:
    Code (Text):
    package me.waykillerz.phantom.PhantomSkills;

    import org.bukkit.Bukkit;
    import org.bukkit.Material;
    import org.bukkit.NamespacedKey;
    import org.bukkit.entity.Entity;
    import org.bukkit.entity.LivingEntity;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.block.Action;
    import org.bukkit.event.player.AsyncPlayerChatEvent;
    import org.bukkit.event.player.PlayerInteractEvent;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.potion.PotionEffect;
    import org.bukkit.potion.PotionEffectType;

    import me.waykillerz.phantom.Main;
    import me.waykillerz.phantom.PhantomGears.PhantomChestplate;

    public class WindOfDeath implements Listener{
      Main pl;
      public WindOfDeath(Main pl) {
        this.pl = pl;
        Bukkit.getPluginManager().registerEvents(this, pl);
      }
     
     
     
      @EventHandler
      public void onActivate(PlayerInteractEvent e) {
        if(!(e.getAction() == Action.RIGHT_CLICK_AIR)) return;
        Player p = e.getPlayer();
        if(p.getInventory().getChestplate() == null) return;
        ItemStack i = p.getInventory().getChestplate();
        if(!PhantomChestplate.is(i)) return;
        for(Entity en : p.getNearbyEntities(10, 10, 10)) {
          if(en instanceof LivingEntity) {
            ((LivingEntity) en).addPotionEffect(new PotionEffect(PotionEffectType.POISON, 3*20, 2));
            ((LivingEntity) en).addPotionEffect(new PotionEffect(PotionEffectType.SLOW, 3*20, 1));
            ((LivingEntity) en).addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 3*20, 2));
            ((LivingEntity) en).addPotionEffect(new PotionEffect(PotionEffectType.GLOWING, 3*20, 2));
          }
        }
      }
     
      @EventHandler
      public void onChat(AsyncPlayerChatEvent e) {
        if(e.getMessage().equals("Hello")) {
          e.getPlayer().getInventory().addItem(new PhantomChestplate());
        }
      }
    }