Skip to content

配方系统

配方是 EmakiForge 的核心数据结构,定义了一次锻造需要什么图纸、什么材料、怎么算品质、产出什么东西。每个配方对应 recipes/ 目录下的一个 YAML 文件。

配方完整格式

下面是一个包含所有可用字段的完整示例。实际使用时,大部分字段是可选的,按需配置即可。

yaml
# 配方唯一标识符
id: example_sword

# 显示名称(支持 MiniMessage 格式)
display_name: "<gold>铁剑锻造"

# 锻造容量 — 限制可投入材料的总容量
forge_capacity: 100

# ===== 图纸需求 =====
# 锻造前必须在图纸槽位放入匹配的图纸
blueprint_requirements:
  - iron_sword_blueprint

# ===== 材料列表 =====
materials:
  # 必选材料
  - item: "minecraft:iron_ingot"
    amount: 5
    optional: false
    capacity_cost: 10
    effects:
      - type: stat_contribution
        stat: physical_damage
        amount: 12.0

      - type: quality_modify
        modifier_type: minimum    # minimum | force
        tier: "精良"

  # 可选材料
  - item: "neigeitems:magic_crystal"
    amount: 1
    optional: true
    capacity_cost: 20
    effects:
      - type: attribute
        attribute: "攻击力"
        value: 5.0

      - type: capacity_bonus
        amount: 15

      - type: name_modify
        format: "<light_purple>魔力{name}"

      - type: lore_action
        action: append
        section: enchant_info
        lines:
          - "<gray>附魔:<aqua>魔力注入"

      - type: structured_presentation
        name_contributions:
          magic_prefix:
            order: 1
            format: "<light_purple>魔力 "
        lore_sections:
          magic_info:
            order: 50
            lines:
              - "<gray>魔力注入:<aqua>+5"

# 可选材料数量上限
optional_material_limit: 3

# ===== 条件系统 =====
# 条件类型:all_match(全部满足)| any_match(任一满足)
condition_type: all_match
conditions:
  - type: permission
    value: "emakiforge.recipe.example_sword"
  - type: level
    operator: ">="
    value: 10
  - type: placeholder
    placeholder: "%player_exp%"
    operator: ">="
    value: "500"

# ===== 品质配置 =====
quality:
  # 自定义品质池(不设置则使用全局 config.yml 中的 tiers)
  custom_pool:
    - "普通-40-1.0"
    - "精良-35-1.3"
    - "史诗-20-1.6"
    - "传说-5-2.0"

  # 品质动作 — 根据品质等级触发不同动作
  actions:
    传说:
      - "broadcast message=<gold>{player} <yellow>锻造出了传说品质的 {item}!"
      - "playsound sound=ui.toast.challenge_complete volume=1.0 pitch=1.0"
    史诗:
      - "playsound sound=entity.player.levelup volume=1.0 pitch=1.2"

# ===== 结果定义 =====
result:
  # 输出物品(物品来源 ID)
  output_item: "minecraft:iron_sword"

  # 元动作 — 对输出物品执行的修改操作
  meta_actions:
    - type: set_name
      value: "{quality} 铁剑"
    - type: set_lore
      lines:
        - "<gray>物理伤害:<white>{physical_damage}"
        - "<gray>品质:<white>{quality}"
        - "<gray>品质倍率:<white>{multiplier}"
    - type: set_custom_model_data
      value: 10001

  # 动作阶段
  action:
    # 锻造前执行
    pre:
      - "playsound sound=block.anvil.use volume=1.0 pitch=0.8"
      - "sendmessage message=<gray>开始锻造..."

    # 锻造成功后执行
    success:
      - "playsound sound=block.anvil.land volume=1.0 pitch=1.2"
      - "sendmessage message=<green>锻造成功!品质:{quality}"
      - "giveexp amount=100"

    # 锻造失败后执行(当前版本锻造默认成功,此阶段为预留)
    failure:
      - "playsound sound=block.anvil.destroy volume=1.0 pitch=0.5"
      - "sendmessage message=<red>锻造失败了..."

# 权限节点(可选,覆盖全局权限检查)
permission: "emakiforge.recipe.example_sword"

材料效果类型

每种材料可以挂载多个效果(effects 列表),在锻造时一起生效。支持的效果类型如下:

效果类型做什么关键字段
stat_contribution给产物贡献数值属性(如物理伤害),最终值会乘以品质倍率stat, amount
structured_presentation控制产物的名称前缀/后缀和 Lore 区块的渲染name_contributions, lore_sections
capacity_bonus增加本次锻造的容量上限,让你能塞进更多材料amount
quality_modify干预品质结果:强制指定品质,或设定品质下限modifier_type, tier
attribute向产物写入 EmakiAttribute 属性attribute, value
name_modify直接修改产物的显示名称format
lore_action追加或替换产物的 Lore 行action, section, lines
skill向产物写入技能 ID,让装备解锁对应的 EmakiSkills 技能skillsskill

stat_contribution 详解

这是最常用的材料效果。它的计算逻辑很直接:

最终属性值 = amount × quality_multiplier
变量说明
stat属性名称,比如 physical_damagespell_power
amount这个材料贡献的基础属性值
quality_multiplier品质倍率,由最终品质等级决定(比如传说 = 2.0)

举个例子:材料贡献 physical_damage = 12.0,最终品质是"传说"(倍率 2.0),那物理伤害 = 12.0 × 2.0 = 24.0。

如果多个材料都贡献了同一个 stat,它们的 amount 会先累加,再乘以品质倍率。

quality_modify 详解

品质修正有两种模式,适用于不同场景:

modifier_type效果典型用途
force直接把品质锁定为指定等级,跳过随机特殊材料(如"传说之心")保证出传说品质
minimum设定品质下限,随机结果低于这个等级时自动提升高级材料保底不出太差的品质
yaml
effects:
  - type: quality_modify
    modifier_type: minimum
    tier: "精良"

structured_presentation 详解

这个效果让材料可以往产物的名称和 Lore 上"注入"内容。多个材料的注入内容会按 order 排序后合并。

yaml
effects:
  - type: structured_presentation
    name_contributions:
      magic_prefix:
        order: 1          # 排序权重,越小越靠前
        format: "<light_purple>魔力 "
    lore_sections:
      magic_info:
        order: 50         # Lore 区块排序权重
        lines:
          - "<gray>魔力注入:<aqua>+5"

name_contributions 中的每个条目会按 order 排序后拼接成最终名称。lore_sections 同理,按 order 排序后依次追加到 Lore 中。这样设计是为了让不同材料的展示内容能有序地组合在一起,而不是互相覆盖。

skill 详解

skill 效果让材料可以给产物写入技能 ID。锻造完成后,产物的 PDC 中会包含技能 ID 列表(通过 ReflectiveSkillPdcGateway 写入),EmakiSkills 扫描装备时就能识别并解锁对应技能。

yaml
effects:
  # 列表写法(推荐,一次声明多个技能)
  - type: skill
    skills:
      - "fireball"
      - "ice_bolt"

  # 单个写法
  - type: skill
    skill: "mana_shield"

多个材料都声明了 skill 效果时,所有技能 ID 会合并去重后写入产物。

结果 meta_actions

meta_actions 在锻造完成后对输出物品做最终修改:

动作类型做什么字段
set_name设置物品显示名称value
set_lore设置物品 Lorelines
set_custom_model_data设置自定义模型数据(用于资源包切换模型)value

meta_actions 中的 valuelines 都支持变量注入,所以你可以写 "{quality} 铁剑" 这样的模板。

变量注入

配方的 meta_actionsaction 阶段和品质动作中都可以用以下变量:

变量说明示例值
{physical_damage}物理伤害属性值(已经乘过品质倍率)24.0
{quality}品质等级名称传说
{multiplier}品质倍率2.0
{player}玩家名称Steve
{item}输出物品名称铁剑

提示

所有 stat_contribution 中声明的 stat 名称都会自动注册为变量。比如你声明了 stat: spell_power,就可以在模板中用 {spell_power} 引用它的最终值。

审计数据

每次锻造完成后,系统会把这次锻造的关键信息记录到玩家数据文件中,方便排查问题或做数据统计:

字段说明
recipe_id使用的配方 ID
quality最终品质等级
quality_multiplier品质倍率
materials_used消耗的材料列表
stat_values最终属性值映射
timestamp锻造时间戳
blueprint_id使用的图纸 ID

ForgeLayerSnapshotBuilder 流程

ForgeLayerSnapshotBuilder 负责把锻造结果打包成 layer snapshot 并写入产物。整个过程是这样的:

收集所有材料的贡献

计算品质等级(加权随机 / 保底 / 材料修正)

把品质倍率乘到所有 stat_contribution 上

合并 structured_presentation(名称贡献 + Lore 区块)

合并 attribute 写入列表

构建 ForgeLayerSnapshot

通过 AssemblyService 写入物品 PDC

触发 StructuredPresentationRenderer 重建物品展示

这个流程是同步执行的。先算好所有数据,再一次性写入,保证物品状态的一致性。

注意

配方加载时会做严格校验:condition_type 如果不是 all_matchany_match,加载器会直接拒绝。配方中如果出现 target_item 节点也会被拒绝(这是旧版字段,已废弃)。

Released under the GPL-3.0 License