Published on

[Minecraft Plugin] How to store data in itemstacks?

Authors

Click HERE to directly see the code.

Recently when I was writing a plugin, I came across a problem. That is, how to store data in itemstack?

The plugin can enable players to store coordinates in a library. After that, other players can open a menu to browse the coordinates, all presented as a paper icon and can be clicked to perform some actions. Since the plugin needs to know which one the player has clicked, we must put some information in every paper item.

At first, I put information(ID of every coordinate, like #00000000) in the item's lore. However, there is a drawback to doing so: players opening the menu can see the ID. Although it is not a severe problem, I still think it is not a good solution. However, after searching for documents and information, I reach the solution.

PersistentDataContainer

From version 1.14, the class ItemMeta begins to extend class PersistentDataHolder. PersistentDataHolder is the key for us to store data in ItemMeta. PersistentDataHolder needs to implement a method like this getPersistentDataContainer(), which will return a custom tag container capable of storing tags on the object when it is invoked.

First, you need to get the ItemMeta, in the following way:

// item is an object of class Itemstack
ItemMeta meta = item.getItemMeta();

Then you can get the PersistentDataContainer of the ItemMeta:

PersistentDataContainer dataContainer = meta.getPersistentDataContainer();

Now, the dataContainer can be used to store data in the item.

dataContainer.set(
    org.bukkit.NamespacedKey key,
    org.bukkit.persistence.PersistentDataType<T, Z> type,
    Z value
);

Let me explain the method. The explanation in API document writes this:

Stores a metadata value on the PersistentDataHolder instance. This API cannot be used to manipulate minecraft data, as the values will be stored using your namespace. This method will override any existing value the PersistentDataHolder may have stored under the provided key.

paramsdescription
keyTo indicate the position you will store the data.
typeThe type of the data to be stored.
valueThe data you want to store.

key

It is made up of two parts:

  • namespace
  • path

It should be like this: namespace:path.

namespace and path can both contain these characters:

  • 0123456789 Numbers
  • abcdefghijklmnopqrstuvwxyz Lowercase letters
  • _ Underscore
  • - Hyphen/minus
  • . Dot

The following characters are illegal in the namespace, but acceptable in the path:

  • / Forward slash (directory separator)

The information above is picked from minecraft wiki

type

The type can be one of the following:

- PersistentDataType.STRING
- PersistentDataType.BOOLEAN
- PersistentDataType.BYTE
- PersistentDataType.DOUBLE
- PersistentDataType.BYTE_ARRAY
- PersistentDataType.FLOAT
- PersistentDataType.INTEGER
- PersistentDataType.INTEGER_ARRAY
- PersistentDataType.LONG
- PersistentDataType.LONG_ARRAY
- PersistentDataType.SHORT
- PersistentDataType.TAG_CONTAINER
- PersistentDataType.TAG_CONTAINER_ARRAY

value

It is what you want to store.

Summary

Now, you can write the following code:

// item is an object of class Itemstack
ItemMeta meta = item.getItemMeta();
PersistentDataContainer dataContainer = meta.getPersistentDataContainer();
// I use my code as an example
dataContainer.set(NamespacedKey.fromString("com.adyingdeath.coordinateslibrary:coord_id"), PersistentDataType.STRING, coordinate.getId());

The code above store a STRING data into the item. You can later get the data in the item somewhere else, like in a click event.

// event is an object of class InventoryClickEvent.
// Get the ID stored in the item clicked
String id = event.getCurrentItem().getItemMeta().getPersistentDataContainer().get(NamespacedKey.fromString("com.adyingdeath.coordinateslibrary:coord_id"), PersistentDataType.STRING);

Actually, in this way, not only can we store data in item, but also we can store data in other objects. You can check PaperMC API for more information.