DUXPLIMA Documentation

Persistent data

Typed PDC access, boolean flags, UUID storage, single-key similarity and blocking item actions.

Persistent data containers are how an item carries plugin state. The API is verbose enough that most code wraps it; this is that wrapper.

Reading and writing

Pdc.set(item, key, PersistentDataType.STRING, "value");

Pdc.has(item, key, PersistentDataType.STRING);
Optional<String> value = Pdc.get(item, key, PersistentDataType.STRING);
String orDefault = Pdc.getOrDefault(item, key, PersistentDataType.STRING, "none");

For several reads off one item, take a reader once rather than opening the container per call:

Pdc.PdcReader reader = Pdc.read(item);

reader.has(key, PersistentDataType.STRING);
reader.get(key, PersistentDataType.INTEGER);
reader.getOrDefault("owner", UuidArrayType.INSTANCE, fallback);

Items.editPdc(item, pdc -> ...) is the raw form when you need the container itself.

Boolean flags

A flag has no natural persistent type, so it ends up as a byte everybody encodes differently.

PdcFlag.set(pdc, key, true);
PdcFlag.get(view, key);
PdcFlag.getOrDefault(view, key, false);
PdcFlag.has(view, key);
PdcFlag.remove(pdc, key);

UUIDs

Pdc.set(item, ownerKey, UuidArrayType.INSTANCE, player.getUniqueId());

int[] raw = UuidArrayType.toIntArray(uuid);
UUID back = UuidArrayType.fromIntArray(raw);

Stored as an int array, which is compact and matches how Minecraft itself stores UUIDs in NBT.

Single-key similarity

ItemStack.isSimilar compares everything. Often you only care whether two items carry the same plugin identity, and not whether their lore or durability match.

boolean sameToken = Items.isSimilar(a, b, tokenKey, PersistentDataType.STRING);

This is what makes a custom currency stack correctly when one copy has been renamed, or a quest item match after its lore was regenerated.

Blocking item actions

Some items should not be craftable, edible, placeable or droppable. Stamp the item once and the listener enforces it.

ItemBlockerType.block(item, ItemAction.CRAFT, ItemAction.DROP);
ItemBlockerType.block(item, Set.of(ItemAction.CONSUME));

ItemBlockerType.isBlocked(item, ItemAction.DROP);
Set<ItemAction> blocked = ItemBlockerType.blockedActions(view);

Register the listener once:

Bukkit.getPluginManager().registerEvents(new ItemActionListener(), plugin);
ActionEvent cancelled
CRAFTPrepareItemCraftEvent, the result is suppressed
CONSUMEPlayerItemConsumeEvent
PLACEBlockPlaceEvent
DROPPlayerDropItemEvent

Each action has a stable string id written into the item's data, never the enum name, so the enum can be reordered or extended without invalidating items already stamped. The key is uxmlib:blocked_actions.