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
| Module | Written data | Notes |
|---|---|---|
| EmakiItem | Item id, set id, base attributes, skill bindings, version number | Item identity and base configuration data. |
| EmakiForge | Forge layer, quality, material contribution, recipe id | Structured record of a forge result. |
| EmakiStrengthen | Star level, forge-mark state, protection state, strengthen attributes, milestones | Strengthening progress and penalty state. |
| EmakiGem | Socket list, gem id, gem level, upgrade state | Full state of the gem system. |
| EmakiAttribute | Attribute payload, attribute source markers | Attribute values granted by equipment. |
| EmakiSkills | Player skill slots, skill levels, trigger bindings | Usually stored in player data files rather than item PDC. |
| EmakiCooking | World station state, block-entity PDC keys such as emakicooking:station_state | Prefers 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 (.):
emaki_attribute:item_attributes_source_index
emakiforge:forge_quality_id
emaki:item_operations
emaki:item_state_meta_revisionBukkit'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):
/emakicorelib pdc-convert <players|containers|entities|all> [--dry-run]| Scope | Coverage |
|---|---|
players | Online players' inventory, armor slots, off-hand, ender chest (including nested shulker boxes), plus the player's own PDC |
containers | Items inside container blocks in loaded chunks |
entities | Entity PDC in loaded chunks, plus items on dropped items, item frames, and mob equipment slots |
all | Everything 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_matchconfig, such as"emakiforge:forge.quality_id". - Variable names derived from PDC keys and used in expressions or matchers:
pdc_<namespace>_<key>anditem_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:
module writes PDC → CoreLib reads every layer → Assembly renders → final lore / name / attributesWhich 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
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
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:
// 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
| Event | PDC behaviour |
|---|---|
| Item creation | The module writes its initial PDC data. |
| Item operation (strengthen / forge / inlay) | The owning module updates its own PDC data. |
| Item refresh | CoreLib reads PDC and rebuilds the presentation. |
| Item dropped or stored | PDC data is saved along with the item. |
| Server restart | PDC data persists with the item and is not lost. |
| Item copied by another plugin | Depends on the copy method; ItemStack.clone() preserves PDC. |
| Item edited by an NBT editor | May 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:
| Data | Authoritative entry point | Legacy CoreLib entry point |
|---|---|---|
| Equipment attribute PDC contract | EmakiAttributeApi (in the EmakiAttributeApi module) | PdcAttributeGateway and EmakiAttributeBridge were removed in CoreLib 4.6.7 |
| Equipment skill PDC read/write | EquipmentSkillPdcCodec (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.