Skip to content

API

EmakiAttribute 的公开 API 全部位于独立的 EmakiAttributeApi 模块(Maven 坐标 emaki.jiuwu.craft:emaki-attribute-api),包名 emaki.jiuwu.craft.attribute.apiemaki.jiuwu.craft.attribute.model。它是 Attribute 契约的唯一权威入口

  • PdcAttributeApi — 物品 PDC 属性 payload 的来源注册与读写。
  • EmakiAttributeApi — 玩家资源、已解析属性值、属性伤害与装备同步。

其他模块如果需要和属性系统联动,应使用这两个静态门面或公开事件,而不是直接解析 Attribute 内部数据文件或调用内部 service 类。

PdcAttributeApi

PdcAttributeApi 面向“物品属性 payload”的读写。Forge、Strengthen、Gem、Item 这类装备模块可以通过它向装备写入自己的属性来源。每个 payload 按 source id 隔离存放,互不覆盖。

方法签名

方法用途
static boolean available()判断 Attribute 是否已安装 PDC API 桥接。
static boolean registerSource(String sourceId)注册一个属性来源,例如 forge、strengthen、gem、item。
static void unregisterSource(String sourceId)注销属性来源。
static boolean isRegisteredSource(String sourceId)判断来源是否已注册。
static Set<String> registeredSources()查看当前已注册来源;不可用时返回空集合。
static boolean write(ItemStack, PdcAttributePayload)写入或替换该 payload 所属来源的属性。
static boolean write(ItemStack, String sourceId, Map<String, Double> attributes, Map<String, String> meta)由原始 Map 构造 payload 后写入。
static PdcAttributePayload read(ItemStack, String sourceId)读取指定来源属性;缺失时返回 null
static Map<String, PdcAttributePayload> readAll(ItemStack)读取物品上所有来源属性;永不为 null
static boolean clear(ItemStack, String sourceId)清理指定来源属性。
static void clearAll(ItemStack)清理全部 Attribute payload。
static void copy(ItemStack fromItem, ItemStack toItem, Set<String> excludedSourceIds)按来源整体复制 payload。

PdcAttributePayload 字段

PdcAttributePayload 是不可变 record,构造时会规范化各级 key:

字段类型说明
sourceId()String所属来源 ID。
attributes()Map<String, Double>属性 ID → 数值。
meta()Map<String, String>任意字符串元数据。
conditions()Map<String, String>按属性 ID 指定的激活条件。
schemaVersion()intpayload 结构版本;当前 CURRENT_SCHEMA_VERSION = 2
updatedAt()long最后更新的 epoch 毫秒。

配套方法:of(sourceId, attributes, meta)of(sourceId, attributes, meta, conditions)conditionFor(attributeId)hasDurabilityScaling()toMap()fromMap(Map)

copy 的完整保真语义

copy 会逐个来源整体搬运 payload,并完整保留每个 payload 的全部字段,包括 conditionsschemaVersionupdatedAt;目标物品上的同名来源会被覆盖。列入 excludedSourceIds 的来源保持目标物品原有内容不变。

升级、重铸、复制物品时应使用 copy,不要用「读出 attributes 再写回」的方式,那样会丢失条件与版本信息。

来源隔离原则

每个模块应写入自己的 source,不要覆盖其他来源。例如 Strengthen 只清理 strengthen 来源,Gem 只清理 gem 来源。这样可以避免强化刷新时误删宝石属性,或宝石提取时误删锻造属性。

来源注册校验

写入前会校验 sourceId 是否已注册。确保在 write 之前调用 registerSource

EmakiAttributeApi

EmakiAttributeApi 是玩家运行时状态与伤害能力的规范入口。每个方法在 Attribute 缺失、禁用或重载期间都会退化为下表中的固定返回值,因此调用方除避免类加载外无需额外守卫。

方法不可用时返回用途
static boolean available()false判断玩法 API 桥接是否就绪。
static double readResourceCurrent(Player, String resourceId)-1读取玩家资源当前值。
static double readResourceMax(Player, String resourceId)-1读取玩家资源当前上限。
static boolean consumeResource(Player, String resourceId, double amount)false消耗资源;会触发 PlayerResourceConsumeEvent
static double readAttributeValue(Player, String attributeId)0读取玩家已解析的属性值。
static void scheduleEquipmentSync(Player)无操作请求一次装备属性重新同步。
static boolean applyDamage(LivingEntity attacker, LivingEntity target, String damageTypeId, double baseDamage, Map<String, Object> context)false按属性管线结算并施加伤害;damageTypeId 留空使用默认伤害类型。

不要缓存内部 Bridge 实例,始终通过静态方法调用,否则重载或禁用后可能通过失效桥接调用。

已废弃的 CoreLib 镜像入口

早期版本在 CoreLib 侧提供了 Attribute 的镜像入口。它们现在只是委托到上面的规范门面,并已标记 @Deprecated(forRemoval = true),将随废弃窗口结束一并移除:

废弃入口替代
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 的 PdcAttributeGateway同上两者

Attribute 侧由唯一的兼容适配器 LegacyCoreAttributeCompatibility 实现这些废弃接口,它本身不含任何业务规则,只逐一委托到规范门面。新代码不应使用这些镜像入口,请直接依赖 emaki-attribute-api

接入建议

  • 插件启动后再调用 PdcAttributeApi.available() / EmakiAttributeApi.available()(或 PdcAttributeApiProvider.available()),避免加载顺序问题。
  • 查询不到 API 时降级运行,不要让 softdepend 模块直接崩溃。
  • 不要缓存长期属性快照,装备变化、重载或 resync 后应重新读取。
  • 写属性时写真实 payload,Lore 只作为展示。
  • 复制物品属性时使用 copy,保留条件与结构版本。
  • 消耗资源时使用 EmakiAttributeApi.consumeResource,不要绕过 Attribute 的资源状态管理。

常见接入场景

  • Skills 释放技能前检查和消耗法力。
  • Gem 镶嵌后写入宝石属性。
  • Strengthen 根据星级写入强化属性。
  • Forge 根据品质写入锻造属性。
  • 外部插件读取玩家当前攻击、防御或资源。
  • 监听 EmakiAttributeDamageEvent 拦截或修改属性伤害(详见伤害事件 API 文档)。

写入示例

java
PdcAttributeApi.registerSource("forge");
boolean changed = PdcAttributeApi.write(itemStack, "forge", attributes, meta);
// attributes: Map<String, Double> — 属性 ID → 值
// meta: Map<String, String> — 元数据键值对

也可以配合 PdcAttributeApiProvider.available() / requireAvailable() 做可用性检查;后者在 API 不可用时抛出 IllegalStateException

EmakiAttributeDamageEvent

属性伤害计算完成后触发的 Bukkit 事件。可取消、可修改最终伤害。详见伤害事件 API 文档。

JavaScript 调用

CoreLib JavaScript 脚本中可通过 emaki.module("attribute") 调用 PdcAttributeApi 的物品属性 payload 能力。调用前先检查 available(),避免服务器未安装 Attribute 时脚本失败。

方法说明
available()判断 Attribute API 是否可用。
registerSource(sourceId) / unregisterSource(sourceId) / isRegisteredSource(sourceId)来源注册管理。
registeredSources()查看已注册来源。
read(itemKey, sourceId)读取上下文物品指定来源 payload。
readAll(itemKey)读取上下文物品全部 Attribute payload。
write(itemKey, sourceId, attributes, meta)写入属性 payload。
clear(itemKey, sourceId)清理指定来源 payload。
clearAll(itemKey)清理全部 Attribute payload。
applyDamage(...) / calculateDamage(...) / setDamageTypeOverride(...)伤害施加、试算与类型覆盖。

脚本读到的 payload 投影包含 sourceIdattributesmetaconditionsschemaVersionupdatedAt 六个字段,由 Attribute 侧的 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 动态属性与伤害流

在 CoreLib 脚本根目录的 extensions/attribute/ 下,扩展脚本可通过 register() 注册运行时属性、属性提供者、伤害类型、伤害管线和伤害钩子。脚本注册的属性会在 Attribute 重载时重建,参与属性读取、快照签名和伤害计算。

完整的注册 API、definition 字段与 event / ctx 回调方法见 JavaScript 脚本

通过 CoreLib MythicMobs JS mechanic 调用 Attribute

emaki_js 不是 Attribute 注册的 mechanic。它由 CoreLib 注册,注册名为 emaki_js,别名为 corelib_jsemakicorelib_js。Attribute 只提供 emaki.module("attribute") 脚本模块和示例脚本,供 CoreLib 的通用 JS mechanic 调用。

Attribute 自己注册的 MythicMobs 能力是属性伤害 mechanic emaki_damage(别名 emakiattribute_damageattribute_damage)和属性条件 emaki_attribute(别名 emakiattribute_attributeattribute_valueattribute_resource),详见 MythicMobs 集成

用 CoreLib 通用 JS mechanic 调用 Attribute 示例脚本:

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

对应 JS 函数接收 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 会把 scripts/mythic/mythic_js_damage.js 示例释放到 CoreLib 脚本仓库;目标文件已存在时不会覆盖。