简体中文
图纸与材料
图纸要求和材料列表分别怎么写, 以及它们如何决定一次锻造能不能开始, 成本多大, 出什么品质, 给成品附加哪些效果
图纸管的是"能不能做", 材料管的是"用什么做, 做得多好": 图纸决定哪些配方可以被执行, 材料决定锻造成本, 品质和附加效果
图纸要求
yaml
blueprint_requirements:
- item_sources:
- "minecraft-enchanted_book"
amount: 1| 字段 | 类型 | 必填 | 默认值 | 取值范围 | 说明 |
|---|---|---|---|---|---|
id | string | 否 | 由 item_sources 简写派生; 无物品源时退化为 matcher 摘要 | 非空字符串 (声明了就不能为空白, 否则报 IDENTITY_BLANK) | 图纸要求的身份键, 同一个图纸的多个条目按它归到一起计数. 见下方同一图纸的多种形态 |
blueprint_id | string | 否 | 同 id | 同上 | id 的别名; 两个都写时以 id 为准 |
item_sources | list<string> | 否 | 空 (不限来源) | 物品源简写, 如 minecraft-enchanted_book | 允许作为图纸的物品来源清单. 它和 matcher 必须同时满足; 两个都省略时, 这个条目永远不会命中 (BLUEPRINT_MATCH_EMPTY) |
matcher | object | 否 | 空 (不加额外条件) | 组件 / PDC / Lore 等非物品源条件 | 通用物品匹配器. 见 物品匹配器 |
amount | integer | 否 | 1 | > 0 (<= 0 使该条目解析失败, 整条配方被拒绝加载) | 需要的数量 |
item | string | 否 | 空 | 物品源简写 | 兼容键: 只有没写 item_sources 时才作为展示用的简写读取, 不参与身份推导 |
图纸不会被消耗, 只检查玩家是否持有. 你用它就能做出"要先拿到图纸才能锻造"的玩法
发货默认值: 随模块发布的 recipes/example_recipe.yml 用两个同 id 条目演示同一图纸的两种可接受形态; 可直接复制的写法见下面的同一图纸的多种形态
同一图纸的多种形态
同一种图纸有多种可以接受的形态时, 把它们写成多个 id 相同的条目, 计数按 id 加起来, 玩家持有其中任意一种就算满足:
yaml
blueprint_requirements:
# 两种形态都算"烈焰之剑图纸", 各算一份
- id: flame_sword_blueprint
item_sources:
- "minecraft-enchanted_book"
amount: 1
- id: flame_sword_blueprint
item_sources:
- "minecraft-paper"
matcher:
type: component
component: custom_name
operator: contains
value: 烈焰之剑图纸
amount: 1过去把多种形态塞进同一个 matcher 的 any_of, 现在改用这种写法
材料列表
yaml
materials:
- item_sources:
- "minecraft-iron_ingot"
amount: 3
capacity_cost: 5
effects:
- type: "variables"
variables:
physical_damage: 5
- type: "ea_attribute"
ea_attributes:
physical_attack: 5.0| 字段 | 类型 | 必填 | 默认值 | 取值范围 | 说明 |
|---|---|---|---|---|---|
material_id | string | 否 | 由 item_sources 简写派生; 无物品源时退化为 matcher 摘要 | 非空字符串 (声明了就不能为空白, 否则报 IDENTITY_BLANK) | 材料的身份键, 决定材料怎么被选中和查找; 它和 count_key / audit_id 可以各自独立设置. 见下方材料身份键 |
count_key | string | 否 | 解析出的 material_id | 非空字符串 | 计数和消耗时使用的身份键 |
audit_id | string | 否 | 解析出的 material_id | 非空字符串; 同一配方内不能被不同 material_id 共用 (报 AUDIT_ID_CONFLICT) | 写进成品 PDC 并用于刷新时查找的审计身份 |
item_sources | list<string> | 否 | 空 (不限来源) | 物品源简写, 如 minecraft-iron_ingot | 允许作为材料的物品来源清单; 没显式声明身份时, 它会参与推导材料身份. 它和 matcher 必须同时满足; 两个都省略时, 这个条目永远不会命中 (MATERIAL_MATCH_EMPTY) |
matcher | object | 否 | 空 (不加额外条件) | 组件 / PDC / Lore 等非物品源条件 | 通用物品匹配器. 见 物品匹配器 |
amount | integer | 否 | 1 | 非 0 (0 使该条目解析失败, 整条配方被拒绝加载) | 需要的数量 |
capacity_cost | number | expression | 否 | 0 | 求值后四舍五入取整, >= 0 | 这种材料占用的锻造容量. 可以写表达式或随机配置, 每次锻造时求值 |
optional | boolean | 否 | false | true / false | 这种材料是不是可选的 |
effects | list<object> | 否 | 空列表 | — | 这种材料附带的效果清单, 见材料效果 |
item | string | 否 | 空 | 物品源简写 | 兼容键: 只有没写 item_sources 时才作为展示用的简写读取, 不参与身份推导 |
item_sources 与 matcher 都不写时, 这个材料条目永远不会命中
WARNING
materials[] 的条目里不要写 id, display_name 或 description. 材料解析器看到带这三个键的节点, 会当成"不是材料定义"而返回空, 结果整条配方加载失败 (INVALID_CONFIG). 材料的身份键是 material_id
同一条配方里, 同一个 material_id 的所有条目必须用相同的 count_key, audit_id, amount 与 optional, 否则报 MATERIAL_IDENTITY_CONFLICT
发货默认值: recipes/example_recipe.yml 的 materials: 列表演示了必需材料, 可选材料, capacity_bonus, 纯 matcher 材料与"物品源 + 组件条件"材料五类写法
容量与可选材料
forge_capacity 限制这个配方允许投入的材料总容量, 你投入的所有材料的 capacity_cost 加起来不能超过这个值
yaml
forge_capacity: 35建议:
- 你给基础配方的容量小一点, 免得玩家一次投入太多, 看不懂发生了什么
- 高级配方多留一些可选材料的空间, 让玩家去追求更高品质
- 可选材料要在界面里展示清楚, 否则玩家不明白品质为什么变了
材料匹配建议
- 你用固定的
item_sources格式 ("提供者-物品ID") - 贵重材料建议开启精确匹配, 免得玩家用外观相似的假物品顶替
- 材料来自其他模块时, 先确认那个模块的加载顺序排在 Forge 之前
材料身份键
每种材料有三类可以分开设置的身份: material_id 决定材料怎么被选中和查找, count_key 决定计数和消耗, audit_id 写进成品 PDC 并用于锻造审计和刷新查找. 没填的按下面的顺序补上:
material_id先取显式写的material_id, 没写就取item_sources简写, 最后才取 matcher 内容摘要.count_key/audit_id不参与推导material_idcount_key不写时, 用推导出来的material_idaudit_id不写时, 用推导出来的material_id
纯 matcher 材料请显式写 material_id
一种材料只写 matcher, 不写 item_sources 时, 材料身份会退到 matcher 摘要 -- 随 matcher 的内容变化. 之后只要改了 matcher, 已经锻造好的物品在刷新时就可能报材料缺失
给这类材料显式写 material_id; 需要把选择, 计数消费和审计刷新分开设置时, 再分别写 count_key 与 audit_id. Forge 读旧审计记录时, 按 audit_id → material_id → count_key → 旧 material_item / source 的顺序逐个尝试; 不是完整规范格式的记录, 在成功解析后会请求刷新写回, 解析不到材料就保留原物品并告警, 不会用不完整的数据覆盖
通用物品匹配器 (matcher)
blueprint_requirements[] 和 materials[] 的判定都由两个并列字段一起决定, 两个都要满足: item_sources 只写允许的物品来源, matcher 只写组件 / PDC / Lore 这类与物品来源无关的条件. 完整语法 (包括全部类型, operator, path 和嵌套写法) 见 物品匹配器
WARNING
matcher 内部不能写物品源条件. type: item_source / item_sources / source / sources 会被解析器拒绝并告警, 该 matcher 永远不匹配
yaml
materials:
# 窄条件写在前面: 附了锋利的铁锭才吃这一条
- material_id: enchanted_iron_ingot
item_sources:
- "minecraft-iron_ingot"
matcher:
type: component
component: enchantments
path: sharpness
operator: '>='
value: 3
amount: 1
capacity_cost: 10
effects:
- type: "variables"
variables:
physical_damage: 15
# 宽条件写在后面: 普通铁锭
- item_sources:
- "minecraft-iron_ingot"
amount: 3
capacity_cost: 5上例两条材料的物品源相同, 所以窄条件那条必须显式写 material_id -- 否则两条会推导出同一个身份键, 计数会混在一起
DANGER
材料按配方里声明的顺序从上往下找, 第一个匹配上的就算, 先声明的宽条件会挡住后声明的窄条件
Forge 对每个投入的物品从上往下找第一条匹配的材料, 找到就停. 如果上例把普通铁锭那条写在前面, 附魔铁锭也会先命中它, 后面的窄条件永远轮不到
规则很简单: 窄条件写在前面, 宽条件写在后面. 图纸要求 (blueprint_requirements) 用同样的逻辑, 顺序要求一致
材料效果
材料可以附带效果 (effects), 用来在锻造成功后影响结果物品. 效果写在材料配置的 effects 列表里
效果类型
每条效果至少要写 type; 除 type 外的其他键都会被保存下来, 但真正读取的只有下表列出的键
| 字段 | 类型 | 必填 | 默认值 | 取值范围 | 说明 |
|---|---|---|---|---|---|
effects[].type | string | 是 | — | variables / ea_attribute / es_skill / name_action / lore_action / quality_modify / capacity_bonus | 效果的类型. 留空时这条效果解析失败, 整条配方被拒绝加载 |
effects[].variables | object | 否 | 空 | map<变量名, number | expression> | variables 效果的变量表. 它给锻造结果提供文本和模板用的变量值, 不写入 Attribute PDC |
effects[].ea_attributes | object | 否 | 空 | map<属性 id, number | expression> | ea_attribute 效果的属性表. 它向结果物品写入 PDC 属性, 需要安装 EmakiAttribute |
effects[].es_skills | list<string> | 否 | 空列表 | 技能 ID 列表 | es_skill 效果绑定的技能, 去掉重复后写入, 需要安装 EmakiSkills |
effects[].name_actions | list<object> | 否 | 空列表 | CoreLib 名称动作 | name_action 效果对结果物品名称执行的动作链 |
effects[].lore_actions | list<object> | 否 | 空列表 | CoreLib Lore 动作 | lore_action 效果对结果物品 Lore 执行的动作链 |
effects[].mode | string | 否 | — | force / minimum | quality_modify 的模式; 缺失或留空时整条效果被忽略 |
effects[].tier | string | 否 | — | 品质池中存在的品质名 | quality_modify 的目标品质; 缺失或留空时整条效果被忽略 |
effects[].value | number | expression | 否 | 0 | 任意数值 | capacity_bonus 带来的容量加成. 每次锻造时求值再四舍五入取整, 负值部分加总为 0 |
发货默认值: recipes/example_recipe.yml 覆盖了除 quality_modify 外的六种效果类型, 可直接对照抄写
NOTE
效果值的最终算法是 配置值 × 材料数量 × 品质倍率. 这条对 variables 和 ea_attribute 效果都适用, 但两者的含义不同: variables 只用于文本和模板, 真实属性必须写在 ea_attributes 里
variables 效果
给锻造结果注入变量值. 这些值会受品质倍率影响, 可以在 lore_actions 和 name_actions 的模板里使用
yaml
effects:
- type: "variables"
variables:
fire_damage: 10
fire_resistance: 5ea_attribute 效果
通过 EmakiAttribute 的 API 向结果物品写入结构化 PDC 属性层, 需要安装 EmakiAttribute
yaml
effects:
- type: "ea_attribute"
ea_attributes:
physical_attack: 15.0
physical_defense: 5.0现在的配置不再使用 ea_attribute_meta. 属性值的最终结果就是 配置值 × 材料数量 × 品质倍率. 没装 EmakiAttribute 时这条效果走 no-op 路径 (空操作), 锻造照常完成, 只是不写入属性
es_skill 效果
给结果物品绑定技能 ID, 需要安装 EmakiSkills
yaml
effects:
- type: "es_skill"
es_skills:
- "fire_slash"
- "flame_shield"现在推荐只用 es_skills 列表写法, 旧的单个 es_skill 字段不再推荐使用
name_action 效果
对锻造结果物品的名称执行操作, 支持 CoreLib 名称操作系统的全部动作类型
yaml
effects:
- type: "name_action"
name_actions:
- action: "prepend_prefix"
value: "<red>烈焰 </red>"
- action: "append_suffix"
value: " <gray>[锻造]</gray>"lore_action 效果
对锻造结果物品的 Lore 执行操作, 支持 CoreLib Lore 操作系统的全部动作类型
yaml
effects:
- type: "lore_action"
lore_actions:
- action: "insert_below"
anchor: "锻造属性:"
content:
- "<gray>物理伤害: <red>+%physical_damage%</red></gray>"
- "<gray>生命值: <green>+%max_health%</green></gray>"模板变量
在 name_actions 的 value 字段和 lore_actions 的 content 字段里, 可以用下面这些变量:
| 变量 | 说明 |
|---|---|
%quality% | 品质名. 只有在品质档位解析成功时才会注入 |
%quality_name% | 品质显示名, 与 %quality% 取值相同 |
%quality_multiplier% | 品质倍率, 按 0.## 格式化 |
%multiplier% | 品质倍率的简写别名 |
%变量名% | 通过 variables 效果注入的变量值, 已经乘过材料数量和品质倍率 |
quality_modify 效果
修改品质计算的结果. 支持两种模式:
| 模式 | 说明 |
|---|---|
force | 把品质直接设成指定等级, 不管随机抽到什么 |
minimum | 设置品质下限, 抽到的结果低于这个等级时, 提升到这个等级 |
yaml
effects:
- type: "quality_modify"
mode: "force"
tier: "史诗"IMPORTANT
现在推荐用字段名 tier. 旧的 quality 不再推荐使用. force 模式会跳过保底计数器
capacity_bonus 效果
带这种效果的材料, 本身的 capacity_cost 为 0, 同时给配方多加一些容量
yaml
effects:
- type: "capacity_bonus"
value: 20IMPORTANT
现在推荐用字段名 value. 旧的 amount, bonus, capacity 不再推荐使用
完整示例
yaml
id: "example_recipe"
display_name: "<gold>烈焰之剑锻造配方</gold>"
forge_capacity: 35
blueprint_requirements:
- item_sources:
- "minecraft-enchanted_book"
amount: 1
materials:
- item_sources:
- "minecraft-iron_ingot"
amount: 3
capacity_cost: 5
effects:
- type: "variables"
variables:
physical_damage: 5
max_health: 2
- type: "ea_attribute"
ea_attributes:
physical_attack: 5.0
max_health: 2.0
- type: "lore_action"
lore_actions:
- action: "insert_below"
anchor: "锻造属性:"
content:
- "<gray>物理伤害: <red>+%physical_damage%</red></gray>"
- "<gray>生命值: <green>+%max_health%</green></gray>"
- item_sources:
- "minecraft-blaze_powder"
amount: 1
capacity_cost: 10
effects:
- type: "variables"
variables:
fire_damage: 10
critical_chance: 5
- type: "ea_attribute"
ea_attributes:
fire_damage: 10.0
physical_crit_rate: 5.0
- type: "es_skill"
es_skills:
- "flame_strike"
- type: "name_action"
name_actions:
- action: "prepend_prefix"
value: "<red>烈焰 </red>"
- type: "lore_action"
lore_actions:
- action: "insert_below"
anchor: "锻造属性:"
content:
- "<red>火焰伤害: +%fire_damage%</red>"