Skip to content

PDC

PDC means Bukkit PersistentDataContainer. CoreLib uses it to store structured module state on items, block states, and other persistent holders. EmakiCooking now prefers block-entity PDC for station state and falls back to data/stations/ YAML only for non-TileState station anchors.

Why PDC matters

Lore is display text, not reliable data. PDC is more suitable for real state such as item IDs, strengthening stars, forge quality, gem sockets, set pieces, skill IDs, and attribute payloads.

What each module writes

ModuleWritten dataNotes
EmakiItemItem id, set id, base attributes, skill bindings, version numberItem identity and base configuration data.
EmakiForgeForge layer, quality, material contribution, recipe idStructured record of a forge result.
EmakiStrengthenStar level, forge-mark state, protection state, strengthen attributes, milestonesStrengthening progress and penalty state.
EmakiGemSocket list, gem id, gem level, upgrade stateFull state of the gem system.
EmakiAttributeAttribute payload, attribute source markersAttribute values granted by equipment.
EmakiSkillsPlayer skill slots, skill levels, trigger bindingsUsually stored in player data files rather than item PDC.
EmakiCookingWorld station state, block-entity PDC keys such as emakicooking:station_statePrefers the station anchor's block-entity PDC; plain blocks fall back to data/stations/, with a coordinate index used for chunk recovery.

Key naming: no dots

Every Emaki PDC key joins its levels with underscores (_) and never with dots (.):

text
emaki_attribute:item_attributes_source_index
emakiforge:forge_quality_id
emaki:item_operations
emaki:item_state_meta_revision

Bukkit's YamlConfiguration treats . as a path separator, so a dotted key cannot be expressed in YAML at all — quoting and backslash escaping both fail because the split happens while the YAML is loaded. Flat keys can be written directly into any Bukkit YAML config, which is what third-party plugins need.

This was a breaking change

Earlier versions joined with dots (emakiforge:forge.quality_id). Existing items, players, and entities still carry the old keys; the plugin migrates them automatically, see Legacy key migration.

If you are writing an extension module, keep dots out of both partition paths and field names. PdcPartition joins partition and field with _, but it does not replace dots you pass in yourself.

Legacy key migration

There are two migration paths and normally you do not need to do anything.

Lazy conversion (automatic): on read, a module tries the flat key first and falls back to the legacy dotted key; on a hit it writes the flat key in place and removes the old one. Player join additionally runs one full conversion over the player's own PDC, which covers write-only mirror keys that a read path would never touch.

Manual command (speed-up and troubleshooting):

text
/emakicorelib pdc-convert <players|containers|entities|all> [--dry-run]
ScopeCoverage
playersOnline players' inventory, armor slots, off-hand, ender chest (including nested shulker boxes), plus the player's own PDC
containersItems inside container blocks in loaded chunks
entitiesEntity PDC in loaded chunks, plus items on dropped items, item frames, and mob equipment slots
allEverything above

Requires emakicorelib.admin. Add --dry-run to count without writing. The command is idempotent: a second run should report 0 conversions. Scanning is batched per loaded chunk and never force-loads chunks.

What the command cannot reach

Offline players' inventories and their own PDC (that data lives in playerdata NBT files), and containers or entities in unloaded chunks. Those rely on lazy conversion and are handled automatically on the next read after the player logs in or the chunk loads. No manual action is needed.

Config files need a manual check

The converter only touches PDC data and never edits config files. Two things need updating by hand:

  • Full key names written directly in your own pdc_match config, such as "emakiforge:forge.quality_id".
  • Variable names derived from PDC keys and used in expressions or matchers: pdc_<namespace>_<key> and item_pdc_<namespace>_<key>.

EmakiStrengthen's Forge variables are the exception: their dotted spelling is kept as an alias and needs no change.

Namespace rule

Each module should write its own namespace or source and avoid overwriting other module data. For example, Gem should not clear Strengthen data, and Strengthen should not clear Forge data.

How PDC relates to Assembly

PDC holds the real data; Assembly renders it into the final presentation:

text
module writes PDC → CoreLib reads every layer → Assembly renders → final lore / name / attributes

Which means:

  • Lore is an output, not an input. Never derive data back from lore.
  • Editing lore does not change real state.
  • Refreshing an item makes CoreLib re-read PDC and rebuild the presentation.

Advice

Do not manually edit PDC in production. Use module commands or APIs to inspect, clear, or refresh state.

Most of the time you never edit PDC by hand. What matters operationally:

  • Do not let other plugins clean up PDC on Emaki items. Some "item cleaner" plugins strip custom NBT data.
  • Do not rewrite PDC-carrying gear through an incompatible plugin. Some item editors build a brand-new ItemStack and lose the original PDC.
  • Use inspect / dump style commands when debugging gear. Do not judge an item's health from its lore alone.
  • Prefer a module's own clear / reset command to wipe that module's state. Deleting PDC keys by hand can leave data inconsistent.
  • Back up important gear before any destructive testing.

Notes for developers

Use your own namespace

java
NamespacedKey key = new NamespacedKey(yourPlugin, "your_data_key");

Never write into another module's namespace.

Keep the data small

Item PDC travels with the item over the network, so large payloads cost performance:

  • Store only the identifiers and values you need.
  • Keep complex data in external files and store just a reference id in PDC.
  • Put a sensible cap on list data.

Version your structures

java
container.set(versionKey, PersistentDataType.INTEGER, 2);

A version number lets you tell whether a migration is needed when the format changes.

Let Assembly generate the presentation

Build presentation through Assembly / Renderer rather than concatenating lore directly. That keeps multi-module ordering consistent, avoids duplicate or missing entries, and supports templating and localisation.

Read other modules through their own API

Prefer the owning module's API module. Do not depend on internal keys, and do not look for an entry point in CoreLib:

java
// Recommended: go through the owning module's API
// Attributes → EmakiAttributeApi (emaki.jiuwu.craft.attribute.api)
EmakiResult<Double> attack = EmakiAttributeApi.catalog().attributeValue(player, "physical_attack");

// Not recommended: reading an internal PDC key directly
NamespacedKey internalKey = new NamespacedKey(attributePlugin, "internal_key");

Internal keys may change between versions; the API stays stable.

Data lifecycle

EventPDC behaviour
Item creationThe module writes its initial PDC data.
Item operation (strengthen / forge / inlay)The owning module updates its own PDC data.
Item refreshCoreLib reads PDC and rebuilds the presentation.
Item dropped or storedPDC data is saved along with the item.
Server restartPDC data persists with the item and is not lost.
Item copied by another pluginDepends on the copy method; ItemStack.clone() preserves PDC.
Item edited by an NBT editorMay break the data structure; editing by hand is discouraged.

Where shared PDC contracts live now

CoreLib used to host some cross-module PDC contracts. Those contracts have been moved to the owning API / protocol modules. New code should use the right-hand column:

DataAuthoritative entry pointLegacy CoreLib entry point
Equipment attribute PDC contractEmakiAttributeApi (in the EmakiAttributeApi module)PdcAttributeGateway and EmakiAttributeBridge were removed in CoreLib 4.6.7
Equipment skill PDC read/writeEquipmentSkillPdcCodec (package emaki.jiuwu.craft.skills.api.pdc in the EmakiSkillsApi module)SkillPdcGateway was removed in CoreLib 4.6.7

These classes no longer exist on the CoreLib side; new code must use the right-hand column.

When you store structured data, keep a version number so you can migrate later. CoreLib's SnapshotCodec provides encoding, decoding, and version compatibility support.