Item Data
The item package stores small, typed values directly on an ItemStack β the item-level
counterpart to the player-record storage/database layers. Reach for it when state belongs to a
specific item rather than a player or the world: durability counters, ownership tags, upgrade
levels, kill/usage trackers.
ItemDataStore interface
Section titled βItemDataStore interfaceβpublic interface ItemDataStore { int getInt(ItemStack item, String key); ItemStack setInt(ItemStack item, String key, int value); String getString(ItemStack item, String key); ItemStack setString(ItemStack item, String key, String value); boolean hasKey(ItemStack item, String key); ItemStack removeKey(ItemStack item, String key); Set<String> keys(ItemStack item);}ItemStacks are value types, so every mutating method returns the updated stack β always use
the return value, never assume the argument was modified in place:
item = data.setInt(item, "kills", data.getInt(item, "kills") + 1);player.getInventory().setItemInMainHand(item);PdcItemDataStore (default)
Section titled βPdcItemDataStore (default)βNative, dependency-free implementation backed by the Bukkit PersistentDataContainer. Keys are
namespaced to the owning plugin (so they never clash with vanilla NBT or other plugins) and
lower-cased to satisfy NamespacedKeyβs charset.
ItemDataStore data = new PdcItemDataStore(plugin);
ItemStack sword = new ItemStack(Material.DIAMOND_SWORD);sword = data.setInt(sword, "kills", 0);
boolean tracked = data.hasKey(sword, "kills"); // trueint kills = data.getInt(sword, "kills"); // 0This is the recommended default and is fully unit-testable under MockBukkit.
NbtApiItemDataStore
Section titled βNbtApiItemDataStoreβBacked by NBTAPI, writing raw, case-sensitive NBT root
tags. Choose it only when you must read or preserve an existing item format β for example items
tagged Playerkills / StatTag that predate the persistent data container, or tags shared with
another plugin.
ItemDataStore data = new NbtApiItemDataStore();sword = data.setInt(sword, "Playerkills", 0); // raw tag, exact casing preservedRequirements and caveats:
- Add the NBTAPI plugin as a dependency in
plugin.yml:depend: [NBTAPI](orsoftdepend). - The framework compiles against NBTAPI with
providedscope β the server supplies the plugin. - NBTAPI resolves NMS at runtime, so it cannot run under MockBukkit. Cover your calling logic
against
PdcItemDataStore(same interface) and verify the NBTAPI path on a live server.
Choosing an implementation
Section titled βChoosing an implementationβ| Scenario | Use |
|---|---|
| New plugin, no legacy format | PdcItemDataStore |
| Must read/preserve existing raw NBT tags (legacy or cross-plugin) | NbtApiItemDataStore |
| You want testable logic | Code against ItemDataStore; inject PdcItemDataStore in tests |
Because callers depend on the ItemDataStore interface, you can swap the backend without touching
business logic β the recommended pattern is to inject the store and pass PdcItemDataStore from
unit tests while wiring NbtApiItemDataStore in production.