Recipes
Cooking recipes are grouped by station. Each station has different fields because the gameplay flow is different. Keep recipes in station-specific folders so permissions, balancing, and result items remain easy to maintain.
Recipe folders
| Folder | Station | Typical use |
|---|---|---|
recipes/chopping_board/ | Chopping Board | Single input, repeated cuts, sliced output. |
recipes/wok/ | Wok | Multiple ingredients, heat, stirring, and failure branches. |
recipes/grinder/ | Grinder | Input item plus processing time. |
recipes/steamer/ | Steamer | Input item plus steam or progress requirement. |
recipes/oven/ | Oven | Single input resolved by baking time, perfect heat ratio, and overbake stage. |
recipes/juicer/ | Juicer | Single input pressed into fluid, then bottled by serving capacity. |
recipes/fermentation_barrel/ | Fermentation Barrel | Multiple inputs resolved by fermentation time, early collection, and over-fermentation. |
Common fields
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique recipe id. Prefer matching the file name. |
display_name | MiniMessage string | Yes | Name shown in menus, messages, and logs. |
permission | string | No | Permission required to use the recipe. |
input / inputs / ingredients | object/list | Yes | Required items, using CoreLib Item Source. |
result.<branch>.outputs | list | Yes | Current recommended result-output list. Use a list even for one output item. |
result.<branch>.actions | list | No | Current recommended action list, placed beside outputs under the result branch. |
completion_conditions / condition nodes | list/object | No | Extra checks before a recipe can enter the success/result branch. |
structured_presentation | object | No | Optional CoreLib structured presentation config. |
Result branch structure
Current Cooking recipes use the unified result.<branch>.outputs/actions structure:
result:
success:
outputs:
- item_sources:
- "minecraft-baked_potato"
amount: 1
actions:
- "sendmessage text=\"<gold>Cooking complete.</gold>\""Rules:
outputsis always a list, even when there is only one output item.actionsis placed besideoutputsunder the same result branch.- Wok recipes can use branches such as
success,undercooked,overcooked, andinvalid. - Oven recipes can use branches such as
success,perfect, andoverbaked. - Fermentation barrel recipes can use
success,early, andover.fermentation.early_collect.min_progress_ratioandfermentation.over_time_secondsonly control timing; outputs still belong underresult.earlyandresult.over. - Old forms such as
result.output,result.outputs,result.actions,perfect_output,overbaked_output,fermentation.early_collect.output, andfermentation.over_outputare not the current recommended forms.
Item sources
Inputs and outputs use CoreLib Item Source. Prefer stable short ids or explicit source objects:
input:
item_sources:
- minecraft-wheatProject short forms may also be used:
input: mc-wheat
output: emaki_item-noodleThe old minecraft:wheat colon format is not recommended because it can conflict with namespace parsing rules from other plugins.
Chopping board example
id: sliced_potato
display_name: '<yellow>Sliced Potato'
permission: emakicooking.recipe.sliced_potato
input:
source: vanilla
id: POTATO
amount: 1
cuts_required: 4
output:
source: vanilla
id: BAKED_POTATO
amount: 1
actions:
complete:
- 'sendmessage <green>The potato has been sliced.'| Field | Description |
|---|---|
input | Item placed on the chopping board. |
cuts_required | Required cut count. Keep it reasonable to avoid repetitive fatigue. |
output | Result after cutting completes. |
Grinder example
id: wheat_flour
display_name: '<white>Wheat Flour'
input:
source: vanilla
id: WHEAT
amount: 3
grind_time_seconds: 8
output:
source: emaki_item
id: wheat_flour
amount: 1
actions:
start:
- 'playsound BLOCK_GRINDSTONE_USE 0.8 1.2'
complete:
- 'sendmessage <gray>Grinding complete.'| Field | Description |
|---|---|
grind_time_seconds | Processing time. Test it together with TPS and player wait time. |
actions.start | Actions executed when grinding starts. |
actions.complete | Actions executed when grinding completes. |
Steamer example
id: steamed_fish
display_name: '<aqua>Steamed Fish'
input:
source: vanilla
id: COD
amount: 1
required_steam: 100
output:
source: vanilla
id: COOKED_COD
amount: 1required_steam is the accumulated steam/progress requirement. Higher values take longer and should be shown in the GUI for valuable recipes.
Wok example
id: fried_rice
display_name: '<gold>Fried Rice'
ingredients:
- source: vanilla
id: WHEAT
amount: 2
- source: vanilla
id: EGG
amount: 1
heat_level:
min: 2
max: 4
stir_total: 6
fault_tolerance: 1
result:
success:
outputs:
- source: emaki_item
id: fried_rice
amount: 1
undercooked:
outputs:
- source: vanilla
id: WHEAT
amount: 1
overcooked:
outputs:
- source: vanilla
id: CHARCOAL
amount: 1
invalid:
outputs:
- source: vanilla
id: BOWL
amount: 1Wok fields
| Field | Description |
|---|---|
ingredients | Ingredient list. |
heat_level.min | Minimum valid heat level. |
heat_level.max | Maximum valid heat level. |
stir_total | Required number of stirs. |
fault_tolerance | Allowed mistakes before the recipe fails. |
result.success.outputs | Outputs for correct operation. |
result.undercooked.outputs | Outputs when heat or progress is too low. |
result.overcooked.outputs | Outputs when heat is too high. |
result.invalid.outputs | Outputs for invalid ingredients or state. |
Oven example
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:
- "sendmessage text=\"<gold>Baking complete.</gold>\""
perfect:
outputs:
- item_sources:
- "minecraft-golden_carrot"
amount: 1
overbaked:
outputs:
- item_sources:
- "minecraft-charcoal"
amount: 1
structured_presentation: {}Oven fields
| Field | Description |
|---|---|
input | Item inserted into the oven. |
bake_time_seconds | Base time required to finish baking. |
baking.perfect_heat.min | Minimum heat counted as perfect. |
baking.perfect_heat.max | Maximum heat counted as perfect. |
baking.perfect_required_ratio | Required ratio of perfect-heat time to total baking time. |
baking.overbake_seconds | Time after completion before the recipe enters overbake stage. |
result.success.outputs | Normal completion outputs; branches such as perfect and overbaked use the same outputs/actions structure. |
The oven records the baking stage. After base time is reached, the item can be collected; if it keeps heating, it can enter the overbaked stage. For valuable food, use a narrower perfect heat range and show current heat in the GUI.
Juicer example
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:
- "sendmessage text=\"<aqua>Juicing complete.</aqua>\""
structured_presentation: {}Juicer fields
| Field | Description |
|---|---|
input | Item that can be pressed. |
presses_required | Number of operations required for one press cycle. |
fluid.id | Fluid id used to prevent mixing different fluids. |
fluid.display_name | Fluid name shown in GUI and messages. |
fluid.amount_ml | Fluid amount added to the station after each completed press. |
container.item_sources | Containers that can bottle this fluid. |
container.serving_ml | Fluid consumed by one serving. Falls back to station default_serving_ml if omitted. |
result.success.outputs | Output items given after bottling. |
For example, the default apple juice adds 180ml per press, while a glass bottle needs 250ml. One press is not enough to bottle; the player must accumulate more fluid. The station should only contain one fluid.id at a time to avoid mixing different drinks.
Fermentation barrel example
id: "apple_cider"
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"
result:
success:
outputs:
- item_sources:
- "minecraft-honey_bottle"
amount: 1
actions:
- "sendmessage text=\"<gold>Fermentation complete.</gold>\""
early:
outputs:
- item_sources:
- "minecraft-potion"
amount: 1
actions:
- "sendmessage text=\"<yellow>You collected a half-fermented apple drink.</yellow>\""
over:
outputs:
- item_sources:
- "minecraft-honey_bottle"
amount: 1
actions:
- "sendmessage text=\"<gold>The cider continued fermenting into a sweet vinegar.</gold>\""
structured_presentation: {}Fermentation barrel fields
| Field | Description |
|---|---|
inputs | Multiple required input items. |
fermentation_time_seconds | Time required for normal completion. |
fermentation.early_collect.min_progress_ratio | Minimum progress ratio for early collection. |
fermentation.over_time_seconds | Time after normal completion before over-fermentation. |
result.early.outputs | Outputs for early collection. |
result.over.outputs | Outputs for the over-fermented branch. |
result.success.outputs | Normal completion outputs. |
Fermentation barrels are useful for “time for value” gameplay: early collection gives a weaker result, normal completion gives the target result, and over-fermentation can turn it into a byproduct or failed result.
Permissions and presentation
Recipes may define permission. If a recipe book or menu is used, show locked or level-gated states to the player. structured_presentation can hand result display to CoreLib structured presentation.
structured_presentation:
enabled: true
template: cooking_result
placeholders:
difficulty: 'Normal'
station: 'Wok'Balancing tips
- Keep low-level recipes to one or two ingredients.
- Wok
fault_toleranceshould not be too strict, otherwise network latency amplifies failures. - Oven perfect heat ranges should not be too narrow unless the GUI clearly shows current heat.
- Match juicer
fluid.amount_mlwithserving_mlso players do not press many times without being able to serve. - Early fermentation output should be clearly weaker than the normal output.
- High-value recipes can be gated by permissions, station tier, rare ingredients, and long progress.
- If results interact with attributes, skills, or strengthening, prefer EmakiItem or PDC data over lore-only identification.
Testing checklist
Test correct ingredients, wrong ingredients, missing permission, full inventory, station reload, and fast clicking for every recipe. Also test every wok branch; oven low heat, perfect heat, and overbake; juicer insufficient fluid, enough fluid, wrong container, and mixed-fluid attempts; fermentation early collection, normal completion, and over-fermentation.
Troubleshooting
Recipe does not load
Check file extension, YAML indentation, duplicated id, correct station folder, and console load logs.
Correct material does not match
Check Item Source type, id case, amount, and PDC matching rules. If another plugin modified the item, inspect the item with a debug command first.
Wok always fails
Check whether heat_level, stir_total, and fault_tolerance are too strict, and verify GUI/interaction code writes heat and stir state correctly.
Oven never completes
Check whether station heat is in the configured advancing range, whether fuel remains, and whether bake_time_seconds is too high.
Juicer cannot bottle
Check whether accumulated fluid reaches container.serving_ml, and whether the held container matches container.item_sources or station defaults.
Fermentation result is unexpected
Check the current fermentation stage. Not reaching early ratio, normal completion, and passing over_time_seconds all affect output selection.