简体中文
物品分解
分解站的定义怎么写, 分解配方有哪些字段, 输入怎么匹配, 产物怎么按权重抽取
分解站与合成工作站完全独立: 两者的 ID 互不关联, 各自在自己的目录里加载. 分解不是工作站的第四页
text
/emakistation dismantle <工作站>打开分解站需要 emakistation.dismantle, 以及该分解站的访问权限 (配置留空时会自动改用 emakistation.dismantle.access.<id>)
分解没有输入槽: 打开界面时插件会扫描你的背包, 取第一件能匹配某条可用分解配方的物品, 并选中对应配方. 背包里没有能匹配的物品时, 界面不会打开, 返回 station.dismantle_no_matching_item. 你点了确认才真正消耗 1 个输入物品, 随后按 rolls 的次数从 pool 里随机抽取产物; 再点一次确认 (这时按钮已经变成领取) 会把产物送到配置好的去向. 界面里的输入图标只是这条配方的输入预览, 你不需要也不允许往里放物品
分解站定义
放在 plugins/EmakiStation/stations_dismantle/ 下, 文件名与 id 一致
yaml
id: "example_dismantle"
display_name: "<aqua>示例分解台</aqua>"
layout: "station_dismantle"
permission: ""
output:
default: "storage_first"| 字段 | 类型 | 必填 | 默认值 | 取值范围 | 说明 |
|---|---|---|---|---|---|
id | string | 是 | — | — | 分解站 id, 与文件名一致. 缺失时该文件被拒绝加载 (station.dismantle_station_missing_id) |
display_name | string | 否 | 取 id | MiniMessage 文本 | 界面上显示的标题名称 |
layout | string | 否 | "station_dismantle" | gui/<名字>.yml 的 id | 界面布局. 缺失时启动预检报 missing_layout |
permission | string | 否 | "" | 权限节点 | 打开该分解站需要的权限. 留空时会自动改用 emakistation.dismantle.access.<id> |
output.default | string | 否 | "storage_first" | storage_first, backpack_first, storage_only, backpack_only | 产物送去的方向, 取值与合成工作站一致. 填了无法识别的值会改回 storage_first |
condition | 段 | 否 | 空条件 | 见条件系统 | 条件检查.目前会被解析并保存, 但运行时不会对它做判断, 不会限制打开 |
注意, 分解站没有 queue 段, 没有 channels 段, 没有 preview_layout / queue_layout, 也没有 output.player_switchable. 分解是即时结算的, 不进队列
yaml
# 示例: 产物只进仓库的分解站
id: "scrap_yard"
display_name: "<gray>废料场</gray>"
layout: "station_dismantle"
output:
default: "storage_only"产物投递失败时的现状
分解产物按 output.default 送出去. 当配置的目标都放不下时, 目前的实现会把这次已经抽到的产物清空, 不会进入待领取状态, 也不会写到文件. 开放分解玩法前, 请确认玩家的仓库或背包还有余量, 或者把 output.default 设成更宽裕的取值
分解配方定义
放在 plugins/EmakiStation/recipes_dismantle/ 下. 一个文件一条配方, 文件名不影响加载, 配方 ID 由文件内的 id 字段决定
yaml
id: "example_dismantle"
display_name: "<yellow>铁块分解示例</yellow>"
station_id: ""
tags:
- "blacksmith"
permission: ""
item_sources:
- "minecraft-iron_block"
rolls:
min: 2
max: 3
pool:
- item_source: "minecraft-iron_ingot"
amount:
min: 2
max: 4
weight: 6.0
- item_source: "minecraft-iron_nugget"
amount: 3
weight: 3.0| 字段 | 类型 | 必填 | 默认值 | 取值范围 | 说明 |
|---|---|---|---|---|---|
id | string | 是 | — | — | 配方 id. 缺失时该文件被拒绝加载 (station.dismantle_recipe_missing_id) |
display_name | string | 否 | 取 id | MiniMessage 文本 | 界面上显示的名称 |
station_id | string | 否 | "" | 单个分解站 id | 绑定的分解站, 单数形式. 留空时不限定工位, 任何分解站都可以使用这条配方 |
tags | list<string> | 否 | [] | 字符串列表 | 目前的实现只解析并保存这个字段, 没有任何地方读取它. 工位绑定只看 station_id |
item_sources | list<string> | 否 (与 input_source 至少写一个) | [] | 物品源 token (连字符写法) | 输入物品的来源列表, 当前写法. 背包里的物品必须匹配其中一个 (若同时写了 matcher, 还要满足 matcher) |
input_source | string | 否 (与 item_sources 至少写一个) | — | 单个物品源 token | 旧写法. 仍然兼容读取, 但加载时会告警 dismantle_recipe_legacy_input_source, 建议改用 item_sources. 和 item_sources 同时出现会被拒绝 (station.recipe_source_field_conflict) |
matcher | 段/object | 否 | — | 通用物品匹配器 | 顶层匹配器, 按组件, PDC, Lore 这类条件判断输入, 和 item_sources 取且的关系. 见物品匹配器 |
rolls | integer | 段 | 否 | 1 | 整数 ≥1, 或 min/max 均 ≥1 | 每次分解的投掷次数. 两种写法都含两端 |
pool | list | 是 | — | 非空列表 | 产物的概率池. 为空时整条配方会被拒绝加载 (station.dismantle_recipe_empty_pool) |
permission | string | 否 | "" | 权限节点 | 使用这条配方需要的权限. 留空表示不限制 |
condition | 段 | 否 | 空条件 | 见条件系统 | 条件检查.目前会被解析并保存, 但分解流程不会对它做判断, 条件不满足也不会阻止分解 |
两个键 (item_sources 和 input_source) 都没写, 或者写了空值时, 配方会被拒绝加载, 并报 station.dismantle_recipe_no_input
用 matcher 判定输入
顶层 matcher 让分解配方可以按物品数据挑输入, 例如只拆解被摔过的装备:
yaml
id: "damaged_gear_dismantle"
# item_sources 仍必填, 且与 matcher 一起参与判定
item_sources:
- "minecraft-iron_chestplate"
matcher:
type: component
component: damage
operator: '>'
value: 0
rolls: 1
pool:
- item_source: "minecraft-iron_nugget"
amount: 2
weight: 1.0matcher 与 item_sources 取"且"关系
item_sources 和 matcher 是且的关系: item_sources 必须匹配, matcher (如果写了) 再追加判断, 两者都成立才能分解. 输入来源是必填项 (item_sources 是当前写法, 旧键 input_source 仍兼容读取但会告警). 上面的例子只拆解「铁胸甲且被摔过」的物品
所以要表达「某种物品 且 满足组件条件」, 你只要把物品源写进 item_sources, 组件条件写进 matcher
matcher 内部仍然不能补物品源条件 (type: item_source / item_sources / source / sources 会被拒绝并告警, 这个 matcher 永远不会匹配). 物品源只写在顶层 item_sources
NOTE
分解侧没有合成侧那种「matcher 材料不走仓库」的限制: 分解只看你背包里的实际物品, 不涉及仓库供料
完整语法见物品匹配器
rolls 投掷次数
两种写法:
yaml
# 固定次数
rolls: 3yaml
# 范围 (含两端)
rolls:
min: 2
max: 4每次投掷互相独立, 每次都从 pool 里按权重抽一项. 你把 min 写成小于 1 会按 1 处理, max 小于 min 时按 min 处理
pool 产物概率池
| 字段 | 类型 | 必填 | 默认值 | 取值范围 | 说明 |
|---|---|---|---|---|---|
pool[].item_source | string | 是 | — | 单个物品源 token | 产物来源, 单数, 一项写一个来源. 空值会跳过这一项; 解析不了的 token 报 station.dismantle_recipe_bad_source 并跳过这一项 |
pool[].amount | integer | 段 | 否 | 1 | 整数 ≥1, 或 min/max 均 ≥1 | 数量, 可以写固定值或 min / max 范围; 越界都按大于等于 1 处理 |
pool[].weight | double | 否 | 1.0 | >0 | 相对权重. 不合法的值 (<= 0 或解析不了) 会改回 1.0 |
与合成配方的差异
| 维度 | 合成配方 | 分解配方 |
|---|---|---|
| 工作站绑定 | station_ids (复数列表) | station_id (单数, 留空则不限定工位) |
| 输入 | materials (多条需求, 每条一个 item_sources 集合) | item_sources (来源列表, 从背包自动匹配, 无输入槽) |
| 产出 | result.outputs 固定清单 | pool 按 weight 随机抽取 |
| 耗时 | duration_seconds, 进队列 | 无耗时, 即时结算 |
| 货币成本 | cost | 无 |
| 条件门 | condition (提交时求值) + display_condition (目录绘制时求值) | 只有 condition, 且目前不做判断 |
| 阶段动作 | actions.pre / success / failure (目前不执行) | 无 |