[Minecraft Plugin] How to store data in itemstacks?

[Minecraft Plugin] How to store data in itemstacks?

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.

params description
key To indicate the position you will store the data.
type The type of the data to be stored.
value The 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.

Read more

我的世界指令:检测玩家y值是否低于指定值

我的世界指令:检测玩家y值是否低于指定值

以下内容仅在Java版中有效 在我的世界中,我们有时候有一个需求,即检测玩家的y坐标是否低于(或高于)给定值,该怎么做呢? 目录 * 方案一:“无限大”长方体 * 方案二:跟随玩家的长方体 * 只要命令,不想看文章?快捷跳转到命令 第一时间我们应该会想到用目标选择器来完成这个操作,我从wiki中截了一段有关目标选择器中坐标参数的描述。 坐标(x、y、z): [x=<值>,y=<值>,z=<值>] — 在世界中定义一个位置。 这个位置将成为目标选择器执行位置(不修改命令执行位置),这意味着@p所选择的目标可能发生改变。 如果其中任意参数未定义,则默认使用命令执行位置的坐标。 可用于distance参数或dx、dy和dz参数,以平移选择范围。 坐标可以是整数或像12.34这样的小数(具体为双精度浮点数)且不会进行中心校正(center-corrected),这意味着x=

By adyingdeath