[Library] Edit or create NBT tags with a compact class - no OBC/NMS

Discussion in 'Resources' started by Comphenix, Sep 29, 2013.

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

    pokuit

    Comphenix Thanks for the help, though I want to do it without using OBC
     
  2. Offline

    gabizou

    So with this, I could create new custom data my other plugins would need stored on items and the custom tag data would be stored to disk no problem, no deletion issues etc.? Just trying to see if the AttributeStorage is indeed able to allow the creation, reading, storing, and modification of custom attributes that the client would NOT see.

    I've been really interested in getting custom fields to be stored to items for some time, and only now getting around to writing in to some plugins to get it working ;)
     
  3. Offline

    Comphenix

    It will be persisted to disk as often and safely as the item stack itself. It just becomes part of its data.

    Unfortunately - as I mention here - the attribute will be transmitted to the client that is viewing the item stack, and be displayed as an empty line. You can hide it with ProtocolLib or ItemRenamer.
     
  4. Offline

    L33m4n123

    First off all. Great work.

    However I run into a small problem I cannot seem to figure out [could be that I need sleep.. lol]

    What I try to do is adding some custom NBT tags to a potion and when the player consumes it it works with that. So. At least according to some debug messages the first part works

    Code:java
    1. // Above here I get the Display Name and Lore from the Item they clicked on in the inventory. Works
    2. ItemStack stack = NbtFactory.getCraftItemStack(new ItemStack(Material.POTION));
    3. ItemMeta stackMeta = e.getCurrentItem().getItemMeta();
    4. stack.setItemMeta(stackMeta);
    5. NbtFactory.NbtCompound other = NbtFactory.fromItemTag(stack);
    6.  
    7. // Add some stuff
    8. other.put("TestWorks", "yes");
    9. other.put("AwwIAmTired", "Go to sleep");
    10. //Debug messages
    11. System.out.println(other.getString("TestWorks", "no");
    12. System.out.println(other.getString("AwwIAmTired", "No I am not");
    13. p.getInventory().addItem(stack);


    So. The messages print out what they should.

    Now getting the Item in the consume event to print out messages I did following

    Code:java
    1. if (e.getItem().hasItemMeta()) {
    2. NbtFactory.NbtCompound other = NbtFactory.fromItemTag(e.getItem());


    then I got the stacktrace that the ItemStack needs to be a CraftItemStack so I changed it to

    Code:java
    1. if (e.getItem().hasItemMeta()) {
    2. ItemStack tempStack = NbtFactory.getCraftItemStack(e.getItem());
    3. NbtFactory.NbtCompound other = NbtFactory.fromItemTag(tempStack);


    and when I then print out the debug messages I had above it prints out "no" and "No I am not"

    So I think I somehow have to add to the itemStack that I add to the players Inventory those NBT-Tags that I defined already here
    Show Spoiler
    Code:java
    1. // Above here I get the Display Name and Lore from the Item they clicked on in the inventory. Works
    2. ItemStack stack = NbtFactory.getCraftItemStack(new ItemStack(Material.POTION));
    3. ItemMeta stackMeta = e.getCurrentItem().getItemMeta();
    4. stack.setItemMeta(stackMeta);
    5. NbtFactory.NbtCompound other = NbtFactory.fromItemTag(stack);
    6.  
    7. // Add some stuff
    8. other.put("TestWorks", "yes");
    9. other.put("AwwIAmTired", "Go to sleep");
    10. //Debug messages
    11. System.out.println(other.getString("TestWorks", "no");
    12. System.out.println(other.getString("AwwIAmTired", "No I am not");
    13. p.getInventory().addItem(stack);


    But either I am blind / doing something horribly wrong.. but I cannot figure it out. Any help appreciated
     
  5. Offline

    Comphenix

    You cannot safely store arbitrary NBT tags in an ItemStack, as Bukkit will automatically remove unrecognized tags whenever it clones a stack (which is often, especially on creative mode) or a plugin uses ItemMeta.

    Instead, try storing arbitrary data in the name of dummy attributes, using a unique UUID.
     
  6. Offline

    L33m4n123


    Oh ok. Thanks will give it a shot
     
  7. Offline

    desht

    I can confirm that this approach works very nicely; my next (unreleased) plugin will be making very extensive use of this feature :) Arbitrarily tagged items open up a host of possibilities...
     
    Comphenix likes this.
  8. Offline

    L33m4n123


    Yupp can confirm it aswell. First of all. Due to his Util-Classes it's superb easy to use. And it's SO usefull. Comphenix thanks for that :)
     
  9. Offline

    desht

  10. Offline

    Comphenix

    desht likes this.

  11. Hey, I just copying the NbtFactory class into my project but I'm getting some errors. Getting errors on lines 444, 446, 472 & 474, it says the method Closeable.closeQuietly(InputStream) couldn't be found. For me, the class closeables only contains one method, close.

    It would be great if you could look into this, thanks!
     
  12. Offline

    Comphenix

    Really? Are you compiling against a recent version of Bukkit? And have you imported the correct Closeables:
    Code:java
    1. import com.google.common.io.Closeables;
     
    TigerHix likes this.
  13. Using the latest version of a certain popular fork of CraftBukkit, maybe they use a different version?
     
  14. Offline

    TigerHix

    Comphenix

    I found an interesting bug. When PlayerInteractEvent happens, I will check if the event item is actually stored in AttributeStorage, using method below:

    Code:java
    1. protected boolean correct(ItemStack item) {
    2. if (handler == null) return false;
    3. if (item == null || item.getTypeId() <= 0) return false;
    4. if (AttributeStorage.newTarget(item).getData(null) == null) return false;
    5. return true;
    6. }


    But the line, AttributeStorage.newTarget(item).getData(null) == null brings unexpected result. If a player use a diamond sword to attack, first the diamond sword deals 8.0 damage, but after that the diamond sword will only deal 1.0 damage. If I remove this line, everything goes well.

    Sounds like the most confusing bug to me. o_0
     
    Comphenix likes this.
  15. Offline

    TigerHix

    Comphenix Could you help please? Stuck with this bug for awhile. :(
     
  16. Offline

    Comphenix

    Looks like this affects any sword or axe that is the target of attribute storage. Apparently, the default attack strength is lost whenever you apply a custom attribute list to an item stack, regardless of the type of the attributes in the list. I can't use ADD_PERCENTAGE or MULTIPLY_PERCENTAGE either, as the base damage is reset to zero.

    So - looks like I have to hard code this damage in AttributeStorage. In addition, it's probably best to only create an attribute list when we explicitly add attributes, not when we're merely reading the attribute list (like in getData()).

    You can get the updated version on GitHub:
    https://github.com/aadnk/AttributeStorage
     
    TigerHix likes this.
  17. Offline

    TigerHix

    Wow, thx so much for answering :D Finally can resolve some affections due to this.

    Sorry if you felt disturbed. <3
     
  18. Offline

    Comphenix

    Ah, I think I see what's going on. The Bukkit fork you're using has probably upgraded Guava from version 10 (in Bukkit) to version 16.

    In that case, I'll just switch to using Closeables.close(). It's more correct in any case.

    Oh, I don't mind.

    In fact, I reckon this issue has probably affected many other people, but for one reason or another decided not to contact me (might have figured it out, or not known the source, or not cared enough). So - getting it fixed may end up helping a lot of people. :)
     
    iKeirNez and TigerHix like this.
  19. Offline

    desht

    Working nicely, thanks :) (Using your latest version with Closeables.close())

    I noticed that a Java 7 compiler is required for this (due to the use of Collections.emptyIterator()) - probably not a big deal these days, so more of an FYI to anyone who hits a compilation problem with that.

    Any chance of making the AttributeStorage classes available via your Maven repo so they can be shaded into plugins?
     
    iKeirNez and TigerHix like this.
  20. Thanks, much appreciated!
    I second the Maven repo, would help to automate things a bit more
     
  21. Offline

    Comphenix

    Hm - sure, I suppose it wouldn't hurt.

    I'll add it to my main repository, and my Jenkins server (which has a backup repository).
     
    iKeirNez and desht like this.
  22. Offline

    tehface

    Comphenix
    Does nbtfactory work with 1.7.10 ?

    thnx
     
  23. Offline

    uksspy

    Is it possible to apply the "Unbreakable" tag to an item using this library? I tried
    Code:java
    1. NbtCompound compound = NbtFactory.fromItemTag(NbtFactory.getCraftItemStack(item));
    2. compound.put("Unbreakable", 1);

    but that didn't work.
     
  24. Offline

    StaticJava

    I'm using the updated version of this library (https://github.com/aadnk/AttributeStorage) and have a question:

    Do all tag compounds have to be manually set using the putPath() method, or will constructing a new NbtCompound from an ItemStack automatically grab all of its tags and save them in the Map<String, Object>?

    This is my current code I'm trying to use: http://pastebin.com/nbPRgABd

    However, when calling this method, I get this error: http://pastebin.com/igrP9nMi

    Am I doing something incorrectly?

    Thanks,
    StaticJava
     
  25. Offline

    T0pAz7

    Any update to this?
     
  26. Offline

    Zettelkasten

    @Comphenix Even though this thread is quite old now, I got a question: How would you go for changing NBT-data on blocks using your class? It is really great and straight-forward, good job and thanks for making this!

    Edit: Actually, I would need tile entities.
     
    Last edited: Jan 25, 2015
Thread Status:
Not open for further replies.

Share This Page