SpigotMC/Spigot-API — pull request #17 by NathanWolf (2014-09-02 20:12:08+00:00)
Title: [B+C] Add ItemMeta.hasCustomData/getCustomData. Adds BUKKIT-3221  

## Spigot PR

This is my first time trying to submit a Spigot PR. I wasn't sure if this would work, or if I need to update patches and submit a PR against Spigot- please let me know!

This PR is a copy of one that has been sitting around in Bukkit for a while (but which got a lot of positive attention):

https://github.com/Bukkit/Bukkit/pull/1064

## The Issue

There is currently no API method to track an ItemStack through its lifecycle for the purpose of creating a custom item.

## Justification for this PR

The ability to create custom items by tagging them with arbitrary data could add lot of depth to what Plugin developers are able to offer.

There are various methods employed to accomplish this (protocol hacking, direct NBT editing, name/lore data storage) but they all have downsides and don't interact well with each other or the API.

The item "glow" API requested by BUKKIT-4767 is also added here, it was a very clean and easy fit into the metadata framework provided by the bulk of this PR, and will hopefully make testing all of this in conjunction easier.

This PR provides also provides a mechanism to store unknown or custom NBT data on items, which may be important given the addition of custom item data in 1.8.

## PR Breakdown

### Bukkit

The ItemMeta interface now extends Metadatable. This is a different kind of persistent metadata store that can not store arbitrary Object instances. I wanted to make that clear and hopefully avoid confusion, so I made a new PersistentMetadataValue type that must be used when storing custom item data.

Basic types, Lists and Maps can be stored, as can ConfigurationSerializeable objects.

ItemStack also contains two "hasMetadata" methods which can be used to do efficient first-pass checks for custom data without the expense of unpacking the ItemMeta structure.

### CraftBukkit

Custom data will be stored in a "bukkit" NBT tag on the NMS ItemStack. This is an implementation detail that could change in the future, but at present is the easiest and safest method for storing relatively small amounts of structured data on an item.

The "bukkit" tag itself is reserved for internal Bukkit use. This PR also implements the item "glow" API requested by BUKKIT-4767, using a custom "bukkit.glow" flag to maintain state independently of enchantments.

Custom Plugin metadata is stored in "bukkit.plugins..". No effort is made to preserve data attached to items that is registered to an unloaded plugin.

## Testing Results and Materials

A JUnit test is provided in the CB PR which attempts to exercise the API as much as possible. There is also a plugin that can be used for testing, available here:

https://github.com/NathanWolf/Test-ItemMetaData/tree/Metadatable
http://mine.elmakers.com/Test-ItemMetaData.jar

This plugin has several commands available for adding custom data, testing with enchants, glow effect, and checking for data.

### Plugin Commands

*All of the following must be used in-game.*

invpush: Push your entire inventory into a serialized stack. Useful for testing item serialization.
invpop: Pop your stored inventory off the stack. Will drop any items you have to the ground.

*All of the following must be used while holding an item*

itemcheck: Display information about an item, including any custom data
itemclone: Make a copy of an item
itemunenchant: Remove all enchantments from an item
itemfly: Tag an item with some special data that also makes you fly when you swing it
itemunfly: Remove the special testing/fly data.
itemglow: Make an item glow
itemunglow: Make an item not glow, unless it's enchanted

After you've used /itemfly, the item will have its custom data updated each time you swing it. Use /itemcheck to verify the data is getting updated properly.

## Relevant PR(s)

B-1053 : https://github.com/Bukkit/Bukkit/pull/1053 - @Ribesg 's glow API
CB-1376: https://github.com/Bukkit/CraftBukkit/pull/1376 - Associated CB PR

## JIRA Ticket
https://bukkit.atlassian.net/browse/BUKKIT-3221
Also resolves these tickets:
https://bukkit.atlassian.net/browse/BUKKIT-4864
https://bukkit.atlassian.net/browse/BUKKIT-4767