Skip to content

Recipes

EmakiCooking recipes are stored by station under plugins/EmakiCooking/recipes/<station>/. Each station has its own gameplay flow, so each recipe type has different fields: chopping boards use input amount and cut counts, woks use stirring and heat, ovens use baking stages, juicers use fluid volume, and fermentation barrels use time stages.

Recipe folders

FolderStationTypical use
recipes/chopping_board/Chopping BoardSingle input, accepts the whole main-hand stack, then uses input amount and repeated cuts for sliced output.
recipes/wok/WokMultiple ingredients, heat, stirring, and failure branches.
recipes/grinder/GrinderInput item plus processing time.
recipes/steamer/SteamerInput item plus steaming time or chained steps.
recipes/oven/OvenSingle input resolved by baking time, perfect heat ratio, and overbake stage.
recipes/juicer/JuicerSingle input pressed into fluid, then bottled by serving capacity.
recipes/fermentation_barrel/Fermentation BarrelMultiple inputs resolved by fermentation time, early collection, and over-fermentation.

Current default resources use CoreLib Item Source lists and result branches:

yaml
result:
  success:
    outputs:
      - item_sources:
          - "minecraft-baked_potato"
        amount: 1
    actions:
      - 'send_message text="<gold>Cooking complete.</gold>"'

Rules:

  • Inputs and outputs should use item_sources lists, such as minecraft-carrot or minecraft-glass_bottle.
  • result.<branch>.outputs is always a list, even for one output item.
  • result.<branch>.actions is placed beside outputs under the same result branch.
  • Do not use old examples such as output, result.output, result.outputs, result.actions, perfect_output, overbaked_output, fermentation.early_collect.output, or fermentation.over_output.

Common fields

FieldRequiredDescription
idYesUnique recipe id. Prefer matching the file name.
display_nameYesDisplay name. Supports MiniMessage.
permissionNoPermission required to use this recipe. Empty means no gate.
conditionNoCompletion/collection condition block. Can include on_pass.actions, on_fail.actions, and on_fail.block_output.
availability_conditionNoCondition block deciding whether the recipe is available at all. Unlike condition, it is evaluated during matching: if it fails, the recipe does not take part in matching.
structured_presentationNoRecipe-level structured presentation config. An output entry may carry its own outputs[].structured_presentation; the two layers are merged, with the output level overriding the recipe level.
result.<branch>.outputsYesOutput list for this branch.
result.<branch>.outputs[].chanceNoDrop chance for this output, 0-100, default 100. <=0 never grants it, >=100 always does. Each output is rolled independently.
result.<branch>.outputs[].amount_rangeNoRandom amount range, written as the min / max subkeys. When present it overrides amount; if min > max the two are swapped automatically.
result.<branch>.actionsNoActions executed when this branch outputs.

General item matcher

Every input-side field in Cooking accepts a matcher that narrows item selection further by component, PDC, or lore. Full syntax is in Item Matcher.

Every matching position is item_sources AND matcher

Recipe inputs and station roles now follow the same rule. Each matching position holds two sibling fields: item_sources for the allowed item sources, matcher for non-item-source conditions (component, PDC, lore, variable). Both must hold; either may be omitted, and only omitting both makes the position never match. That is why the bare item_sources examples on this page all work.

Item source conditions must not be written inside matcher. type: item_source / item_sources / source / sources are rejected at load time with a warning, and such a matcher never matches. The same ban applies to all_of / any_of / none_of child lists.

Station roles now nest their pair under a child node — stations.chopping_board.tool, stations.wok.spatula, stations.juicer.container, stations.steamer.moisture_rules[].input — each holding a standard item_sources + matcher. The old flat keys (tool_matcher, spatula_matcher, container_matcher, input_matcher) are still read at load time for compatibility, but write the nested form in new configs. See Stations.

Fermentation barrel inputs[] keeps item_sources for a second reason too: that key doubles as the slot aggregation key. See How matcher relates to item_sources.

Config pathPurpose
ingredients[].matcherRecipe ingredients.
inputs[].matcherInputs of a multi-input recipe.
input.matcherInput of a single-input recipe.
container.matcherContainer item such as a bottle.
stations.chopping_board.tool.matcherTool detection.
stations.wok.spatula.matcherSpatula detection.
stations.juicer.container.matcherStation container detection.
stations.oven.fuels[].matcherOven fuel (config.yml).
stations.steamer.fuels[].matcherSteamer fuel (config.yml).
stations.steamer.moisture_rules[].input.matcherSteamer moisture rule input (config.yml).
nutrition.food_sources[].matcherFood-to-nutrition mapping (config.yml, see Nutrition).

Each path pairs with an item_sources at the same level.

yaml
id: fresh_carrot_slice
ingredients:
  # "is a carrot" AND "was never renamed", written as two sibling fields
  - item_sources:
      - "minecraft-carrot"
    matcher:
      type: component
      component: custom_name
      operator: absent
    amount: 1
result:
  success:
    outputs:
      - item_sources:
          - "minecraft-golden_carrot"
        amount: 1

DANGER

The block side and the output side do not support matchers.

  • Station block detection (fields such as block_item_sources) decides which block counts as the station; it is not input matching.
  • The output side (result.<branch>.outputs[].item_sources) creates items rather than matching them.

A matcher in either place has no effect. See Only input-matching fields support matcher.

Result branches

StationCommon branches
Chopping Boardsuccess
Grindersuccess
Steamersuccess; chained recipes may continue through steps.
Woksuccess, undercooked, overcooked, invalid
Ovensuccess, perfect, overbaked
Juicersuccess
Fermentation Barrelsuccess, early, over

When condition.on_fail.block_output is true, a failed condition blocks output. When it is false, output can still happen but fail actions run. For fermentation barrels, automatic completion and block-break drops may happen while the player is offline; source behavior is authoritative in those cases.

Chopping board example

yaml
id: "cut_carrot"
display_name: "Cut Carrot"

input:
  item_sources:
    - "minecraft-carrot"
  amount: 2

cuts_required: 1
tool_damage: 1

result:
  success:
    outputs:
      - item_sources:
          - "minecraft-golden_carrot"
        amount: 1
    actions:
      - 'send_message text="<green>Chopping complete.</green>"'
FieldDescription
input.item_sourcesRequired (at least one of this and input.matcher). Matching input sources.
input.amountInput amount required and consumed for each completed cut cycle. Defaults to 1.
cuts_requiredRequired. Click count required to complete one cut cycle.
tool_damageDurability damage applied to the tool per cut.
damage_override.chanceOverrides config.yml > stations.chopping_board.cut_damage.chance for this recipe.
damage_override.valueOverrides config.yml > stations.chopping_board.cut_damage.value for this recipe.

damage_override is optional; when omitted, the global cut_damage settings from config.yml are used.

When a player places input on a chopping board, the board takes the whole main-hand stack and stores the accumulated amount in station state; the display entity still shows only one item. Cutting cannot start until the stored amount reaches input.amount. With cuts_required: 1, players can continuously process an already placed batch without re-placing one ingredient at a time.

Wok example

yaml
id: "example_recipe"
display_name: "Simple Stew"

ingredients:
  - item_sources:
      - "minecraft-carrot"
    amount: 1
    stir_rule: "1-3"
  - item_sources:
      - "minecraft-cooked_chicken"
    amount: 1
    stir_rule: "2-3"

heat_level: 1

stir_total:
  min: 2
  max: 5

fault_tolerance: 0
permission: "emakicooking.recipe.simple_stew"

condition:
  type: all_of
  entries:
    - "%player_level% >= 5"
  on_pass:
    actions:
      - 'send_message text="<green>Cooking skill check passed.</green>"'
  on_fail:
    actions:
      - 'send_message text="<red>Cooking skill level is too low.</red>"'
    block_output: true

result:
  success:
    outputs:
      - item_sources:
          - "minecraft-rabbit_stew"
        amount: 1
    actions:
      - 'send_message text="<green>Served successfully.</green>"'
  undercooked:
    outputs:
      - item_sources:
          - "minecraft-mushroom_stew"
        amount: 1
    actions: []
  overcooked:
    outputs:
      - item_sources:
          - "minecraft-dried_kelp"
        amount: 1
    actions: []
  invalid:
    outputs:
      - item_sources:
          - "minecraft-stone"
        amount: 1
    actions: []
FieldDescription
ingredientsRequired. Ingredient list; the recipe refuses to load without it.
ingredients[].item_sourcesMatching ingredient sources.
ingredients[].amountRequired amount.
ingredients[].stir_ruleSuggested add/stir interval, such as 1-3.
heat_levelRequired. Required heat level.
stir_total.min/maxBoth subkeys required. Valid total stir count range.
fault_toleranceRequired. Allowed mistake count.

Grinder example

yaml
id: "bone_meal"
display_name: "Ground Bone Meal"

input:
  item_sources:
    - "minecraft-bone"

grind_time_seconds: 6

permission: "emakicooking.recipe.bone_meal"

result:
  success:
    outputs:
      - item_sources:
          - "minecraft-bone_meal"
        amount: 3
    actions:
      - 'send_message text="<gray>Grinding finished.</gray>"'
FieldDescription
input.item_sourcesRequired (at least one of this and input.matcher). Matching input sources.
grind_time_secondsRequired. Seconds required to grind. The grinder advances on the config.yml > stations.grinder.check_delay_ticks cycle.

Steamer example

yaml
id: "steamed_cod"
display_name: "Steamed Cod"

input:
  item_sources:
    - "minecraft-cod"

required_steam: 40

permission: "emakicooking.recipe.steamed_cod"

result:
  success:
    outputs:
      - item_sources:
          - "minecraft-cooked_cod"
        amount: 1
    actions:
      - 'send_message text="<aqua>Steaming finished.</aqua>"'
FieldDescription
input.item_sourcesRequired (at least one of this and input.matcher). Matching input sources.
required_steamRequired. Total steam that must be consumed to finish the recipe.
requires_previous_stepOptional. Another steamer recipe ID marking this recipe as its follow-up step, used for chained steaming.

Chained example: recipes/steamer/chain_example_recipe.yml uses requires_previous_step: "example_recipe" to feed the previous output into the next step.

Oven example

yaml
id: "baked_potato"
display_name: "Baked Potato"

input:
  item_sources:
    - "minecraft-potato"

bake_time_seconds: 20

baking:
  perfect_heat:
    min: 45
    max: 60
  perfect_required_ratio: 0.7
  overbake_seconds: 10

permission: "emakicooking.recipe.baked_potato"

result:
  success:
    outputs:
      - item_sources:
          - "minecraft-baked_potato"
        amount: 1
    actions:
      - 'send_message text="<gold>Baking complete.</gold>"'
  perfect:
    outputs:
      - item_sources:
          - "minecraft-golden_carrot"
        amount: 1
  overbaked:
    outputs:
      - item_sources:
          - "minecraft-charcoal"
        amount: 1

Required fields for an oven recipe are id, display_name, input.item_sources (or input.matcher), and bake_time_seconds; the recipe refuses to load if any of them is missing. The baking block is optional.

The oven chooses output by baking time, perfect heat ratio, and continued heating after completion. For valuable food, show heat and progress clearly in the GUI so players understand why an item became overbaked.

Juicer example

yaml
id: "apple_juice"
display_name: "Apple Juice"

input:
  item_sources:
    - "minecraft-apple"

presses_required: 5

fluid:
  id: "apple_juice"
  display_name: "Apple Juice"
  amount_ml: 180

container:
  item_sources:
    - "minecraft-glass_bottle"
  serving_ml: 250

permission: "emakicooking.recipe.apple_juice"

result:
  success:
    outputs:
      - item_sources:
          - "minecraft-honey_bottle"
        amount: 1
    actions:
      - 'send_message text="<aqua>Juicing complete.</aqua>"'

Required fields for a juicer recipe are id, display_name, input.item_sources (or input.matcher), and presses_required; the recipe refuses to load if any of them is missing.

Each completed press adds fluid.amount_ml to the station. Bottling consumes container.serving_ml. For example, the default apple juice adds 180ml per press while a bottle needs 250ml, so one press is not enough to serve once.

Fermentation barrel example

yaml
id: "example_recipe"
display_name: "Apple Cider"

inputs:
  - item_sources:
      - "minecraft-apple"
    amount: 3
  - item_sources:
      - "minecraft-sugar"
    amount: 1

fermentation_time_seconds: 300

fermentation:
  early_collect:
    min_progress_ratio: 0.5
  over_time_seconds: 600

permission: "emakicooking.recipe.apple_cider"

condition:
  type: all_of
  entries:
    - "%player_level% >= 3"
  on_pass:
    actions:
      - 'send_message text="<green>Fermentation matured.</green>"'
  on_fail:
    actions:
      - 'send_message text="<yellow>Extra fermentation condition failed.</yellow>"'
    block_output: false

result:
  success:
    outputs:
      - item_sources:
          - "minecraft-honey_bottle"
        amount: 1
    actions:
      - 'send_message text="<gold>Fermentation complete.</gold>"'
  early:
    outputs:
      - item_sources:
          - "minecraft-potion"
        amount: 1
    actions:
      - 'send_message text="<yellow>You collected a half-fermented apple drink.</yellow>"'
  over:
    outputs:
      - item_sources:
          - "minecraft-honey_bottle"
        amount: 1
    actions:
      - 'send_message text="<gold>The cider continued fermenting into a sweet vinegar.</gold>"'
FieldDescription
inputsRequired. Multiple required inputs; each entry uses sibling item_sources + matcher, ANDed.
inputs[].slot_idPersisted slot identity. It must be non-blank and unique within the recipe; do not reuse it for another material when editing a recipe.
inputs[].count_keyQuantity aggregation and consumption identity. Multiple stable slots may share one key, but the key must remain stable.
inputs[].matcherOptional non-item-source condition, ANDed with the sibling item_sources.
fermentation_time_secondsRequired. Time required for normal completion.
fermentation.early_collect.min_progress_ratioMinimum progress ratio for early collection.
fermentation.over_time_secondsTime after normal completion before over-fermentation.
result.early.outputsOutputs for early collection; each output uses scalar item_source.
result.over.outputsOutputs for the over-fermented branch; each output uses scalar item_source.
result.success.outputsNormal completion outputs; each output uses scalar item_source.

Debugging and validation

  • Use /ecooking reload after editing recipes.
  • Use /ecooking inspect hand to verify whether the held item can be resolved by Item Source.
  • Test each recipe with missing permission, missing ingredients, full inventory, correct branch, failure branch, and station state after server restart.
  • For woks, test success, undercooked, overcooked, and invalid.
  • For ovens, test normal completion, perfect completion, and overbaking.
  • For juicers, test insufficient fluid, wrong container, and mixed-fluid attempts.
  • For fermentation barrels, test early collection, normal completion, and over-fermentation.