Skip to content

物品定义与套装

EmakiItem 的物品文件通常位于 items/*.yml,套装文件位于 sets/*.yml。物品定义决定一个稳定物品 ID 如何生成 ItemStack,套装定义决定多个装备同时穿戴时如何提供额外效果。

物品定义字段

完整字段参考

字段类型必填默认值说明
idstring物品唯一 ID。其他模块引用时使用。
itemobject共享基础物品定义,包含 sourceamountcomponents
name_actionslist/object在基础组件生成后处理名称的动作链。
lore_actionslist/object在基础组件生成后处理 Lore 的动作链。
effectslist变量、EmakiAttribute 属性和 EmakiSkills 技能等业务效果。
equip_slotstringall业务属性/技能生效的装备槽:allhandmain_handoff_handhelmetchestplateleggingsboots。不支持的值会回退为 all 并输出警告。
setobject套装信息。
conditionobject装备条件配置。
repairobject修复配置。
updateobject自动更新配置。
actionsobject触发动作配置。

旧顶层 materialdisplay_nameitem_namelorecomponentsamount 仍可读取并转换到共享 definition,但新配置、默认资源和 JavaScript 示例不再写这些字段。新旧同时存在时以嵌套 item 为准。

旧版物品定义自动迁移

items/*.{yml,yaml} 会在 definition 正式解析前执行一次 configured-item 迁移。它只转换 YAML 节点,不创建 Bukkit ItemStack,因此迁移结果不依赖玩家、世界或第三方物品插件运行状态。

主要映射包括:

旧字段新字段 / 行为
material规范化为小写、下划线形式并写入 item.source,例如 DIAMOND_SWORDminecraft-diamond_sword
sourceitem_sourceitem_sources、标量 item取可用来源写入 item.source;列表来源保留运行时转换器的首个来源优先语义。
amount写入 item.amount
display_nameitem_namelore写入 item.components.custom_name / item.components.item_name / item.components.lore
custom_model_data写入 item.components.custom_model_data;在 1.21.5+ 配置中支持 floats 等结构。
enchantments写入 item.components.enchantments 的附魔 ID → 等级直接映射;旧隐藏附魔标记同步到 tooltip_display.hidden_components
item_flagshidden_components映射到 1.21.5+ item.components.tooltip_display
unbreakable 等旧组件字段转换为对应 namespaced component 结构,并保留现代组件优先规则。

安全边界:

  • 现代 item.sourceitem.amount 与已有 item.components 永远优先,旧字段只填补缺失值。
  • 出现 components.rawitem.components.raw 时跳过整个候选节点,不做部分迁移。
  • effectsequip_slotsetconditionrepairupdateactions 等业务字段保持不变。
  • 每批修改先备份原文到 plugins/EmakiItem/migration-backups/configured-item-format/<时间戳>/,保留相对于 items/ 的目录层级。
  • 新 YAML 先写入同目录临时文件并重新解析校验;只有校验成功才替换原文件。失败时保留或恢复原文件,并拒绝使用未经验证的迁移结果。
  • 迁移是幂等的;成功迁移后的文件再次启动不会重复改写。

迁移不读取 EmakiItem、CoreLib、配置或语言文件中的版本值,也不依赖某个历史版本号判断是否执行;只要候选节点仍包含旧字段,就会按相同规则处理。转换规则由 EmakiItem 自身持有,只在 definition 加载入口调用 CoreLib 的通用迁移执行器,兼容期结束后可移除该入口,而不改变共享 ConfiguredItemDefinition 或 canonical parser。

效果系统(effects)

物品效果统一使用 effects 列表,通过 type 字段区分类型:

type说明
variables表达式引擎变量,用于 display_namelore 中的占位符渲染。
ea_attributeEmakiAttribute PDC 属性,写入物品 PDC。
es_skillEmakiSkills 技能附加,装备时获得技能;payload 使用 es_skills 列表。
yaml
effects:
  - type: "variables"
    variables:
      physical_attack: 12
      physical_crit_rate: 5
  - type: "ea_attribute"
    ea_attributes:
      physical_attack: 12.0
      physical_crit_rate: 5.0
  - type: "es_skill"
    es_skills:
      - "fireball"
      - "flame_dash"
    es_skill_triggers:
      fireball: "right_click"

es_skill 效果支持可选的 es_skill_triggers(也接受 skill_triggers),格式为 技能 ID: 触发器 ID。它写入装备强制触发器,使该技能在装备时由指定触发器释放,不占用玩家技能槽。

当前配置线不再使用 ea_attribute_meta;如果需要真实属性输出,请把属性值写入显式 ea_attributesvariables 只作为显示文本和占位符上下文,不会自动变成 Attribute PDC 属性。

技能 ID 与技能触发器写入物品 PDC 的过程不检查 EmakiSkills 是否启用;相关键由独立协议模块统一持有。

item 与原版组件

yaml
item:
  source: minecraft-netherite_sword
  amount: 1
  components:
    custom_name: '<gradient:red:gold>%name%</gradient>'
    lore:
      - '<gray>攻击:%physical_attack%</gray>'
    item_model: emaki:flame_blade
    custom_model_data:
      floats: [1001.0]
    attribute_modifiers:
      - type: minecraft:attack_damage
        id: emakiitem:flame_blade/attack_damage
        amount: 12.0
        operation: add_value
        slot: mainhand
    rarity: rare
    max_stack_size: 1
    $unset:
      - repairable
    $reset:
      - enchantments

components 使用 Minecraft namespaced data component ID;未写命名空间时默认使用 minecraft:,例如 custom_name 等价于 minecraft:custom_name,显式的其他命名空间保持不变。该规则同样适用于 $unset / $reset 列表。map/list/scalar 直接按 JSON 等价结构写成 YAML;普通值表示 SET$unset 删除组件,$reset 恢复材质原型默认值。文本组件允许 MiniMessage 字符串简写;极少数 JSON 无法无损表达的 NBT 可使用受控 {$snbt: '...'} 逃生口。

错误与版本策略:

  • 未知组件 ID:配置错误,definition 不进入有效缓存。
  • 当前版本支持但值非法:配置错误,definition 不进入有效缓存。
  • 已知但高于服务器版本:跳过该组件并记录警告,其余组件继续处理。
  • 第三方 ItemSource:保留来源身份、PDC 和未知组件,只应用当前 Paper 可安全传递的组件。

item.source 不限于 Bukkit Material,可使用 CoreLib 当前注册的所有 ItemSource。resolver 不存在、插件未安装或来源无法创建时,该 EmakiItem definition 会被拒绝缓存。最低支持 Paper 1.21.8+;组件目录与运行时 capability 共同决定当前服务器可用能力。

物品示例

基础武器

yaml
id: "beginner_blade"
item:
  source: minecraft-iron_sword
  components:
    minecraft:custom_name: "<white>新手长剑</white>"
    minecraft:lore:
      - "<gray>一把稳定可靠的基础武器。</gray>"
      - ""
      - "<gray>攻击力:<white>+10</white></gray>"
    minecraft:unbreakable: {}
    minecraft:tooltip_display:
      hidden_components:
        - minecraft:unbreakable
effects:
  - type: "ea_attribute"
    ea_attributes:
      physical_attack: 10.0
set:
  id: "beginner_set"
  piece: "weapon"

带变量的高级装备

yaml
id: "flame_blade"
item:
  source: minecraft-netherite_sword
  components:
    minecraft:custom_name: "<gradient:red:gold>%name%</gradient>"
    minecraft:lore:
      - "<dark_gray>━━━━━━━━━━━━━━━━━━</dark_gray>"
      - "<red>⚔ 物理攻击:<white>+%physical_attack%</white></red>"
      - "<yellow>✦ 暴击率:<white>+%physical_crit_rate%%</white></yellow>"
      - "<dark_gray>━━━━━━━━━━━━━━━━━━</dark_gray>"
      - "<gray>传说中由龙焰锻造的神兵。</gray>"
    minecraft:item_model: "emaki:flame_blade"
    minecraft:enchantment_glint_override: true
    minecraft:rarity: "rare"
    minecraft:max_stack_size: 1
effects:
  - type: "variables"
    variables:
      name: "烈焰之刃"
      physical_attack: 45
      physical_crit_rate: 12
  - type: "ea_attribute"
    ea_attributes:
      physical_attack: 45.0
      physical_crit_rate: 0.12
  - type: "es_skill"
    es_skills:
      - "flame_slash"
set:
  id: "flame_set"
  piece: "weapon"

消耗品

yaml
id: "health_potion_large"
item:
  source: minecraft-potion
  amount: 1
  components:
    minecraft:custom_name: "<red>大型生命药水</red>"
    minecraft:lore:
      - "<gray>右键使用,恢复 50 点生命。</gray>"
      - "<dark_gray>使用后消耗。</dark_gray>"
    minecraft:max_stack_size: 16
    minecraft:custom_model_data:
      floats: [1001.0]
actions:
  right_click:
    - 'heal amount=50'
    - 'playsound sound=minecraft:entity.generic.drink volume=1 pitch=1'
    - 'clearitem slot=mainhand source=emakiitem-health_potion_large'
    - 'sendmessage text="<green>恢复了 50 点生命。</green>"'

actions 的 key 必须是触发器页列出的触发器名,例如 right_clickconsumeattackgive。未列出的 key 不会被执行。

条件配置

物品可以配置装备条件,不满足时该物品对该玩家整体失效:

yaml
condition:
  type: "all_of"
  entries:
    - "%player_level% >= 10"
    - "%player_class% == 'warrior'"
  required_count: 2
  invalid_as_failure: true
  on_pass:
    actions:
      - 'sendmessage text="<green>装备条件满足,属性已生效。</green>"'
  on_fail:
    message: "<red>你不满足装备条件!</red>"
    actions:
      - 'sendmessage text="<red>需要等级 10 以上的战士才能装备此武器。</red>"'
字段说明
entries条件表达式列表。也可写作 conditions
type条件组合方式:all_of(全部满足)/ any_of(任一满足);默认 all_of
required_count需要满足的最少条件数。
invalid_as_failure表达式解析失败时是否视为不满足。
on_pass.actions满足时执行的动作。
on_fail.message不满足时的提示消息。
on_fail.actions不满足时执行的动作。

门控范围

条件不满足时,以下内容全部不生效:

传递面数据来源
EA 属性Lore 词条与 PDC 属性两条来源同时失效
装备技能Lore 与 PDC 两条来源同时失效
套装属性emakiitememakiitem_set 两个 PDC 来源
触发器动作该次触发被拦截

仍然生效、不受此条件门控的部分:EmakiGem 宝石、EmakiForge 锻造、 EmakiStrengthen 强化各自写入的 PDC 属性。它们由对应模块拥有, 不随宿主物品条件失效。

求值时机:触发器动作在每次触发执行前求值;属性与技能在每次装备收集时 按玩家实时求值,因此等级、职业等变化后立即生效,无需重新装备。 属性与技能的门控求值不发送 on_fail.message、不执行 on_pass/on_fail 动作,这些只在触发器路径产生。

属性与技能门控由 EmakiAttribute 承载,需要 EmakiAttribute 已启用; 仅安装 EmakiItem 时条件只门控触发器动作。

修复配置

物品耐久耗尽后可以通过材料或金币修复:

yaml
repair:
  enabled: true
  materials:
    - item_sources:
        - "minecraft-diamond"
      amount: 1
      restore: 250
  economy:
    enabled: true
    restore: "100%"
    currencies:
      - provider: "vault"
        currency_id: ""
        base_cost: 100
        cost_formula: "base_cost + missing_durability * 0.25"
        display_name: "金币"
  on_disabled:
    - 'sendmessage text="<red>你的武器已损坏!</red>"'
  on_repaired:
    - 'sendmessage text="<green>武器已修复!</green>"'

字段含义与完整流程见物品修复系统

套装定义

套装字段

字段类型必填说明
idstring套装唯一 ID。缺失或非法时跳过该文件。
display_namestring套装显示名(MiniMessage 格式);缺省时回退为套装 ID。
piecesmap套装部件定义(key 为部件标识)。
loreobject套装 Lore 显示格式配置。
thresholdsmap件数阈值效果配置;key 为所需件数,必须为正整数。

套装文件放在 sets/ 下,支持子目录递归加载。重复 id 只保留首个定义并输出警告。

状态计算与错误槽位

套装 membership 可见性与激活件数分别计算。只要物品 definition 声明了可用的 set.id,当前状态就保留该套装,即使所有候选件都因槽位不匹配而无效,Lore 也会显示 0/%total%,而不是构造成缺少套装定义的空状态。

只有同时满足以下条件的装备才进入 activeCount 和激活阈值:

  1. 能唯一解析到 sets/*.yml 中的真实部件;
  2. 当前装备槽匹配物品 definition 的 equip_slot
  3. 当前装备槽同时匹配套装部件的 slot

缺失或无法加载的套装定义会被安全隔离,不进入可见状态,也不会触发奖励或破坏性 Lore 写回;运行时会为每个缺失套装 ID 输出一次警告,启用 set DEBUG 时还会输出 [DEBUG:SET_STATE] state=missing_definition action=preserve。Folia 与 Paper 都使用同一纯状态构造规则,Folia 只改变 owner-thread 调度边界。

部件定义(pieces)

yaml
pieces:
  blade:
    item: "example_item"
    slot: "main_hand"
    display: "示例之刃"
  helmet:
    item: "example_guardian_helmet"
    slot: "helmet"
    display: "守护者头盔"
字段说明
item对应的物品 ID(items/ 目录下的物品定义);缺省时使用部件 key。
slot装备槽位(main_hand/off_hand/helmet/chestplate/leggings/boots);缺省时使用部件 key。
display在套装 Lore 中显示的部件名称;缺省时使用部件 key。

部件也可简写为 部件key: 物品ID,此时槽位与显示名都回退为部件 key。

Lore 显示配置

yaml
lore:
  header: "<dark_gray>—— <aqua>套装名</aqua> <gray>(%active%/%total%)</gray> ——</dark_gray>"
  equipped_format: "<green>✔ %piece%</green>"
  missing_format: "<gray>✘ %piece%</gray>"
  active_threshold_format: "<green>%line%</green>"
  inactive_threshold_format: "<dark_gray>%line%</dark_gray>"
  separator: ""

套装示例

yaml
id: "example_set"
display_name: "<aqua>示例守护者套装</aqua>"

pieces:
  blade:
    item: "example_item"
    slot: "main_hand"
    display: "示例之刃"
  helmet:
    item: "example_guardian_helmet"
    slot: "helmet"
    display: "守护者头盔"
  chestplate:
    item: "example_guardian_chestplate"
    slot: "chestplate"
    display: "守护者胸甲"
  boots:
    item: "example_guardian_boots"
    slot: "boots"
    display: "守护者战靴"

lore:
  header: "<dark_gray>—— <aqua>示例守护者套装</aqua> <gray>(%active%/%total%)</gray> ——</dark_gray>"
  equipped_format: "<green>✔ %piece%</green>"
  missing_format: "<gray>✘ %piece%</gray>"
  active_threshold_format: "<green>%line%</green>"
  inactive_threshold_format: "<dark_gray>%line%</dark_gray>"
  separator: ""

thresholds:
  2:
    lore:
      - "[2件套] 物理攻击 +5,解锁冲刺技能"
    effects:
      - type: "ea_attribute"
        ea_attributes:
          physical_attack: 5.0
      - type: "es_skill"
        es_skills:
          - "guardian_dash"
  4:
    lore:
      - "[4件套] 物理攻击 +15,物理防御 +10,解锁守护者光环"
    effects:
      - type: "ea_attribute"
        ea_attributes:
          physical_attack: 15.0
          physical_defense: 10.0
      - type: "es_skill"
        es_skills:
          - "guardian_aura"

自动更新

update 配置控制物品在哪些时机自动刷新:

yaml
update:
  enabled: true
  version: 1
  triggers:
    join: true
    held_change: true
    inventory_click: true
    inventory_drag: true
    pickup: true
    interact: true
    command: true
触发项说明性能影响
join玩家登录时。
held_change切换手持物品时。
inventory_click点击背包时。
inventory_drag拖拽物品时。
pickup拾取物品时。
interact交互事件时。
command执行 /ei update 时。

每次修改物品配置后递增 version 字段即可触发更新。建议不要开启过多高频触发,先确保手动 /ei update 正常,再逐步开启自动更新。