Skip to content

EmakiStation ​

用大白话认识 EmakiStation: 它是做什么的, 你会用到哪些文件, 以及第一次打开工作站要敲哪几条命令

EmakiStation 是 Emaki 系列的通用合成工作站. 你按配方投入材料, 材料排进队列, 到点就能领取产物, 整条流程都做成了一个可以自由配置的界面工作站. 它还附带一套独立的分解站

合成侧一共有三页界面 (配方目录 → 材料预览 → 合成队列). 队列按顺序一个接一个推进, 同一时刻只有排在最前面的条目在做. 材料从「背包和仓库」合并成的一个池子里扣除, 装了 EmakiStorage 后仓库也会参与供料; 产物按配置送到仓库或背包, 两边都放不下时会进入待领取状态, 既不会掉落, 也不会销毁

基本信息 ​

项目值
模块版本1.1.8
API 坐标emaki.jiuwu.craft:emaki-station-api:1.1.7
主类emaki.jiuwu.craft.station.EmakiStationPlugin
主命令/emakistation
别名/estation, /est
硬依赖EmakiCoreLib
软依赖EmakiStorage, PlaceholderAPI
描述符基线api-version: "26.1", folia-supported: true
JavaJava 25
主要权限emakistation.use (默认 true), emakistation.purchase (默认 true), emakistation.dismantle (默认 true), emakistation.reload (op), emakistation.debug (op), emakistation.admin (op)

这里有一组容易混淆的版本号, 先分清: 模块本体和默认 config.yml 的版本值都是 1.1.8, API 构件另为 1.1.7. 源码里的 AppConfig.CURRENT_VERSION = "1.0.2" 是配置迁移用的结构常量, 跟前两者用途不同, 不要混用

功能页面 ​

页面内容
命令与权限/emakistation 的 9 个功能子命令 (另有 help), 6 个权限节点与两个访问权限前缀
配置详解config.yml 的 queue, limits, storage, persistence, gui 五段, 含全部键与默认值
工作站定义stations/<id>.yml 的布局, 权限, 队列参数, 材料通道, 产物去向与条件检查
配方定义recipes/<配方>.yml 的归属, 材料, 产物, 耗时, 货币成本, 动作段与两种条件检查
合成队列队列长度的三个来源, 逐个推进, 取消退还与待领取状态
付费队列位queue_costs.yml 的档位, 逐格计价, 三道开关与 unlocks.yml 已购存档
物品分解独立分解站与分解配方的 item_sources, rolls, pool 权重抽取
界面模板四份 GUI 模板的槽位类型, 占位符全集与「必须显式写 type:」的约束
API 与集成emaki-station-api 的门面, 查询与操作接口及线程约束
事件 APIStationCraftSubmitEvent, StationCraftCancelEvent, StationCraftCompletedEvent

核心能力 ​

  • 无序集合匹配: 配方只数材料的种类和总数, 不看放在哪一格, 也没有摆放形状的概念. item_sources 是「任意其一」集合, 数量按集合内总数计算 -- 需要 64 个时, 30 个 coal 加 34 个 charcoal 也算满足
  • 背包与仓库合并供料: 两个通道都开启时, 材料来自合并后的一个池子, 优先扣背包. 你看不到通道切换按钮, 界面里显示的「拥有」就是两边合计
  • 串行单线队列: 你在一个工作站只有一条队列, 同一时刻只有排在最前面的条目在推进. waiting 与 running 占用队列长度, pending_claim 不占用
  • 队列长度三来源: 队列能排多长由三样东西决定: 基础长度, emakistation.queue.<n> 权限档, 付费购买. 权限档取代基础长度, 付费额度叠加在其上, 最终统一被 max_length 截断
  • 产物永不丢失: 所有配置的去处都放不下时, 条目转为待领取, 等你用 /emakistation claim 或界面按钮领取
  • 分解站完全独立: 分解站与合成站 ID 互不关联, 各自在 stations_dismantle/ 与 recipes_dismantle/ 目录加载, 不是工作站的第四页

文件结构 ​

服务器跑起来后, EmakiStation 主要用到下面这些文件:

text
plugins/EmakiStation/
├─ config.yml
├─ queue_costs.yml
├─ stations/
│  └─ blacksmith.yml
├─ recipes/
│  └─ example_recipe.yml
├─ stations_dismantle/
│  └─ example_dismantle_station.yml
├─ recipes_dismantle/
│  └─ example_dismantle_recipe.yml
├─ gui/
│  ├─ station_catalog.yml
│  ├─ station_preview.yml
│  ├─ station_queue.yml
│  └─ station_dismantle.yml
├─ data/
│  └─ <玩家 UUID>/
│     └─ unlocks.yml
└─ lang/
   ├─ zh_CN.yml
   └─ en_US.yml
路径说明
config.yml主配置, 管队列默认值, 容量上限, 仓库通道, 持久化与界面刷新限制
queue_costs.yml付费队列位的档位. 属于业务数据文件, 只在缺失时释放一次, 版本升级不会覆盖管理员改过的内容
stations/<id>.yml合成工作站定义, 文件名与 id 一致
recipes/<配方>.yml合成配方定义, 一个文件一条配方, 归属由配方侧的 station_ids 声明
stations_dismantle/<id>.yml分解站定义, 与合成站互不关联
recipes_dismantle/<配方>.yml分解配方定义, 含输入物品与产物概率池
gui/*.yml四份界面模板: 配方目录, 材料预览, 合成队列, 分解界面
data/<玩家 UUID>/unlocks.yml每个玩家已购队列位的存档, 由插件自动维护, 额度为空时不生成该文件. 见付费队列位
lang/*.yml命令, 界面, 启动预检与控制台里的文案

快速开始 ​

  1. 先把 EmakiCoreLib-*.jar 与 EmakiStation-*.jar 放入服务器 plugins/
  2. 不要把 emaki-station-api-*.jar 放进 plugins/; API Jar 只给开发者当编译依赖用
  3. 首次启动后, 打开 plugins/EmakiStation/config.yml 和示例工作站 stations/blacksmith.yml 看一眼
  4. 打开示例工作站:
text
/emakistation open blacksmith
  1. 想看自己的队列, 或者领取产物, 用这两条:
text
/emakistation queue
/emakistation claim
  1. 改完配置后, 重载让它生效:
text
/emakistation reload

使用提示 ​

  • 注意, 工作站的 channels.backpack 与 channels.storage 不能同时为 false, 否则这个工作站会被拒绝加载. 这样的配置能打开, 却永远用不了, 插件宁可在启动时就报错
  • channels.default 是保留键, 现在已经不生效了. 通道合并之后, 「停在哪个通道」这件事就不存在了; 插件仍会读取这个值, 但没有任何地方真正用到它, 留着只是为了让旧配置不报未知键
  • 想用仓库通道, 光有 storage.enabled: true 还不够, EmakiStorage 还得提供 emakistorage:atomic_batch 能力 (一批操作要么全做, 要么全不做的批量接口). 缺这个能力时插件不会改成逐个取出, 因为那会让材料在你的背包里闪现一次
  • 注意 progress_mode: offline 只表示「计时继续」, 不表示「离线发货」. 离线期间到点的条目只是到了期, 真正结算发生在玩家下次上线时
  • 三份布局文件 (layout, preview_layout, queue_layout) 一个都不能少, 缺任何一份, 启动预检都会报 missing_layout
  • 确定性最大流材料分配: 你点提交时, 插件把背包里的一堆堆物品与仓库里的库存一起放进一张分配图, 在全部需求之间寻找一套能同时满足的完整分配, 不再依赖配方声明顺序. 约束更窄的 matcher 材料会优先参与建图, 但最终仍然以整体上能不能分配为准; 如果分配失败, 说明当前候选材料确实无法同时满足全部需求
  • 尚未接通的功能: EmakiStation 目前不注册任何动作段 id, 也不注册 PlaceholderAPI 扩展. 配方里的 actions.pre / success / failure, result.actions, 以及工作站与分解站级别的 condition, 都会被解析并保存, 但目前没有执行入口; limits.batch_multiplier_max 同样只被解析, 不参与校验. 想看细节, 见配方定义, 工作站定义, 物品分解与配置详解