Skip to content

Station Details

EmakiCooking provides four world stations, each with its own interaction method, state persistence, and special mechanics.

Chopping Board

Workflow

  1. Player left-clicks the chopping board block while holding an ingredient to place it on the board (consumes 1)
  2. An ItemDisplay entity spawns above the board to display the ingredient
  3. Player left-clicks the board while holding a tool (items defined in tool_sources) to cut
  4. Each cut increments cut_count, and the tool takes tool_damage durability loss
  5. When cut_count >= cuts_required, the recipe completes and results are distributed
  6. Player can right-click the board to retrieve unfinished ingredients

Interactions

ActionConditionEffect
Left-click + IngredientBoard is emptyPlace ingredient on the board
Left-click + ToolBoard has ingredientCut once
Left-click + Empty handBoard has ingredientRetrieve ingredient
Right-clickBoard has ingredientRetrieve ingredient
Break blockBoard has ingredientDrop ingredient, clear state

State File Format

Storage path: 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

Special Mechanics

  • cut_damage: Each cut has a chance% probability of dealing value damage to the player. Recipes can override the global setting via damage_override
  • interaction_delay_ms: Minimum interval between two interactions, prevents rapid clicking
  • space_restriction: When enabled, the space above the board must be an air block to interact
  • tool_sources: Only items in this list can be used as cutting tools
  • ItemDisplay: A display entity spawns above the board when an ingredient is placed, and is removed on retrieval or completion

Wok

Workflow

  1. Confirm the wok has a heat source block below it (defined in heat_levels) to determine heat level
  2. Player left-clicks while holding ingredients to add them to the wok (added in order; identical ingredients added consecutively will merge quantities)
  3. Player left-clicks while holding a spatula (spatula_sources) to stir. Each stir increments the global total_stir_count and each ingredient's stir_times
  4. After stirring is complete, player left-clicks while holding a bowl (need_bowl: true) or empty-handed (need_bowl: false) to serve
  5. The system matches a recipe and determines the result branch based on stir count and stir_rule

Interactions

ActionConditionEffect
Left-click + IngredientHas heat sourceAdd ingredient to wok
Left-click + SpatulaHas ingredientsStir once
Right-click + SpatulaHas ingredientsView wok contents
Left-click + Bowl/Empty handHas ingredients and has been stirredServe (match recipe)
Left-click + Empty handHas ingredientsRetrieve last ingredient (may take scald damage)
Break blockHas ingredientsDrop all ingredients, clear state

State File Format

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

Special Mechanics

  • heat_levels: The block below the wok determines the heat level; recipes can require a specific heat level
  • stir_rule: Each ingredient can define a stir rule (e.g., >=3); the system compares actual stir count per ingredient
  • timeout_ms: If no stir occurs within this time after the last stir, the result is burnt (overcooked)
  • Result branches: success, undercooked, overcooked, invalid
  • scald_damage: When retrieving ingredients bare-handed after stirring, the player takes scald damage
  • failure: Even if a recipe matches successfully, there is still a chance% probability of producing the failure item specified by output_source

Grinder

Workflow

  1. Player left-clicks the grinder block while holding an ingredient; the ingredient is consumed and grinding begins
  2. The system starts a background timer (at check_delay_ticks intervals) to continuously check grinding progress
  3. Smoke particle effects appear above the block during grinding
  4. After grind_time_seconds seconds, grinding completes and results are distributed
  5. Other players cannot use the same grinder during grinding

Interactions

ActionConditionEffect
Left-click + IngredientGrinder is idleStart grinding
Left-click + IngredientGrinder is busyPrompt that grinding is in progress
Break blockCurrently grindingDrop input item, clear state

State File Format

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"

Special Mechanics

  • check_delay_ticks: Background timer check interval, default 20 ticks (1 second)
  • Background Ticker: The grinder uses a BukkitTask timer that automatically cancels when there are no active grinders to save performance
  • The initiating player is automatically notified upon grinding completion if they are online

Steamer

Workflow

  1. Confirm the steamer has a heat source block below it (heat_sources)
  2. Player sneaks and right-clicks the steamer to open the GUI, then places ingredients into GUI slots
  3. Player sneaks and left-clicks the heat source block below the steamer while holding fuel to add burn time
  4. Player sneaks and left-clicks the steamer while holding a water bucket or similar item to add moisture
  5. System ticks every second: burning + has moisture → produces steam → steam drives ingredient cooking progress
  6. When an ingredient's progress reaches required_steam, it completes; the output replaces the original ingredient or drops

Interactions

ActionConditionEffect
Right-click steamerSneakingOpen steamer GUI
Left-click heat source + FuelSneakingAdd fuel, extend burn time
Left-click steamer + Water bucketSneakingAdd moisture
Left-click steamer + Empty handSneakingView steamer status info
Break blockHas contentsDrop all items, clear state

State File Format

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: { ... }    # Serialized ItemStack data
  - index: 1
    source: "minecraft-salmon"
slot_progress:
  - index: 0
    progress: 80
  - index: 1
    progress: 20

Special Mechanics

  • fuel system: Fuel provides burn time (burning_until_ms); while burning, the heat source block is ignited (campfire lit / furnace burning)
  • moisture system: Moisture is the raw material for steam; each tick consumes steam_production_efficiency units of moisture to convert into steam
  • steam system: Steam drives cooking; each tick has a base consumption of steam_consumption_efficiency, plus each ingredient consumes an additional steam_conversion_efficiency
  • reset_progress_when_steam_empty: Whether to reset all ingredient cooking progress when steam is depleted
  • GUI: Uses Bukkit native containers (default HOPPER type), configurable as CHEST with custom slot count
  • Dirty state flushing: The steamer uses an in-memory cache + periodic flush mechanism to avoid frequent IO

CookingBlockMatcher

CookingBlockMatcher is responsible for determining whether a block in the world matches a station's configured block_source.

Matching Logic

Source TypeMatching Method
VANILLACompares the block's Material with the vanilla material parsed from block_source
CRAFTENGINEDelegates to CraftEngineBlockBridge for custom block matching
ITEMSADDERDelegates to ItemsAdderBlockBridge for custom block matching
NEXODelegates to NexoBlockBridge for custom block matching
yaml
# Vanilla block example
block_source: "minecraft-oak_slab"

# CraftEngine custom block example
block_source: "craftengine-my_namespace:my_block"

# ItemsAdder custom block example
block_source: "itemsadder-my_namespace:my_block"

# Nexo custom block example
block_source: "nexo-my_block_id"

Note

Custom block types (CRAFTENGINE, ITEMSADDER, NEXO) always return false when the corresponding plugin is not installed. Make sure the required plugin is properly installed when using custom blocks for stations.


CookingRewardService

CookingRewardService handles result distribution for all stations uniformly.

Distribution Modes

ModeConditionBehavior
Dropdrop_result: true or player offlineNaturally drops items above the station
Givedrop_result: false and player onlineDirectly placed in inventory; drops if full

Output Fields

FieldTypeDescription
sourcestringItem source identifier
amountintFixed quantity (default 1)
amount_rangeobjectRandom quantity range {min, max}
chanceintOutput probability 0-100 (default 100)
actionslistAction list executed on output

Tip

amount and amount_range are mutually exclusive; when both are present, amount_range takes priority. chance is a percentage where 100 means guaranteed output.


LegacyImportService

LegacyImportService provides configuration migration capabilities from the legacy JiuWu's Kitchen to EmakiCooking 2.0.

Two Modes

ModeCommandBehavior
dryrun/ecooking convert old dryrunParses legacy config, generates import report, writes no files
apply/ecooking convert old applyBacks up current resources → writes converted recipes/station states/config updates → reloads

Import Flow

  1. Read legacy Config.yml, Recipe/, and Data.yml from the old/ directory
  2. Convert recipes: Chopping board, wok, grinder, and steamer recipes are converted to the new format respectively
  3. Convert station states: Convert legacy coordinate format to new YAML files
  4. Convert configuration: Merge legacy station settings into the new config.yml
  5. Convert display adjustments: Convert legacy item display settings to item_adjustments/ files
  6. Generate import report at data/legacy-import-report.yml

Import Report

The report contains the following statistics:

  • converted_recipe_count — Number of successfully converted recipes
  • converted_station_state_count — Number of successfully converted station states
  • skipped_count — Number of skipped entries
  • conflict_count — Number of conflicts (e.g., duplicate IDs)
  • unknown_source_count — Number of unrecognizable item sources
  • action_context_issue_count — Number of uncertain command execution contexts

Note

The apply mode automatically backs up current resources to backup/pre-import-{timestamp}/ before writing. It is recommended to run dryrun first to check the report, and only execute apply after confirming everything is correct.

Released under the GPL-3.0 License