How to apply AttributeModifier to ItemStack?

Discussion in 'Spigot Plugin Development' started by BlackBeltPanda, Apr 19, 2017.

  1. Unfortunately there's no API for using attributes with items (yet?), only entities. So none of that code is going to be really useful for this purpose.

    You'll have to use NMS code to add the attributes as NBT tags directly.

    There is this weird issue of the UUIDs associated with them- the MC docs seem to imply that there are fixed UUIDs for certain attributes under certain situations, but I've never found a clear answer as to what they're for (other than, I think, dealing with attribute stacking in some specific ways) or if it would be bad to just use a random one each time.

    See here for more info:

    http://minecraft.gamepedia.com/Attribute

    And here is a snippet of code I use to show you what the full attribute node would look like:

    Code (Text):

                Object attributesNode = getNode(tag, "AttributeModifiers");
                // .. some code here where I check to see if the attribute already exists on the item
                if (attributeNode == null) {
                    attributeNode = class_NBTTagCompound.newInstance();
                    setMeta(attributeNode, "AttributeName", attributeName);
                    setMeta(attributeNode, "Name", "Equipment Modifier");
                    setMetaInt(attributeNode, "Operation", attributeOperation);
                    setMetaLong(attributeNode, "UUIDMost", attributeUUID.getMostSignificantBits());
                    setMetaLong(attributeNode, "UUIDLeast", attributeUUID.getLeastSignificantBits());
                    if (slot != null) {
                        setMeta(attributeNode, "Slot", slot);
                    }

                    class_NBTTagList_addMethod.invoke(attributesNode, attributeNode);
                }
                setMetaDouble(attributeNode, "Amount", value);
    Or, if you want to just see what an item with attributes looks like, you can set up the tags like so:

    [​IMG]
     
    • Informative Informative x 1
    • Useful Useful x 1
  2. Thanks for the info. =)
    Playing around with it a bit, it seems if you have armor, for example, that has the same UUID, only the modifiers from one of them will work. So you need different UUIDs if you want the modifiers from all armor pieces worn to take affect.

    Since I'm already using PowerNBT for some things, I'm going to see if I can apply the attribute modifiers with it's API. At the very least, I think I can create the items in-game with commands and use PowerNBT to copy the NBT from them to create the ItemStack I need.
     
  3. Choco

    Moderator

    *yet
    @Senmori is working on a PR for ItemStack attributes :)
     
    • Like Like x 3
    • Optimistic Optimistic x 1
  4. Senmori

    Senmori Retired Resource Staff
    Retired Patron

    If you aren't scared of NMS you can add AttributeModifiers without resorting to directly applying any NBT data.
    Code (Java):
    public void a(String attributeName, AttributeModifier modifier, EnumItemSlot slot)
    attributeName is the default Minecraft attribute name. (generic.armor, generic.movementSpeed, etc.)
    modifier is the Minecraft version of the AttributeModifier. The constructor for that is:
    Code (Java):
    public AttributeModifier(String var1, double var2, int var4)
    Where var1 is the name of this modifier(this does not have to be the attribute name).
    var2 is the amount of this modifier.
    var4 is the Operation. You can use Bukkit's AttributeModifier.Operation.ordinal() to get the operation you want.

    And finally, the EnumItemSlot. You don't require this but it's obviously very useful. The enum is self-explanatory, but if you don't include this(i.e. pass in null), the AttributeModifier will be active in ALL slots.

    So yeah, fairly easy to add AttributeModifiers without resorting to directly applying NBT. :)

    Also, if you want to get all the AttributeModifiers there's a method for that as well.
    Code (Java):
    public Multimap<String,AttributeModifier> a(EnumItemSlot slot)
    EnumItemSlot cannot be null in this method. This will return any AttributeModifier if it's slot is null, or if the slot matches the one you passed in AND the UUID is not equal to 0.
     
    • Informative Informative x 1
  5. Thanks for the info. =)
    Is there an advantage to doing this over NBT? I'm already using PowerNBT's API for some stuff so if it's just a matter of not needing to use NBT, I'll probably just use PowerNBT for this, as well.
     
  6. Senmori

    Senmori Retired Resource Staff
    Retired Patron

    @BlackBeltPanda I haven't used PowerNBT in a long time, but there shouldn't be a major difference. Either way the NBT is being set.
     
    • Informative Informative x 1