Solved NBT Tags

Discussion in 'Plugin Development' started by Jogy34, Nov 10, 2012.

Thread Status:
Not open for further replies.
  1. Offline

    Jogy34

    This is mostly for general information about NBT Tags.

    I really just want to know what all the compounds are that can be added to NBT Tags that actually do something. For instance I know the name of an Item is under a display compound then under Name and changing that would change the name of the item. But what about for things like enchantments and the skin that shows up on skulls or the information thing that shows up under a potion.

    Any explanation of these or others would be greatly appreciated.
     
  2. Offline

    one4me

  3. Offline

    Jogy34

    O thanks, that helps a lot.

    I'm running into a problem whenever I try to set lore. It gives me this error then kicks me from an internal server error:
    Code:
    23:28:27 [WARNING] Failed to handle packet: java.lang.IllegalArgumentException: Empty string not allowed
    java.lang.IllegalArgumentException: Empty string not allowed
            at net.minecraft.server.NBTTagString.<init>(SourceFile:15)
            at net.minecraft.server.NBTTagString.clone(SourceFile:39)
            at net.minecraft.server.NBTTagList.clone(SourceFile:87)
            at net.minecraft.server.NBTTagCompound.clone(NBTTagCompound.java:239)
            at net.minecraft.server.NBTTagCompound.clone(NBTTagCompound.java:239)
            at net.minecraft.server.ItemStack.cloneItemStack(ItemStack.java:232)
            at net.minecraft.server.Packet5EntityEquipment.<init>(SourceFile:20)
            at net.minecraft.server.EntityLiving.j_(EntityLiving.java:480)
            at net.minecraft.server.EntityHuman.j_(EntityHuman.java:154)
            at net.minecraft.server.EntityPlayer.g(EntityPlayer.java:188)
            at net.minecraft.server.NetServerHandler.a(NetServerHandler.java:349)
            at net.minecraft.server.Packet10Flying.handle(SourceFile:136)
            at net.minecraft.server.NetworkManager.b(NetworkManager.java:282)
            at net.minecraft.server.NetServerHandler.d(NetServerHandler.java:111)
            at net.minecraft.server.ServerConnection.b(SourceFile:35)
            at net.minecraft.server.DedicatedServerConnection.b(SourceFile:30)
            at net.minecraft.server.MinecraftServer.r(MinecraftServer.java:569)
            at net.minecraft.server.DedicatedServer.r(DedicatedServer.java:215)
            at net.minecraft.server.MinecraftServer.q(MinecraftServer.java:486)
            at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:419)
            at net.minecraft.server.ThreadServerApplication.run(SourceFile:818)
    
    My code for setting the Lore:
    Code:
                NBTTagCompound tag = getTag(p.getItemInHand());
                if(tag.getCompound("display") != null)
                {
                    tag.setCompound("display", new NBTTagCompound());
                }
                // Gets the display tag.
                NBTTagCompound display = tag.getCompound("display");
                //Removes the old name
                display.remove("Lore");
                //sets the new name
                NBTTagList list = new NBTTagList();
                list.add(new NBTTagString("TESTING"));
                display.set("Lore", list);
    
    The getTag method returns the tag of the itemstack. I know it works up until I create the NBTTagList object. I have tried it with replacing the name of the item and it works.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 29, 2016
  4. Offline

    Codex Arcanum

    Huh. I wonder if you could, say set the "author" on a stone sword if you wanted to store information. If it works, that would be very interesting.
     
  5. Offline

    one4me

    I wrote this off the top of my head, so it may need a few changes, but for the most part this is how you'd do that.

    Code:
    /*Get tag compound*/
    NBTTagCompound c = item.getTag();
    
    /*Create display tag if it does not already exist*/
    if(!c.hasKey("display")) {
      c.set("display", new NBTTagCompound());
    }
    
    /*Gets display compound*/
    NBTTagCompound d = c.getCompound("display");
    
    /*Create Lore tag if it does not already exist*/
    if(!d.hasKey("Lore")) {
      d.set("Lore", new NBTTagList());
    }
    
    /*Gets Lore list*/
    NBTTagList l = d.getList("Lore");
    
    /*Add a string to the list*/
    l.add(new NBTTagString("", "String here1"));
    l.add(new NBTTagString("", "String here2"));
    
    /*Sets the list to the display compound*/
    d.set("Lore", l);
    
    There may already be a method to set Lore data like there is to set the Name, but I didn't look.
     
  6. Offline

    Jogy34

    Thank you that works. What's the "" for in the first argument of the NBTTagString though?

    Also I'm guessing I would do the same thing for enchantments but with NBTCompound objects holding NBTTagShort objects for the id and level.
     
  7. Offline

    one4me

    The first parameter, the "", would be the name of the NBTTagString, but since that really isn't needed for a string it's normally left blank.

    The process should be the same for any NBT data. Of course with enchantments, you can always just use one of the addEnchantment methods which saves you the trouble of editing the NBT data yourself.
     
  8. Offline

    Jogy34

    I wanted to use NBTTags for enchantments for items that aren't normally supposed to have enchantments like sticks. I've tried using the addUnsafeEnchantment() method but that only allows me to put on enchantments that have a higher level than they are supposed to and not actually put them on items that aren't supposed to have enchantments unless they changed it from 1.4. Anyways I think I've got the hang of NBT Tags, thanks for all of your help[diamond]
     
  9. Offline

    one4me

    Great, also I shouldn't say the first parameter in an NBTTagString is normally left blank, but in an NBTTagList, the name of a tag isn't saved, so there's not much of a point in putting something other than "".
     
  10. Offline

    Jogy34

    If not in a list what would it be used for?
     
  11. Offline

    one4me

    Such as the title, author, Name, and SkullOwner tags. They're all NBTTagStrings and have a Name and data. But if the NBTTagString is in an NBTTagList like pages, or Lore, the string has only data, and no name.

    Edit - I take that and the last post back... it's 1 in the morning and I'm tired. I was mixing up two methods and a constructor - setString(String s, String s1), set(String s, NBTBase nbtbase), and new NBTTagString(String arg0, String arg1). But never mind I'm just confusing myself and you. 'night.
     
  12. Offline

    rmh4209

    Hey. If you want to learn a little bit more about how NBT Tags work with names and such, check out DiabloDrops' source here: DiabloDrops

    It's a plugin entirely based around manipulating NBT Tags.
     
    Deathmarine likes this.
  13. Offline

    Jogy34

    one4me I was trying to rename an item in a PrepareItemCraftEvent but when I tried to cast the ItemStack from that to a CraftItemStack to get the tag it threw a ClassCastException. What I do now is rename it in a CraftItemEvent and it works fine. Do those events use different ItemStack objects or something?
     
  14. Offline

    one4me

    Use the constructor to make a new CraftItemStack?
    Code:
    @EventHandler
    public void onPrepareItemCraftEvent(PrepareItemCraftEvent event) {
      ItemStack bis = new ItemStack(1);
      CraftItemStack cis = new CraftItemStack(bis);
      net.minecraft.server.ItemStack mis = cis.getHandle();
      mis.c("test");
      event.getInventory().setResult(cis);
    }
    
    It was a little buggy when I shift clicked for the result, I'd recommend just adding a new recipe.[/CODE]
     
  15. Offline

    Jogy34

    I tried adding a new recipe and it only kept the enchantments not the name or lore.
     
  16. Offline

    one4me

    I could add the recipe, with enchantments, name, and lore easily enough, but the shift clicking issue remains.
    Code:
    public void test() {
      CraftItemStack cis = new CraftItemStack(1);
      net.minecraft.server.ItemStack mis = cis.getHandle();
      mis.addEnchantment(net.minecraft.server.Enchantment.DAMAGE_ALL, 5);
      mis.addEnchantment(net.minecraft.server.Enchantment.SILK_TOUCH, 1);
      mis.c(ChatColor.RESET + "" + ChatColor.MAGIC + "Magic");
      NBTTagList list = new NBTTagList();
      list.add(new NBTTagString("", ChatColor.LIGHT_PURPLE + "Magic Stone"));
      mis.tag.getCompound("display").set("Lore", list);
      CraftingManager.getInstance().registerShapedRecipe(mis, new Object[] {"***", "*@*", "***", Character.valueOf('*'), Block.STONE, Character.valueOf('@'), Item.SUGAR});
    }
    
     
  17. Offline

    Jogy34

    Hmmm, whenever I tried adding a recipe only the enchantments would show up. I'll try it again. Thanks for the help
     
  18. Offline

    david_rosales

    Mine wont work...
    This is what i tried. I have no idea how to use NBT so, can someone help?
    Code:java
    1.  
    2. }else if(commandLabel.equalsIgnoreCase("TestCommand"))
    3. {
    4. NBTTagCompound c = getTag(player.getItemInHand());
    5.  
    6. if(!c.hasKey("display")) {
    7. c.set("display", new NBTTagCompound());
    8. }
    9.  
    10. NBTTagCompound d = c.getCompound("display");
    11.  
    12. if(!d.hasKey("Lore")) {
    13. d.set("Lore", new NBTTagList());
    14. }
    15.  
    16. NBTTagList l = d.getList("Lore");
    17.  
    18. l.add(new NBTTagString("", "String here1"));
    19. l.add(new NBTTagString("", "String here2"));
    20.  
    21. d.set("Lore", l);
    22. }
    23.  


    This is based off of what one4me said.
     
  19. Offline

    rmh4209

    stirante has a great library that you can use for that called PrettyScaryLib.
     
  20. Offline

    david_rosales

    rmh4209
    I looked at it but couldnt get it to work. I have a feeling im doing it wrong. Obviously i am because it wont work.
    here is my code:
    Code:java
    1.  
    2. if(commandLabel.equalsIgnoreCase("TestCommand"))
    3. {
    4. ItemStack Sword = new ItemStack(Material.IRON_SWORD);
    5. player.setItemInHand(Sword);
    6. Namer.setName(Sword, "TestName");
    7. Namer.addLore(Sword, "TestLore");
    8. }
    9.  
     
  21. Offline

    Jogy34

    Can I see your getTag() method. I have a feeling you aren't casting to a CraftItemStack and instead you are using the CraftItemStack constructor. If you are you have to set the item with the CraftItemStack you get from your method
     
  22. Offline

    david_rosales

    Thats probably the problem. That's all i have.
     
  23. Offline

    rmh4209

    Well, let me take a stab at seeing if I can get this to work for you.

    Code:java
    1.  
    2. /* Use command.getName() here instead of commandLabel */
    3. /* It's traditionally been more reliable than commandLabel in my experience */
    4. if(command.getName().equalsIgnoreCase("testcommand"))
    5. {
    6. /* It's a good idea to make sure the amount in the ItemStack is 1 */
    7. ItemStack sword = new ItemStack(Material.IRON_SWORD, 1);
    8. /* This code should make sure that the ItemStack's name is "TestName" */
    9. sword = Namer.setName(sword, "TestName");
    10. /* This code should make sure that the ItemStack's lore contains "TestLore" */
    11. sword = Namer.addLore(sword, "TestLore");
    12. /* Make sure to only set the item in the players hand AFTER messing around with its values */
    13. player.setItemInHand(sword);
    14. }
    15.  


    Hopefully that will fix your issue.
     
  24. Offline

    david_rosales

    That might work.. i had been trying to set the item in hand first, then editing it. I'll test it when i get my computer on.

    Wont work.. Keep getting an error
    012-11-22 11:49:07 [SEVERE] null
    org.bukkit.command.CommandException: Unhandled exception executing command 'testcommand' in plugin KhSkills v1.0.0
    at org.bukkit.command.PluginCommand.execute(PluginCommand.java:46)
    at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:186)
    at org.bukkit.craftbukkit.CraftServer.dispatchCommand(CraftServer.java:502)
    at net.minecraft.server.NetServerHandler.handleCommand(NetServerHandler.java:985)
    at net.minecraft.server.NetServerHandler.chat(NetServerHandler.java:903)
    at net.minecraft.server.NetServerHandler.a(NetServerHandler.java:858)
    at net.minecraft.server.Packet3Chat.handle(Packet3Chat.java:44)
    at net.minecraft.server.NetworkManager.b(NetworkManager.java:290)
    at net.minecraft.server.NetServerHandler.d(NetServerHandler.java:113)
    at net.minecraft.server.ServerConnection.b(SourceFile:39)
    at net.minecraft.server.DedicatedServerConnection.b(SourceFile:30)
    at net.minecraft.server.MinecraftServer.r(MinecraftServer.java:595)
    at net.minecraft.server.DedicatedServer.r(DedicatedServer.java:222)
    at net.minecraft.server.MinecraftServer.q(MinecraftServer.java:493)
    at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:426)
    at net.minecraft.server.ThreadServerApplication.run(SourceFile:856)
    Caused by: java.lang.NoClassDefFoundError: com/stirante/PrettyScaryLib/Namer
    at com.gmail.david.anekin.rosales.KhSkills.KhSkills.onCommand(KhSkills.java:1822)
    at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44)
    ... 15 more

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 29, 2016
  25. Offline

    Jogy34

    You are trying to call on this class: com/stirante/PrettyScaryLib/Namer

    Which it can't find.
     
  26. Offline

    fireblast709

    Code:java
    1. public NBTTagList getLore(ItemStack i)
    2. {
    3. net.minecraft.server.ItemStack nms = ((CraftItemStack)i).getHandle();
    4. NBTTagCompound tag = nms.getTag()
    5. if (!tag.hasKey("display"))
    6. {
    7. return new NBTTagList();
    8. }
    9. NBTTagCompound display = (NBTTagCompound)tag.get("display");
    10. NBTTagList lore = display.getList("Lore");
    11. if (lore == null)
    12. {
    13. // returns empty list
    14. return new NBTTagList();
    15. }
    16. return lore;
    17. }
    18.  
    19. public void setLore(String lore, ItemStack i)
    20. {
    21. net.minecraft.server.ItemStack nms = ((CraftItemStack)i).getHandle();
    22. NBTTagCompound tag = nms.getTag()
    23. if (!tag.hasKey("display"))
    24. {
    25. this.addDisplay();
    26. }
    27. NBTTagCompound display = this.getDisplay();
    28. NBTTagList l = new NBTTagList();
    29. // Added multiline lore support
    30. // Splits the lines
    31. String[] loreLines = lore.split("\n");
    32. // Add each line
    33. for(String line : loreLines)
    34. {
    35. l.add(new NBTTagString("", line));
    36. }
    37. // Set the lore
    38. display.set("Lore", l);
    39. }
     
  27. Offline

    Jogy34

    ???
     
  28. Offline

    fireblast709

    Jogy34 david_rosales was getting errors right? To make it easy for him I just posted 2 methods that take care of the lore without any other libraries or code using methods from other plugins

    david_rosales Name would kinda be the same, except for the fact that you set a NBTTagString instead of a NBTTagList
     
Thread Status:
Not open for further replies.

Share This Page