Skip to content

Latest commit

 

History

History
263 lines (194 loc) · 7.68 KB

File metadata and controls

263 lines (194 loc) · 7.68 KB

Persistent Data Container (PDC) API Documentation

The PDC API allows Lua scripts to read and write persistent data on ItemStacks, entities, and tile-entity blocks using Paper's PersistentDataContainer system.

Global Access

The API is accessed via the global PdcApi table in Lua scripts.

Supported Holders

PdcApi can attach data to the following objects:

  • ItemStack — data is stored on the item's ItemMeta
  • Entity / Player — data is stored on the entity itself
  • Block — if it is a tile entity (e.g. CHEST, FURNACE, SIGN), the block state is used and updated automatically
  • TileState — direct tile state snapshots; changes are persisted with BlockState.update()
  • Any other PersistentDataHolder

Note: Block support requires the block to be a tile entity. Non-tile blocks (dirt, stone, etc.) have no PDC and will produce a warning.

Supported Types

The type argument for get, set, and has is case-insensitive and supports the following aliases:

Type Aliases Lua Value Notes
byte byte, boolean, bool number / boolean Booleans are stored as 0/1 bytes
short short number
int int, integer number
long long number
float float number
double double number
string string string
bytearray bytearray table (1-indexed) Values outside [-128, 127] are clamped
intarray intarray, integerarray table (1-indexed)
longarray longarray table (1-indexed)
tagcontainer tagcontainer, container PDC userdata Obtained from PdcApi:getContainer or PdcApi:get
tagcontainerarray tagcontainerarray, containerarray table of PDC userdata No nil elements allowed

Keys

Keys are Minecraft NamespacedKeys. You can use them in two forms:

  • namespace:key — e.g. myplugin:counter
  • key — uses the plugin's namespace automatically

Invalid or empty keys log a warning and return nil.

Methods

has

Checks whether a key of a specific type exists on the holder.

Syntax:

local exists = PdcApi:has(holder, key, type)

Parameters:

  • holder (ItemStack, Entity, Player, Block, TileState, or PersistentDataHolder)
  • key (string): the PDC key
  • type (string): the PDC type

Returns:

  • exists (boolean): true if the key exists with the specified type, false or nil otherwise

Example:

if PdcApi:has(item, "myplugin:owner", "string") then
    DebugApi:log("Item has an owner")
end

get

Reads a value from the holder's PDC.

Syntax:

local value = PdcApi:get(holder, key, type)

Parameters:

  • holder (ItemStack, Entity, Player, Block, TileState, or PersistentDataHolder)
  • key (string): the PDC key
  • type (string): the PDC type

Returns:

  • value: the stored value, or nil if the key does not exist or the type does not match. Arrays are returned as Lua tables with 1-based indexing.

Example:

local owner = PdcApi:get(item, "myplugin:owner", "string")
if owner then
    DebugApi:log("Owner: " .. owner)
end

set

Stores a value in the holder's PDC.

Syntax:

local success = PdcApi:set(holder, key, type, value)

Parameters:

  • holder (ItemStack, Entity, Player, Block, TileState, or PersistentDataHolder)
  • key (string): the PDC key
  • type (string): the PDC type
  • value: the value to store (must match the type)

Returns:

  • success (boolean): true if the value was stored, false or nil otherwise

Example:

PdcApi:set(item, "myplugin:owner", "string", "Steve")
PdcApi:set(item, "myplugin:damage", "int", 15)
PdcApi:set(item, "myplugin:tags", "bytearray", {1, 2, 3})

remove

Removes a key from the holder's PDC.

Syntax:

local success = PdcApi:remove(holder, key)

Parameters:

  • holder (ItemStack, Entity, Player, Block, TileState, or PersistentDataHolder)
  • key (string): the PDC key to remove

Returns:

  • success (boolean): true if the mutation was applied, false or nil otherwise

Example:

PdcApi:remove(item, "myplugin:owner")

getKeys

Returns all keys stored on the holder.

Syntax:

local keys = PdcApi:getKeys(holder)

Parameters:

  • holder (ItemStack, Entity, Player, Block, TileState, or PersistentDataHolder)

Returns:

  • keys (table): a 1-indexed Lua table of key strings, or nil on error

Example:

local keys = PdcApi:getKeys(item)
for i, key in ipairs(keys) do
    DebugApi:log("Key " .. i .. ": " .. key)
end

getContainer

Returns the raw PersistentDataContainer for the holder. This is useful when you want to store a container inside another container.

Syntax:

local container = PdcApi:getContainer(holder)

Parameters:

  • holder (ItemStack, Entity, Player, Block, TileState, or PersistentDataHolder)

Returns:

  • container (userdata): the PersistentDataContainer, or nil on error

Notes:

  • For ItemStack and Block, the returned container is from a snapshot of the holder's state. Direct mutations to that container alone will not persist back to the item or block; use PdcApi:set or PdcApi:remove on the original holder instead.
  • For Entity/Player and other live PersistentDataHolders, the returned container is the live container.

Example:

-- Get a container from one item and embed it in another
local container = PdcApi:getContainer(item)
PdcApi:set(otherItem, "myplugin:embedded", "tagcontainer", container)

Usage Examples

Tag an item with its owner

registerCommand("tagitem", "myplugin.tagitem", function(sender, args)
    local player = castTo(sender, "org.bukkit.entity.Player")
    if player == nil then return end
    local item = player:getInventory():getItemInMainHand()
    if item == nil or item:getType():isAir() then
        DebugApi:error("Hold an item first")
        return
    end
    PdcApi:set(item, "myplugin:owner", "string", player:getName())
    DebugApi:log("Item tagged")
end)

Store numeric stats on a player

PdcApi:set(player, "myplugin:kills", "int", 42)
PdcApi:set(player, "myplugin:ratio", "double", 1.25)

local kills = PdcApi:get(player, "myplugin:kills", "int")
DebugApi:log("Kills: " .. kills)

Store data on a chest block

local loc = player:getLocation()
loc:setY(loc:getY() - 1)
local block = WorldApi:getBlock(loc)
if block then
    PdcApi:set(block, "myplugin:claimed", "boolean", true)
end

Nested container (sub-data)

-- Build a nested container from the item's PDC snapshot and store it inside the item.
-- Note: getContainer(item) returns a snapshot; build the sub-container data
-- and then use PdcApi:set on the original item to persist it.
local subContainer = PdcApi:getContainer(item)
PdcApi:set(subContainer, "sub:key", "string", "nested value")
PdcApi:set(item, "myplugin:sub", "tagcontainer", subContainer)

Notes

  • ItemStack PDC operations require a non-air item with valid ItemMeta
  • Block PDC operations only work on tile entities and call BlockState.update() automatically
  • byte values and bytearray elements are clamped to the [-128, 127] range; out-of-range values log a warning
  • short values are clamped to the [-32768, 32767] range
  • For the boolean/bool type, set uses Lua truthiness: only false and nil are stored as 0; all other values (including 0 and empty strings) are stored as 1
  • Array types with missing indices treat nil entries as 0 and log a warning
  • get, set, has, and remove return nil on invalid input or unsupported holders