How to get enchantments on item using NMS

Discussion in 'Spigot Plugin Development' started by ktri, Apr 17, 2019 at 4:50 AM.

  1. I'm trying to add and check enchants on an item using NMS. For the longest time I was doing this with Item.addEnchantment() and Item.getItemMeta().hasEnchantment() but I was told that this is not the proper way and that professionals use NMS. So now here I am trying to learn NMS Enchanting. I think I am adding an enchant properly but I can't seem to get the list to check it afterwards. Here is what I have for adding the enchant:

    Code (Text):
    final ItemStack item = player.getInventory().getItemInMainHand();
                final net.minecraft.server.v1_12_R1.ItemStack nmsStack = CraftItemStack.asNMSCopy(item);
                final NBTTagCompound compound = (nmsStack.hasTag()) ? nmsStack.getTag() : new NBTTagCompound();
                final NBTTagList ench = new NBTTagList();
                final NBTTagCompound enchant = new NBTTagCompound();
                enchant.set("id", new NBTTagInt(118));
                enchant.set("lvl", new NBTTagInt(1));
                ench.add(enchant);
                compound.set("ench", ench);
                nmsStack.setTag(compound);
                player.getInventory().setItemInMainHand(CraftItemStack.asBukkitCopy(nmsStack));
    and here is what I have for checking if it exists on the item:

    Code (Text):
    final ItemStack item = player.getInventory().getItemInMainHand();
                final net.minecraft.server.v1_12_R1.ItemStack nmsStack = CraftItemStack.asNMSCopy(item);
    final NBTTagCompound compound =  nmsStack.getTag();
    final NBTTagList ench = compound.getList("ench", 0);
    player.sendMessage("" + ench.get(0).get("id"));
    player.sendMessage just prints null instead of 118 like I would expect so something is clearly wrong. I tried looking through the nms but it is all obfuscated with methods named as single letters and variables named var1, var2, etc so I really don't know what I'm doing here. Also I don't even know if this is the correct approach that the guy, who told me I was doing enchants wrong, was referring to. He just said when I asked what was wrong with my code that I should "Add a lore and NBT to represent the enchantment instead of using mc enchantment id" If I am going about this wrong could someone please provide an nms example of how to properly add check and use nms enchants? Thanks.
     
    #1 ktri, Apr 17, 2019 at 4:50 AM
    Last edited: Apr 17, 2019 at 4:57 AM
  2. I'm not 100% sure what's wrong here, however I don't quite understand the motivation behind working with enchants via NMS, professionals use clean code and that is definitely not clean code, leading me to believe that whoever told you that is definitely wrong. ItemMeta#addEnchant and ItemMeta#hasEnchant are perfectly acceptable to use.

    I see you are using NBT there, if the reason you turned to nms was to use NBT I would suggest not doing that and instead using this well-written and easy to use api by tr7zw found here.
     
    • Agree Agree x 2
  3. Ah that looks promising thanks. Though one more question. I noticed that when I add a tag it does not add the enchantment glow. While I have seen other posts saying that I could register a blank enchant and just add that to the item or apply infinity and remove the lore, I would like to know if there is a more proper way to add the enchantment glow that is not a hacky work-around. Like is there a tag that I can set that determines if the item has the glow or not? Thanks.
     
  4. https://bukkit.org/threads/how-to-make-an-item-glow-with-no-enchant.374594/ not tested this in 1.13, but I believe I used it in 1.12 without issue, the main difference being that the super constructor takes a NamespacedKey rather than a numeric ID.
    Registering a custom enchant might still be considered a bit "hacky", but there's no way to just set an item to glow with no enchants. Also this glow might break on restart.
     
  5. While there is no definitive way to do that yes without some very hacky nms which I doubt could work, you can just register an enchant on the item such as
    Code (Java):
    Enchantment.OXYGEN
    On a pickaxe or bow for example, and then use other irrelevant ones such as infinity for armour or swords etc.
    You can then hide the enchantment using the flag:

    void addItemFlags(ItemFlag... itemFlags)
    Set itemflags which should be ignored when rendering a ItemStack in the Client.

    IE:
    Code (Java):
    itemMeta.addItemFlag(ItemFlag.HIDE_ENCHANTS);
    And that shouldn't be lost on restart as it uses nbt to save that data.
     
  6. It's a shame that spigot and bukkit removes the ability to have invalid achievements glow like you can in vanilla :/

    I'm sure that there are reasons for it
     
  7. I am surprised because I feel like whether or not the item has the glow effect on it has to be stored in some variable somewhere. Even if its private maybe it could be accessed with reflection. I feel like that would involve digging deep into the nms though and that would take way more time than its worth. I was just hoping there was a known method. Guess Ill just use the oxygen enchant.
     
  8. Yeah afaik there is no "glowing variable" only whether it has enchants or not.
     
  9. I'd imagine it's more likely a client-side visual effect based on the item having an enchantment.
     
    • Agree Agree x 1

Share This Page