简体中文
工作站定义
stations/<id>.yml 里每个字段怎么写, 工作站怎么决定材料从哪来, 产物往哪去, 以及配方归属由谁声明
合成工作站放在 plugins/EmakiStation/stations/ 下, 一个文件就是一个工作站, 文件名与 id 一致
完整示例
yaml
id: "blacksmith"
display_name: "<gold>铁匠工坊</gold>"
layout: "station_catalog"
preview_layout: "station_preview"
queue_layout: "station_queue"
permission: ""
queue:
base_length: 3
max_length: 16
progress_mode: "offline"
cancel_refund_rate: 1.0
speed_multiplier: 1.0
allow_purchase: false
channels:
backpack: true
storage: true
default: "backpack"
output:
default: "storage_first"
player_switchable: true
condition:
invalid_as_failure: true字段
| 字段 | 类型 | 必填 | 默认值 | 取值范围 | 说明 |
|---|---|---|---|---|---|
id | string | 是 | — | — | 工作站 id, 与文件名一致. 缺失时该文件被拒绝加载 (station.station_missing_id) |
display_name | string | 否 | 取 id | MiniMessage 文本 | 界面上显示的标题名称 |
layout | string | 否 | 取 id | gui/<名字>.yml 的 id | 配方目录页使用的布局. 省略时会按工作站 id 去找布局文件, 所以示例里写的是 station_catalog |
preview_layout | string | 否 | "station_preview" | gui/<名字>.yml 的 id | 材料预览页使用的布局 |
queue_layout | string | 否 | "station_queue" | gui/<名字>.yml 的 id | 合成队列页使用的布局 |
permission | string | 否 | "" | 权限节点 | 打开这个工作站需要的权限. 留空时会自动改用 emakistation.access.<id> |
queue | 段 | 否 | 继承 config.yml 的 queue | 见下表 | 队列参数, 省略的键会继承主配置里的同名值 |
channels | 段 | 否 | 两个通道都启用 | 见下表 | 材料的来源通道 |
output | 段 | 否 | storage_first + 可切换 | 见下表 | 产物送去的方向 |
condition | 段 | 否 | 空条件 | 见下表 | 条件检查, 语法与其他 Emaki 模块一致, 见条件系统.目前这段会被解析并保存, 但运行时不会对它做判断, 所以它不会限制打开, 也不会因此被拒绝 |
三个布局文件 (layout, preview_layout, queue_layout) 一个都不能少, 缺任何一个, 启动预检都会报 missing_layout
注意, 物品分解页不属于工作站: 分解站是独立配置, 见物品分解
yaml
# 示例: 让新工作站跟随示例布局, 并单独限制权限节点
id: "alchemy"
display_name: "<light_purple>炼金台</light_purple>"
layout: "station_catalog"
preview_layout: "station_preview"
queue_layout: "station_queue"
permission: "emakistation.access.alchemy"配方归属
工作站文件里没有 recipes 段. 开放哪些配方由配方侧决定: 你在 recipes/<配方>.yml 里用 station_ids 列出所属工作站. 配方不写 station_ids, 就表示它对所有工作站开放
queue 段
你可以在工作站侧覆盖主配置 queue 段的同名键, 另外还有工作站独有的 allow_purchase 键. tick_interval 与 purchase 只能由主配置控制
| 字段 | 类型 | 必填 | 默认值 | 取值范围 | 说明 |
|---|---|---|---|---|---|
base_length | integer | 否 | 继承主配置 (3) | 1~64, 越界截断 | 本工作站的基础队列长度 |
permission_tiers | boolean | 否 | 继承主配置 (true) | true, false | 本工作站是否启用权限分档 |
max_length | integer | 否 | 继承主配置 (32) | base_length~64, 越界截断 | 本工作站的队列长度硬上限 |
progress_mode | string | 否 | 继承主配置 ("offline") | offline, online | 本工作站队首的计时方式 |
cancel_refund_rate | double | 否 | 继承主配置 (1.0) | 0.0~1.0, 越界截断 | 取消条目时材料与已付货币的退还比例 |
speed_multiplier | double | 否 | 继承主配置 (1.0) | ≤0 按 1.0 处理, 上限 100.0 | 本工作站的配方耗时倍率 |
allow_purchase | boolean | 否 | false | true, false | 这个工作站是否出售额外队列位. 还需要 config.yml 的 queue.purchase.enabled 为 true |
你取消一个条目时, 已付的货币会按 cancel_refund_rate 折算退还, 跟材料用同一个比例
channels 材料通道
| 字段 | 类型 | 必填 | 默认值 | 取值范围 | 说明 |
|---|---|---|---|---|---|
backpack | boolean | 否 | true | true, false | 是否从玩家背包取材 |
storage | boolean | 否 | true | true, false | 是否从 EmakiStorage 仓库取材. 真正启用还需要 storage.enabled 与 emakistorage:atomic_batch 能力 |
default | string | 否 | "backpack" | backpack, storage | 保留键, 当前不再生效: 源码会读取这个值, 但没有任何界面或扣料的地方真正用它 |
你把 backpack 和 storage 都关掉, 这个工作站会被拒绝加载 (station.station_no_channel). 这样的配置能打开, 却永远用不了, 所以插件宁可在启动时就报错
两个都开着时, 材料来自「背包加仓库」合并成的一个池子, 优先扣背包. 你看不到通道切换按钮, 也不需要切换, 界面里显示的「拥有」就是两边合计
default 留着只是为了让旧配置文件不报未知键, 后续版本可能移除. 别把它当作可用配置
output 产物去向
| 字段 | 类型 | 必填 | 默认值 | 取值范围 | 说明 |
|---|---|---|---|---|---|
default | string | 否 | "storage_first" | storage_first, backpack_first, storage_only, backpack_only | 默认的产物去向. 填了无法识别的值会改回 storage_first |
player_switchable | boolean | 否 | true | true, false | 玩家能不能在界面里切换自己的产物去向偏好. 关掉后点 output_toggle 没有效果 |
default 四个取值的含义, 以及玩家可切换后的实际效果:
| 值 | 行为 |
|---|---|
storage_first | 优先进仓库, 满了退到背包 |
backpack_first | 优先进背包, 满了退到仓库 |
storage_only | 只用仓库 |
backpack_only | 只用背包 |
所有去处都放不下时, 这条产物会进入「待领取」状态, 不会掉落, 也不会销毁
condition 条件门
工作站文件里的 condition 采用 CoreLib 的通用条件块, 字段与条件系统一致
目前运行时不会对工作站级别的条件做判断: 这段会被解析, 保存, 并在启动预检时做一次结构校验, 但你打开工作站 (/emakistation open 或 API openGui) 时不会检查它, 条件不满足也不会被拒绝. 下面列出可以写的键, 方便你按未来版本的含义先把配置写好
| 字段 | 类型 | 必填 | 默认值 | 取值范围 | 说明 |
|---|---|---|---|---|---|
condition.type | string | 否 | all_of | all_of, any_of, none_of, at_least, exactly | 条件的组合方式. 填了无法识别的值会改回 all_of |
condition.entries | list | 否 | [] | 字符串表达式, type: expression 节点, 嵌套条件组 | 条件节点的列表. 为空时整个条件组一直算作 true |
condition.required_count | integer | 否 | 0 | 非负整数 | at_least / exactly 下需要满足的条件数量 |
condition.invalid_as_failure | boolean | 否 | true | true, false | 条件配置写错或算不出结果时, 是否算作失败 |
condition.on_pass.actions | list<string> | 否 | [] | 动作管道行 | 条件通过后要执行的动作. 目前不执行 |
condition.on_fail.actions | list<string> | 否 | [] | 动作管道行 | 条件失败后要执行的动作. 目前不执行 |
condition.on_fail.block_output | boolean | 否 | false | true, false | 条件失败时是否拦下产物输出. 工作站不产出产物, 所以没有实际作用 |
condition.on_fail.message | string | 否 | "" | MiniMessage 文本 | 条件失败时发给玩家的提示. 目前不发送 |