Bukkit/CraftBukkit — pull request #1376 by NathanWolf (2014-05-14 20:11:43+00:00)
Title: [B+C] Add ItemMeta.hasCustomData/getCustomData. Adds BUKKIT-3221

## 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.

## PR Breakdown

### Bukkit

Added hasCustomData and getCustomData methods to ItemMeta. The getCustomData method returns a ConfigurationSection object that may be used to interrogate or modify any custom data present on the item.

I chose to return a live reference to the data to avoid the overhead of copying and converting a potentially large tree structure back and forth between a get and set call.

Basic types, Lists and Arrays can be stored, as can ConfigurationSerializeable objects. Maps cannot be stored directly, though you can create sub-sections as needed or wrap a Map in a serializable object.

### CraftBukkit

Custom data is stored alongside well-known data in the ItemStack's NBT tag root. This has the added benefit of functioning as a data preservation mechanism for unknown data (such as between Minecraft updates).

Only data that is not already accounted for via a registered ItemMetaKey will be presented as custom data. Otherwise the meta object will only contain an additional empty reference to a new CraftMetaItemData object which manages the custom data.

Trying to override well-known data tags via the custom data API will be rejected, as will trying to store any non-serializeable objects.

## 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/NoGlow
http://mine.elmakers.com/Test-ItemMetaData.jar

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

The test plugin was also originally set up to test item glow/unglow, but I removed that from this PR. The glow and custom data changes should probably be tested in conjunction and may not merge well together (see CraftMetaItem::isEmpty), but I'm going to let @Ribesg handle the glow API.

I would be more than happy to restore the glow functionality of the test plugin if the Glow API PR gets accepted before this one does.

### 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.

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.

*Currently Disabled*

itemglow: Make an item glow
itemunglow: Make an item not glow, unless it's enchanted

## Relevant PR(s)

CB-1363 : https://github.com/Bukkit/CraftBukkit/pull/1363 - @Robesg's glow implementation
B-1064: https://github.com/Bukkit/Bukkit/pull/1064 - Associated Bukkit PR

## JIRA Ticket
https://bukkit.atlassian.net/browse/BUKKIT-3221
Also resolves this one:
https://bukkit.atlassian.net/browse/BUKKIT-4864