Skip to content

营养系统 ​

EmakiCooking 的营养系统如下: 玩家吃东西会累积不同类型的营养值, 达到或跌破阈值时触发你配好的动作

EmakiCooking 有一套类似膳食均衡的营养系统: 玩家进食会累积不同类型的营养值, 达到或跌破阈值时触发你自己配置的动作. 这套系统只提供机制 (增减值, 越过阈值时触发, 数据保存), 反胃, 持续 BUFF, 营养衰减这些具体玩法要你自己用 CoreLib 动作拼出来

基本信息 ​

项目值
总开关config.yml → nutrition.enabled (默认 true)
类型定义目录nutrition/<id>.yml
默认营养类型fruit, grain, protein, sugar, vegetable
玩家数据data/nutrition/<玩家UUID>.yml
主要权限emakicooking.nutrition.use, emakicooking.nutrition.admin

营养类型定义 ​

每个营养类型对应 nutrition/ 目录下的一个 .yml 文件, 文件名 (去掉 .yml) 作为 id 的默认值. 默认发布 5 个类型, 可任意增删

字段类型必填默认值取值范围说明
idstring否文件名 (去 .yml)—营养类型唯一标识
display_namestring否等于 id—显示名; 为空时回退为 id
mindouble否0—下限
maxdouble否100—上限
defaultdouble否等于 min截断到 [min, max]玩家初始值

解析规则:

  • 若 min 大于 max 会自动纠正 (取较小为 min, 较大为 max)
  • default 会被截断到 [min, max]
  • display_name 为空时回退为 id

默认 nutrition/fruit.yml 示例:

yaml
# 营养类型: 水果
# 玩家营养值会被限制在 min ~ max 之间
id: fruit
display_name: "水果"
min: 0
max: 100
default: 0

TIP

单类型阈值, 组合阈值, 达成/恢复动作, 食物到营养的映射都不在 nutrition/*.yml 里, 而是配置在 config.yml 的 nutrition: 段. nutrition/*.yml 只定义类型本身的这 5 个字段

食物到营养的映射 ​

食物吃下后增加哪些营养, 配置在 config.yml → nutrition.food_sources (列表)

字段类型必填默认值取值范围说明
item_sourceslist<string>否[]CoreLib 物品来源简写允许的物品来源列表. 与同级 matcher 取 AND, 两者都省略则该规则被跳过
matcherobject否无通用 matcher; 不得写物品源条件组件 / PDC / Lore 等附加条件
nutritionmap<string,double>否{}营养类型id: 增加值命中后增加的营养值. 与 actions 同时为空时该规则被跳过
actionslist<string>否[]CoreLib 动作字符串命中后额外执行的动作

item_sources 与 matcher 是同级并行字段, 判定取 AND: 两者都写时要同时成立才命中

物品来源使用 CoreLib 物品来源前缀: minecraft-<id>, craftengine-<id>, itemsadder-<id>, nexo-<id>, oraxen-<id>, mmoitems-<id>, neigeitems-<id>. 若 item_sources 与 matcher 同时为空, 或 nutrition 与 actions 同时为空, 该规则被跳过

yaml
nutrition:
  food_sources:
    - item_sources:
        - minecraft-apple
        - minecraft-sweet_berries
      nutrition:
        fruit: 20
    - item_sources:
        - minecraft-cake
        - minecraft-cookie
      nutrition:
        sugar: 30
      actions:
        - 'play_sound sound=entity.player.burp volume=1.0 pitch=1.0'
    # 只要没被改过名的蛋糕: 两个字段各写一半
    - item_sources:
        - minecraft-cake
      matcher:
        type: component
        component: custom_name
        operator: absent
      nutrition:
        sugar: 40

进食触发链: 玩家吃下物品 → CoreLib 识别物品来源 → 匹配 food_sources 规则 → 增加营养值 (截断到 min~max) → 执行规则动作 → 重新评估阈值. 原版食物以及通过原版 food 组件实现的 CraftEngine, ItemsAdder, Nexo 食物都走原版进食事件; MMOItems, NeigeItems 通过软依赖单独接入, 未安装时不影响运行

阈值规则 ​

阈值配置在 config.yml → nutrition.thresholds, 分单类型 (single) 和组合 (combo) 两类. 两类都在越过阈值的那一刻触发: 达成时执行一次 actions, 从满足跌回不足时执行一次 on_recover

单类型阈值 single ​

逐个营养类型独立判定

字段类型必填默认值取值范围说明
idstring否single_<下标>—规则 id
typeslist<string>否[] (空=全部类型)已注册的营养类型 id参与判定的营养类型
valuedouble否0—阈值
comparestring否>=见下方运算符表; 无法识别的值回退为 >=比较运算符
actionslist<string>否[]CoreLib 动作字符串达成时执行的动作
on_recoverlist<string>否[]CoreLib 动作字符串跌回不足时执行的动作

组合阈值 combo ​

统计达标的营养类型数量是否达到要求

字段类型必填默认值取值范围说明
idstring否combo_<下标>—规则 id
typeslist<string>否[] (空=全部类型)已注册的营养类型 id参与统计的营养类型
valuedouble否0—每个类型达到该值才算"已达标"
comparestring否>=见下方运算符表; 无法识别的值回退为 >=比较运算符
required_countint否5— (源码未校验, 非数字时按 5)需要多少个类型同时达标才触发
actionslist<string>否[]CoreLib 动作字符串达标数量满足时执行的动作
on_recoverlist<string>否[]CoreLib 动作字符串达标数从满足跌回不足时执行的动作

compare 支持的运算符及其全部别名 (大小写不敏感, 无法识别的值回退为 >=):

运算符可写形式
大于等于>=, gte, at_least, ge
大于>, gt, greater
小于等于<=, lte, at_most, le
小于<, lt, less
等于==, =, eq, equal, equals
不等于!=, <>, ne, not_equal

若 actions 与 on_recover 都为空, 该规则被跳过

反胃与持续 BUFF 的拼装方式 ​

营养服务本身不写死反胃或 BUFF, 而是依赖 CoreLib 循环动作拼装:

  • start_task sequence=<模板> times=<次数> interval=<间隔> key=<唯一key> on_conflict=replace stop_when_offline=true: 在达成动作里启动循环 (如周期性扣营养, 周期性加 BUFF)
  • stop_task key=<同一key>: 在 on_recover 里取消循环

循环模板需在 CoreLib 的 config.yml → action.loop.templates 下定义. 下面是默认的"五大营养全满则反胃衰减"组合阈值示例:

yaml
nutrition:
  thresholds:
    combo:
      - id: overeat
        types: []          # 空=统计全部营养类型
        value: 100         # 每类达到 100 算"已满"
        compare: ">="
        required_count: 5  # 5 类同时满才触发
        actions:
          - 'send_message text=<red>你吃得太撑了,开始反胃……'
          - 'play_sound sound=entity.player.burp volume=1.0 pitch=0.8'
          - 'give_potion_effect type=NAUSEA level=1 duration=200'
          - 'start_task sequence=nutrition_decay times=999999 interval=40t key=nutrition_overeat:%player_name% on_conflict=replace stop_when_offline=true'
        on_recover:
          - 'stop_task key=nutrition_overeat:%player_name%'

营养操作动作 ​

营养增减, 清空, 重置, 阈值复查与配方奖励动作由 EmakiCooking 注册到 CoreLib 的动作注册表, 可在任意 CoreLib 动作链中使用. 当前 Action ID 只使用规范名, 不再注册旧别名; 完整参数见 CoreLib 动作

操作Action ID
增加营养值cooking_add_nutrition
扣除营养值cooking_remove_nutrition
设置营养值cooking_set_nutrition
清空营养值cooking_clear_nutrition
重置营养值cooking_reset_nutrition
复查阈值cooking_recheck_nutrition_threshold
执行配方奖励cooking_run_recipe_reward

命令与权限 ​

营养相关命令见 命令与权限. 营养相关占位符见 占位符参考

持久化 ​

  • 路径: plugins/EmakiCooking/data/nutrition/<玩家UUID>.yml, 每个玩家一个文件
  • 保存时机: 定时保存 (nutrition.save_interval_seconds, 默认 300 秒, 0 表示只在退出或关服时保存), 玩家退出时也会保存一次
  • 玩家加入时加载; 重载后会给在线玩家补齐新增类型的默认值
yaml
schema_version: 1
uuid: <玩家UUID>
name: <玩家名>
nutrition:
  fruit: 60
  vegetable: 40
  protein: 80
  sugar: 20
  grain: 50

配置项一览 ​

字段类型必填默认值取值范围说明
nutrition.enabledboolean否truetrue / false营养系统总开关
nutrition.save_interval_secondsint否300≥ 0 (秒), 小于 0 按 0定时保存的间隔, 0 表示仅退出或关服时保存
nutrition.food_sourceslist<object>否发货给出示例见"食物到营养的映射"食物到营养的映射
nutrition.thresholds.singlelist<object>否发货给出示例见"单类型阈值"单类型阈值规则
nutrition.thresholds.combolist<object>否发货给出示例见"组合阈值"组合阈值规则

外部插件接入 ​

营养相关的 Bukkit 事件见 事件 API: PlayerNutritionConsumeEvent (消费前, 可取消), NutritionThresholdChangeEvent (阈值达成/恢复, 信息型)