Skip to content

工位详解

EmakiCooking 有四种世界工位,每种都有自己的交互方式、状态持久化逻辑和特殊机制。下面逐一说明。

砧板 (Chopping Board)

砧板是最简单的工位:放上食材,拿刀切,切够次数就出结果。

工作流程

  1. 玩家左键点击砧板方块,手持食材放置到砧板上(消耗 1 个)
  2. 砧板上方生成 ItemDisplay 实体展示食材
  3. 玩家手持工具(tool_sources 中定义的物品)左键砧板进行切割
  4. 每次切割增加 cut_count,工具受到 tool_damage 耐久损耗
  5. cut_count >= cuts_required 时,配方完成,发放结果
  6. 玩家可右键砧板取回未完成的食材

交互方式

操作条件效果
左键 + 食材砧板为空放置食材到砧板
左键 + 工具砧板有食材切割一次
左键 + 空手砧板有食材取回食材
右键砧板有食材取回食材
破坏方块砧板有食材掉落食材,清除状态

状态文件格式

每个工位的状态都会持久化到磁盘,路径为 data/stations/{world}/{x}_{y}_{z}.yml。砧板的状态文件长这样:

yaml
schema_version: 1
station_type: chopping_board
world: world
x: 100
y: 64
z: 200
input_item:
  source: "minecraft-carrot"
display_entity:
  uuid: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
timestamps:
  last_interaction_ms: 1700000000000
chopping_board:
  cut_count: 2

特殊机制

  • cut_damage:每次切割有 chance% 概率对玩家造成 value 点伤害,模拟"切到手"的效果。配方可以通过 damage_override 覆盖全局设置——比如切某些坚硬食材时伤害更高
  • interaction_delay_ms:两次交互之间的最小间隔,防止玩家快速连点刷产出
  • space_restriction:启用后砧板上方必须为空气方块才能交互,适合需要更真实感的服务器
  • tool_sources:只有列表中的物品才能作为切割工具,空手或其他物品不算
  • ItemDisplay:食材放置后在砧板上方生成展示实体,让玩家能直观看到砧板上有什么。取回或完成时自动移除

炒锅 (Wok)

炒锅是四种工位中最复杂的一个。它有食材顺序、翻炒次数、火力等级、超时烧焦等多个维度,配方的结果也不是简单的成功/失败,而是分成四个分支。

工作流程

  1. 确认炒锅下方有热源方块(heat_levels 中定义),获得火力等级
  2. 玩家左键手持食材放入炒锅(按顺序添加,相同食材连续放入会合并数量)
  3. 玩家手持锅铲(spatula_sources)左键翻炒,每次翻炒增加全局 total_stir_count 和每个食材的 stir_times
  4. 翻炒完成后,玩家手持碗(need_bowl: true 时)或空手(need_bowl: false 时)左键出锅
  5. 系统匹配配方,根据翻炒次数和 stir_rule 判定走哪个结果分支

交互方式

操作条件效果
左键 + 食材有热源添加食材到炒锅
左键 + 锅铲有食材翻炒一次
右键 + 锅铲有食材查看炒锅内容
左键 + 碗/空手有食材且已翻炒出锅(匹配配方)
左键 + 空手有食材取回最后一个食材(可能受烫伤)
破坏方块有食材掉落所有食材,清除状态

状态文件格式

yaml
schema_version: 1
station_type: wok
world: world
x: 100
y: 64
z: 200
wok:
  total_stir_count: 5
  ingredients:
    - source: "minecraft-beef"
      amount: 2
      stir_times: 5
    - source: "minecraft-carrot"
      amount: 1
      stir_times: 3
timestamps:
  last_stir_time_ms: 1700000000000
  stir_fried_time_ms: 1700000000000

特殊机制

  • heat_levels:炒锅下方方块决定火力等级。不同的热源方块对应不同的火力值,配方可以要求特定火力——比如"大火快炒"需要灵魂营火(火力 2)
  • stir_rule:每个食材可以定义翻炒规则(如 >=3),系统会逐食材比较实际翻炒次数和规则要求
  • timeout_ms:最后一次翻炒后超过此时间没有操作,视为烧焦(overcooked)。这个机制让玩家不能放着不管
  • 结果分支:success(成功)、undercooked(欠火候)、overcooked(过火)、invalid(无效)。每个分支可以配置不同的产出和动作
  • scald_damage:空手取食材时,如果已经翻炒过(锅是热的),玩家会受到烫伤伤害
  • failure:即使配方匹配成功,仍有 chance% 概率产出 output_source 指定的失败物品。这个随机失败机制可以增加烹饪的不确定性

研磨机 (Grinder)

研磨机是一个异步工位——放入食材后不需要玩家持续操作,等一段时间自动完成。

工作流程

  1. 玩家左键手持食材点击研磨机方块,食材被消耗并开始研磨
  2. 系统启动后台定时器(check_delay_ticks 间隔),持续检查研磨进度
  3. 研磨期间在方块上方生成烟雾粒子效果
  4. 经过 grind_time_seconds 秒后,研磨完成,发放结果
  5. 研磨期间其他玩家无法使用同一研磨机

交互方式

操作条件效果
左键 + 食材研磨机空闲开始研磨
左键 + 食材研磨机忙碌提示正在研磨
破坏方块正在研磨掉落输入物品,清除状态

状态文件格式

yaml
schema_version: 1
station_type: grinder
world: world
x: 100
y: 64
z: 200
input_item:
  source: "minecraft-bone"
grinder:
  recipe_id: "bone_meal"
  start_time_ms: 1700000000000
  player_uuid: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
  player_name: "Steve"

特殊机制

  • check_delay_ticks:后台定时器的检查间隔,默认 20 tick(1 秒)。调大可以减少性能开销,但完成时间的精度会降低
  • 后台 Ticker:研磨机使用 BukkitTask 定时器轮询进度。当服务器上没有任何活跃的研磨机时,定时器会自动取消以节省性能
  • 研磨完成后会自动通知在线的发起玩家。如果玩家离线,产出物品会掉落在工位上方

蒸锅 (Steamer)

蒸锅是最接近"真实烹饪"的工位,有燃料、水分、蒸汽三套资源系统,还有 GUI 操作。玩家需要同时管理燃料和水分,才能持续产生蒸汽来推进烹饪。

工作流程

  1. 确认蒸锅下方有热源方块(heat_sources
  2. 玩家潜行右键蒸锅打开 GUI,将食材放入 GUI 槽位
  3. 玩家潜行左键蒸锅下方热源方块,手持燃料添加燃烧时间
  4. 玩家潜行左键蒸锅,手持水桶等物品添加水分
  5. 系统每秒 tick:燃烧中 + 有水分 → 产生蒸汽 → 蒸汽驱动食材烹饪进度
  6. 食材进度达到 required_steam 时完成,产出替换原食材或掉落

交互方式

操作条件效果
右键蒸锅潜行打开蒸锅 GUI
左键热源 + 燃料潜行添加燃料,延长燃烧时间
左键蒸锅 + 水桶潜行添加水分
左键蒸锅 + 空手潜行查看蒸锅状态信息
破坏方块有内容物掉落所有物品,清除状态

状态文件格式

yaml
schema_version: 1
station_type: steamer
world: world
x: 100
y: 64
z: 200
steamer:
  burning_until_ms: 1700000060000
  moisture: 50
  steam: 30
  player_uuid: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
  player_name: "Steve"
gui_slots:
  - index: 0
    source: "minecraft-cod"
    item: { ... }    # 序列化的 ItemStack 数据
  - index: 1
    source: "minecraft-salmon"
slot_progress:
  - index: 0
    progress: 80
  - index: 1
    progress: 20

特殊机制

  • fuel 系统:燃料提供燃烧时间(burning_until_ms),燃烧期间热源方块会被点燃(营火点亮 / 熔炉燃烧),视觉上也能看出蒸锅在工作
  • moisture 系统:水分是蒸汽的原料。每 tick 消耗 steam_production_efficiency 单位水分转化为蒸汽。水分耗尽后蒸汽就不再产生
  • steam 系统:蒸汽驱动烹饪进度。每 tick 基础消耗 steam_consumption_efficiency,每个食材额外消耗 steam_conversion_efficiency。食材越多,蒸汽消耗越快
  • reset_progress_when_steam_empty:蒸汽耗尽时是否重置所有食材的烹饪进度。开启后玩家必须保持蒸汽不断,否则前功尽弃
  • GUI:使用 Bukkit 原生容器(默认 HOPPER 类型),支持配置为 CHEST 并自定义槽位数。槽位数决定了一次能蒸多少食材
  • 脏状态刷盘:蒸锅的状态变化非常频繁(每 tick 都在更新),所以使用内存缓存 + 定时刷盘机制,避免频繁 IO 拖慢性能

CookingBlockMatcher

CookingBlockMatcher 负责判断世界中的方块是否匹配工位配置的 block_source。这是工位交互的第一步——玩家点击一个方块时,系统需要知道它是不是某个工位。

匹配逻辑

来源类型匹配方式
VANILLA比较方块的 Materialblock_source 解析出的原版材质
CRAFTENGINE委托 CraftEngineBlockBridge 进行自定义方块匹配
ITEMSADDER委托 ItemsAdderBlockBridge 进行自定义方块匹配
NEXO委托 NexoBlockBridge 进行自定义方块匹配
yaml
# 原版方块示例
block_source: "minecraft-oak_slab"

# CraftEngine 自定义方块示例
block_source: "craftengine-my_namespace:my_block"

# ItemsAdder 自定义方块示例
block_source: "itemsadder-my_namespace:my_block"

# Nexo 自定义方块示例
block_source: "nexo-my_block_id"

注意

自定义方块类型(CRAFTENGINEITEMSADDERNEXO)在对应插件未安装时,匹配始终返回 false。如果你的工位用了自定义方块,务必确保服务器已安装对应插件。


CookingRewardService

CookingRewardService 处理所有工位的烹饪结果发放。不管是砧板切完、炒锅出锅还是研磨机磨好,最终都走这个服务。

发放模式

模式条件行为
掉落 (drop)drop_result: true 或玩家离线在工位上方自然掉落物品
给予 (give)drop_result: false 且玩家在线直接放入背包,满则掉落

产出字段

字段类型说明
sourcestring物品来源标识
amountint固定数量(默认 1)
amount_rangeobject随机数量范围 {min, max}
chanceint产出概率 0-100(默认 100)
actionslist产出时执行的动作列表

提示

amountamount_range 互斥,同时存在时 amount_range 优先。chance 为百分比,100 表示必定产出。


LegacyImportService

如果你之前用的是旧版 JiuWu's Kitchen,LegacyImportService 可以帮你把配置和数据迁移到 EmakiCooking 2.0。

两种模式

模式命令行为
dryrun/ecooking convert old dryrun解析旧版配置,生成导入报告,不写入任何文件
apply/ecooking convert old apply备份当前资源 → 写入转换后的配方/工位状态/配置更新 → 重载

导入流程

  1. old/ 目录读取旧版 Config.ymlRecipe/Data.yml
  2. 转换配方:砧板、炒锅、研磨机、蒸锅配方分别转换为新格式
  3. 转换工位状态:将旧版坐标格式转换为新版 YAML 文件
  4. 转换配置:将旧版工位设置合并到新版 config.yml
  5. 转换展示调整:将旧版物品展示设置转换为 item_adjustments/ 文件
  6. 生成导入报告至 data/legacy-import-report.yml

导入报告

报告包含以下统计信息:

  • converted_recipe_count — 成功转换的配方数
  • converted_station_state_count — 成功转换的工位状态数
  • skipped_count — 跳过的条目数
  • conflict_count — 冲突数(如重复 ID)
  • unknown_source_count — 无法识别的物品来源数
  • action_context_issue_count — 命令执行上下文不确定的数量

注意

apply 模式会在写入前自动备份当前资源到 backup/pre-import-{timestamp}/。强烈建议先跑一次 dryrun 看看报告,确认没问题再执行 apply

Released under the GPL-3.0 License