Skip to content

API

All public EmakiAttribute APIs live in the standalone EmakiAttributeApi module (Maven coordinate emaki.jiuwu.craft:emaki-attribute-api), under the packages emaki.jiuwu.craft.attribute.api and emaki.jiuwu.craft.attribute.model. It is the single authoritative entry point for the Attribute contract:

  • PdcAttributeApi — source registration and read/write for item PDC attribute payloads.
  • EmakiAttributeApi — player resources, resolved attribute values, attribute damage, and equipment sync.

Other modules should use these static facades or the public events instead of parsing Attribute's internal data files or calling internal service classes.

PdcAttributeApi

PdcAttributeApi handles item attribute payloads. Equipment modules such as Forge, Strengthen, Gem, and Item use it to attach their own attribute source. Each payload is isolated by source id so sources never clobber one another.

Method signatures

MethodPurpose
static boolean available()Whether Attribute has installed the PDC API bridge.
static boolean registerSource(String sourceId)Register an attribute source such as forge, strengthen, gem, or item.
static void unregisterSource(String sourceId)Unregister a source.
static boolean isRegisteredSource(String sourceId)Whether a source is registered.
static Set<String> registeredSources()All registered sources; empty set when unavailable.
static boolean write(ItemStack, PdcAttributePayload)Write or replace the payload for its source.
static boolean write(ItemStack, String sourceId, Map<String, Double> attributes, Map<String, String> meta)Build a payload from raw maps and write it.
static PdcAttributePayload read(ItemStack, String sourceId)Read one source payload; null when absent.
static Map<String, PdcAttributePayload> readAll(ItemStack)Read every source payload; never null.
static boolean clear(ItemStack, String sourceId)Remove one source payload.
static void clearAll(ItemStack)Remove all Attribute payloads.
static void copy(ItemStack fromItem, ItemStack toItem, Set<String> excludedSourceIds)Copy payloads per source id.

PdcAttributePayload fields

PdcAttributePayload is an immutable record that normalizes keys on construction:

FieldTypeDescription
sourceId()StringOwning source id.
attributes()Map<String, Double>Attribute id to value.
meta()Map<String, String>Arbitrary string metadata.
conditions()Map<String, String>Per-attribute activation conditions.
schemaVersion()intPayload schema version; CURRENT_SCHEMA_VERSION = 2.
updatedAt()longEpoch millis of the last update.

Supporting methods: of(sourceId, attributes, meta), of(sourceId, attributes, meta, conditions), conditionFor(attributeId), hasDurabilityScaling(), toMap(), fromMap(Map).

Full-fidelity copy semantics

copy moves payloads source by source and preserves every field of each payload, including conditions, schemaVersion, and updatedAt; matching sources on the destination item are overwritten. Sources listed in excludedSourceIds keep whatever the destination already holds.

Use copy when upgrading, reforging, or duplicating items. Do not read out attributes and write them back, since that discards conditions and schema information.

Source isolation

Each module should only write and clear its own source. Strengthen clears only the strengthen source, Gem only the gem source. This prevents a strengthen refresh from deleting gem attributes, or gem extraction from deleting forge attributes.

Source registration check

Writes validate that the source id is registered, so call registerSource before write.

EmakiAttributeApi

EmakiAttributeApi is the canonical entry point for player runtime state and damage. Every method degrades to the documented value below when Attribute is absent, disabled, or reloading, so callers need no guard beyond avoiding class loading.

MethodValue when unavailablePurpose
static boolean available()falseWhether the gameplay API bridge is installed.
static double readResourceCurrent(Player, String resourceId)-1Read a player's current resource value.
static double readResourceMax(Player, String resourceId)-1Read a player's current resource maximum.
static boolean consumeResource(Player, String resourceId, double amount)falseConsume a resource; fires PlayerResourceConsumeEvent.
static double readAttributeValue(Player, String attributeId)0Read a player's resolved attribute value.
static void scheduleEquipmentSync(Player)no-opRequest an equipment attribute resync.
static boolean applyDamage(LivingEntity attacker, LivingEntity target, String damageTypeId, double baseDamage, Map<String, Object> context)falseResolve and apply damage through the attribute pipeline; a blank damageTypeId uses the configured default.

Do not cache the internal Bridge instance. Always resolve through the static methods, otherwise a reloaded or disabled Attribute may be called through a stale bridge.

Deprecated CoreLib mirrors

Earlier versions exposed Attribute mirrors on the CoreLib side. They now merely delegate to the canonical facades above and are marked @Deprecated(forRemoval = true); they will be removed at the end of the deprecation window:

Deprecated entry pointReplacement
emaki.jiuwu.craft.corelib.api.integration.PdcAttributeApiemaki.jiuwu.craft.attribute.api.PdcAttributeApi
emaki.jiuwu.craft.corelib.api.integration.EmakiAttributeBridgeemaki.jiuwu.craft.attribute.api.EmakiAttributeApi
CoreLib's PdcAttributeGatewayEither of the two above

On the Attribute side these deprecated interfaces are implemented by the single compatibility adapter LegacyCoreAttributeCompatibility, which holds no business rules and only delegates to the canonical facades. New code must not use these mirrors; depend on emaki-attribute-api directly.

Integration guidance

  • Call PdcAttributeApi.available() / EmakiAttributeApi.available() (or PdcAttributeApiProvider.available()) after your plugin is enabled to avoid load-order issues.
  • Degrade gracefully when the API is unavailable; do not crash a soft-dependent module.
  • Do not cache long-lived attribute snapshots; re-read after equipment changes, reloads, or resync.
  • Write real payloads; lore is display only. Do not parse lore for real attribute state.
  • Use copy when duplicating item attributes so conditions and schema version survive.
  • Consume resources through EmakiAttributeApi.consumeResource rather than bypassing Attribute's resource state management.

Write example

java
PdcAttributeApi.registerSource("forge");
boolean changed = PdcAttributeApi.write(itemStack, "forge", attributes, meta);
// attributes: Map<String, Double> — attribute id to value
// meta: Map<String, String> — metadata entries

PdcAttributeApiProvider.available() / requireAvailable() can also be used for availability checks; the latter throws IllegalStateException when the API is unavailable.

JavaScript access

CoreLib JavaScript scripts can access item PDC attribute payloads through emaki.module("attribute"). Always check available() first when Attribute is an optional dependency.

MethodDescription
available()Whether the Attribute API is registered.
registerSource(sourceId) / unregisterSource(sourceId) / isRegisteredSource(sourceId)Source registration management.
registeredSources()List registered sources.
read(itemKey, sourceId)Read one payload from a contextual item.
readAll(itemKey)Read all Attribute payloads from a contextual item.
write(itemKey, sourceId, attributes, meta)Write an attribute payload.
clear(itemKey, sourceId)Clear one source payload.
clearAll(itemKey)Clear all Attribute payloads.
applyDamage(...) / calculateDamage(...) / setDamageTypeOverride(...)Apply damage, calculate without applying, or override the next damage type.

The payload projection seen by scripts contains six fields — sourceId, attributes, meta, conditions, schemaVersion, and updatedAt — produced by Attribute's own script/ScriptAttributeDtoMapper.

js
function main(ctx) {
  if (!emaki.module("attribute").available()) {
    return { skipped: true, message: "Attribute not installed" };
  }

  emaki.module("attribute").registerSource("js_bonus");
  return emaki.module("attribute").write("target_item", "js_bonus", {
    physical_attack: 8,
    physical_defense: 10
  }, {
    reason: "script_bonus"
  });
}

JavaScript dynamic attributes and damage hooks

Extension scripts placed under extensions/attribute/ in the CoreLib script root can use register() to register runtime attributes, attribute providers, damage types, damage pipelines, and damage hooks. Runtime attributes are rebuilt on Attribute reload and participate in attribute lookup, snapshot signatures, and damage calculation.

See JavaScript for the full registration API, definition fields, and the event / ctx callback methods.

Call Attribute through CoreLib's MythicMobs JS mechanic

emaki_js is not registered by Attribute. It is registered by CoreLib with aliases corelib_js and emakicorelib_js. Attribute provides the emaki.module("attribute") script module and example scripts that can be called from CoreLib's generic JS mechanic.

Attribute's own MythicMobs integrations are the attribute damage mechanic emaki_damage (aliases emakiattribute_damage, attribute_damage) and the attribute condition emaki_attribute (aliases emakiattribute_attribute, attribute_value, attribute_resource). See MythicMobs integration.

Use CoreLib's generic JS mechanic to call the Attribute example script:

yaml
Skills:
  JsFireDamage:
    Skills:
      - emaki_js{script="mythic/mythic_js_damage.js";function="mythicDamage";damage=12;damage_type=fire} @target

The JavaScript function receives meta,args:

js
function mythicDamage(meta, args) {
  const caster = meta.caster();
  const target = meta.firstTarget();
  return emaki.module("attribute").applyDamage(caster, target, args.damage_type || "default", Number(args.damage || 1), {
    source: "mythic_js",
    mythic_mechanic: meta.mechanic()
  });
}

Attribute releases scripts/mythic/mythic_js_damage.js into the CoreLib script repository as an example; existing target files are not overwritten.