配方定义
合成配方放在 plugins/EmakiStation/recipes/ 下。一个文件一条配方,文件名不参与识别,配方 id 取文件内的 id 字段。
匹配方式是无序集合匹配:只看材料种类和总数,不看摆放位置,没有 shaped 概念。
完整示例
id: "iron_ingot_block"
display_name: "<white>铁块压制</white>"
station_ids:
- "blacksmith"
tags:
- "blacksmith"
permission: ""
visible: true
duration_seconds: 30
cost:
currency:
type: "vault"
amount: 0
materials:
- item_sources:
- "minecraft-iron_ingot"
amount: 9
consume: true
result:
outputs:
- item_source: "minecraft-iron_block"
amount: 1
actions: []
condition:
invalid_as_failure: true
entries: []
display_condition:
invalid_as_failure: false
entries: []
actions:
pre: []
success: []
failure: []字段
| 字段 | 说明 |
|---|---|
id | 配方 id。 |
display_name | 显示名,支持 MiniMessage。 |
station_ids | 声明此配方属于哪些工作站。留空表示对所有工作站开放。 |
tags | 仍可用于其他用途(如 API 查询),但不再驱动工作站归属逻辑。 |
permission | 使用该配方需要的权限,留空表示不限制。 |
visible | 是否出现在配方目录里。false 表示彻底不显示,通常配合 API 提交使用。 |
duration_seconds | 单次合成耗时(秒)。填 0 或省略表示立即完成,不进队列。 |
cost | 每次合成额外收取的货币,按倍率乘算。 |
materials | 材料需求列表。 |
result.outputs | 产物列表。 |
result.actions | 结算后执行的动作行。 |
condition | 提交前的条件门。 |
display_condition | 解锁条件。 |
actions | 各阶段动作行:pre、success、failure。 |
工作站文件的 recipes 段(include_tags / include_ids / exclude_ids)已废弃,归属关系现在由配方侧的 station_ids 声明。
没有 permission 对应权限时,配方不出现在目录里,不是显示为灰色。
cost 货币成本
| 字段 | 说明 |
|---|---|
cost.currency.type | vault、excellent(excellenteconomy 等价)。填其他值会报错并按不收费处理。 |
cost.currency.amount | 金额。省略或为 0 表示不收费;负数会报错并按不收费处理。 |
WARNING
type 和 amount 必须写在 cost.currency 子节里,不能直接挂在 cost 下。缺少 currency 子节时插件不报错,直接按不收费处理,配置会静默失效。
余额在扣材料之前先校验,扣款在扣材料之后执行;扣款失败会把材料原额退回。取消队列条目时按工作站的 cancel_refund_rate 折算退还。
materials 材料需求
| 字段 | 说明 |
|---|---|
material_id | 可选。材料选择身份;省略时按 recipe_id.material.<index> 派生。配方内与 requirement_id 重复会阻塞该配方加载。 |
requirement_id | 可选。需求记录身份;省略时回退到 material_id。 |
count_key | 可选。数量聚合/消费记录身份;省略时回退到 material_id。 |
item_sources | 「任意其一」集合,数量按集合内总数计算。省略表示不限来源。 |
matcher | 可选。通用物品匹配器,只写组件、PDC、Lore 等非物品源条件,与同级 item_sources 取 AND。见 物品匹配器。注意下方的仓库通道限制。 |
amount | 需要的总数。 |
consume | false 表示只校验持有、不扣除,用于「需要工具在手」这类需求。 |
需要 64 个时,30 个 coal 加 34 个 charcoal 也算满足。
单个配方的材料种类数不受 GUI 槽位数限制。仓库通道按 long 直扣,背包通道受原版每格 64 上限约束。
材料分配是贪心的,没有回溯。当同一个物品能满足多条需求时,会分配给先声明的那一条。极少数情况下这会让一个理论可行的配方匹配失败,拆分配方即可规避。
通用物品匹配器(matcher)
materials[] 的判定由 item_sources 与 matcher 两个同级并行字段合成,取 AND:item_sources 只写允许的物品源,matcher 只写组件、PDC、Lore 等非物品源条件。两者都省略时该材料永不命中。完整语法见 物品匹配器。
materials:
# 铁锭,且没被重命名过
- item_sources:
- minecraft-iron_ingot
matcher:
type: component
component: custom_name
operator: absent
amount: 9
consume: trueWARNING
matcher 内部不能写物品源条件。type: item_source / item_sources / source / sources 会被解析器拒绝并告警,该 matcher 恒不匹配。
声明了 matcher 的材料只能从背包供料
凡是声明了 matcher 的材料,都只能从背包供料,仓库检索会跳过它。 原因是仓库只按物品源统计库存,看不到真实物品的组件,无法证明组件条件成立。
加载期会为这类材料打一次 storage_unreachable_material WARN,看到该提示即为此原因,不是配置错误。
需要走仓库供料的材料请只写 item_sources、不写 matcher。
此外,一条配方里只要出现任意一个 matcher,整条配方的扣料就切换到栈模型:同一配方里其他只写 item_sources 的材料也一并改为背包扣料。
分解配方(recipes_dismantle/*.yml 的顶层 item_sources + matcher)没有这个限制。
两种条件门的区别
| 段 | 决定什么 | 不满足时的表现 |
|---|---|---|
condition | 能不能做 | 配方照常显示,点了会被拒绝。 |
display_condition | 解锁没有 | 配方显示为灰色占位,点击无反应。 |
用灰色占位而不是隐藏,是为了让玩家知道后面还有内容。想彻底隐藏请用 visible: false 或 permission。
display_condition 会在每次绘制目录页时求值,写得太重会拖慢界面。