Skip to content

Nutrition System ​

EmakiCooking provides a balanced-diet style nutrition system: eating accumulates different nutrition values, and crossing thresholds triggers the actions you configured yourself. The nutrition system only provides the mechanics (value changes, edge-triggered thresholds, persistence); gameplay such as nausea, lasting buffs, and decay is assembled by you using CoreLib actions

Basics ​

ItemValue
Master switchconfig.yml → nutrition.enabled (default true)
Type definition foldernutrition/<id>.yml
Default nutrition typesfruit, grain, protein, sugar, vegetable
Player datadata/nutrition/<player-UUID>.yml
Main permissionsemakicooking.nutrition.use, emakicooking.nutrition.admin

Nutrition type definitions ​

Each nutrition type maps to one .yml file under the nutrition/ folder; the file name (without .yml) is the default id. Five types ship by default and can be freely added or removed

FieldTypeRequiredDefaultRangeDescription
idstringNoFile name without .yml—Unique nutrition type id
display_namestringNoEquals id—Display name; an empty value falls back to the id
mindoubleNo0—Lower bound
maxdoubleNo100—Upper bound
defaultdoubleNoEquals minClamped to [min, max]Player initial value

Parsing rules:

  • If min is greater than max, they are corrected automatically (smaller becomes min, larger becomes max)
  • default is clamped to [min, max]
  • An empty display_name falls back to the id

Default nutrition/fruit.yml example:

yaml
# Nutrition type: fruit
# Player nutrition value is clamped between min and max
id: fruit
display_name: "Fruit"
min: 0
max: 100
default: 0

TIP

Single thresholds, combo thresholds, met/recover actions, and food-to-nutrition mappings are not in nutrition/*.yml. They are configured under the nutrition: section of config.yml. The nutrition/*.yml files only define these five fields of the type itself

Food-to-nutrition mapping ​

Which nutrition a food grants is configured under config.yml → nutrition.food_sources (a list)

FieldTypeRequiredDefaultRangeDescription
item_sourceslist<string>No[]CoreLib item source shorthandAllowed item sources, ANDed with the sibling matcher; the rule is skipped when both are omitted
matcherobjectNoNoneGeneral matcher; item source conditions are not allowedExtra component / PDC / lore conditions
nutritionmap<string,double>No{}nutrition-type-id: amountNutrition added on match; the rule is skipped when both this and actions are empty
actionslist<string>No[]CoreLib action stringsExtra actions run on match

item_sources and matcher are sibling fields and both must hold (AND)

Item sources use CoreLib item source prefixes: minecraft-<id>, craftengine-<id>, itemsadder-<id>, nexo-<id>, oraxen-<id>, mmoitems-<id>, neigeitems-<id>. A rule is skipped if both item_sources and matcher are empty, or if both nutrition and actions are empty

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'
    # Only a cake that was never renamed: the two fields each cover half
    - item_sources:
        - minecraft-cake
      matcher:
        type: component
        component: custom_name
        operator: absent
      nutrition:
        sugar: 40

Eating flow: the player eats an item, CoreLib identifies the item source, the food_sources rules are matched, nutrition values are added (clamped to min~max), rule actions run, and thresholds are re-evaluated. Vanilla food and CraftEngine/ItemsAdder/Nexo food implemented through the vanilla food component all go through the vanilla eating event; MMOItems and NeigeItems are wired in separately via soft dependencies and do not affect operation when absent

Threshold rules ​

Thresholds are configured under config.yml → nutrition.thresholds, split into single-type (single) and combo (combo). Both are edge-triggered: actions run once when the threshold is met, and on_recover runs once when it drops back below

Single thresholds ​

Each nutrition type is evaluated independently

FieldTypeRequiredDefaultRangeDescription
idstringNosingle_<index>—Rule id
typeslist<string>No[] (empty = all types)Registered nutrition type idsNutrition types to evaluate
valuedoubleNo0—Threshold
comparestringNo>=See the operator table below; an unrecognized value falls back to >=Comparison operator
actionslist<string>No[]CoreLib action stringsActions on meet
on_recoverlist<string>No[]CoreLib action stringsActions when dropping back below

Combo thresholds ​

Counts whether enough nutrition types are above their value

FieldTypeRequiredDefaultRangeDescription
idstringNocombo_<index>—Rule id
typeslist<string>No[] (empty = all types)Registered nutrition type idsNutrition types to count
valuedoubleNo0—Each type must reach this value to "qualify"
comparestringNo>=See the operator table below; an unrecognized value falls back to >=Comparison operator
required_countintNo5— (not validated; a non-number falls back to 5)How many types must qualify at once to trigger
actionslist<string>No[]CoreLib action stringsActions when the required count is met
on_recoverlist<string>No[]CoreLib action stringsActions when the count drops back below

Operators supported by compare and all of their accepted spellings (case-insensitive; an unrecognized value falls back to >=):

OperatorAccepted spellings
Greater or equal>=, gte, at_least, ge
Greater>, gt, greater
Less or equal<=, lte, at_most, le
Less<, lt, less
Equal==, =, eq, equal, equals
Not equal!=, <>, ne, not_equal

A rule is skipped if both actions and on_recover are empty

Assembling nausea and lasting buffs ​

The nutrition service does not hard-code nausea or buffs; it relies on CoreLib loop actions:

  • start_task sequence=<template> times=<count> interval=<interval> key=<unique-key> on_conflict=replace stop_when_offline=true: start a loop in the met actions (such as periodically draining nutrition or applying a buff)
  • stop_task key=<same-key>: cancel the loop in on_recover

Loop templates must be defined under CoreLib's config.yml → action.loop.templates, and times is capped by EmakiCoreLib's action.loop.max_times. The default "all five nutrition types full triggers nausea and decay" combo threshold:

yaml
nutrition:
  thresholds:
    combo:
      - id: overeat
        types: []          # empty = count all nutrition types
        value: 100         # each type at 100 counts as "full"
        compare: ">="
        required_count: 5  # all 5 full to trigger
        actions:
          - 'send_message text=<red>You overate and feel sick...'
          - '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=100 interval=40t key=nutrition_overeat:%caster.uuid% on_conflict=replace stop_when_offline=true'
        on_recover:
          - 'stop_task key=nutrition_overeat:%caster.uuid%'

Nutrition operation actions ​

Nutrition add/remove/set, clear/reset, threshold recheck, and recipe reward actions are registered to the CoreLib action registry by EmakiCooking and can be used in any CoreLib action chain. Current action IDs use only canonical names; historical aliases are no longer registered. The old emakicookingaddnutrition is now written cooking_add_nutrition, and the others follow the same rule. See CoreLib Actions for complete parameters

OperationAction ID
Add nutritioncooking_add_nutrition
Remove nutritioncooking_remove_nutrition
Set nutritioncooking_set_nutrition
Clear nutritioncooking_clear_nutrition
Reset nutritioncooking_reset_nutrition
Recheck thresholdscooking_recheck_nutrition_threshold
Run recipe rewardcooking_run_recipe_reward

Commands and permissions ​

See Commands & Permissions for nutrition commands. See Placeholders for nutrition placeholders

Persistence ​

  • Path: plugins/EmakiCooking/data/nutrition/<player-UUID>.yml, one file per player
  • Save timing: periodic save (nutrition.save_interval_seconds, default 300 seconds, 0 means save only on quit or shutdown), and on player quit
  • Loaded on player join; after a reload, online players are topped up with defaults for any newly added types
yaml
schema_version: 1
uuid: <player-UUID>
name: <player-name>
nutrition:
  fruit: 60
  vegetable: 40
  protein: 80
  sugar: 20
  grain: 50

Configuration overview ​

FieldTypeRequiredDefaultRangeDescription
nutrition.enabledbooleanNotruetrue / falseNutrition system master switch
nutrition.save_interval_secondsintNo300≥ 0 (seconds), values below 0 are treated as 0Periodic save interval; 0 saves only on quit or shutdown
nutrition.food_sourceslist<object>NoSample rules shippedSee "Food-to-nutrition mapping"Food-to-nutrition mapping
nutrition.thresholds.singlelist<object>NoSample rules shippedSee "Single thresholds"Single-type threshold rules
nutrition.thresholds.combolist<object>NoSample rules shippedSee "Combo thresholds"Combo threshold rules

External plugin integration ​

For nutrition-related Bukkit events see Event API: PlayerNutritionConsumeEvent (before consumption, cancellable) and NutritionThresholdChangeEvent (threshold met/recovered, informational)