English
GUI Configuration
Forge GUI configuration lives in gui/, covering the forge GUI and the recipe book GUI. These screens are not just menus: they guard input slots, handle clicks, return items, and trigger the forge flow
Files
| File | Purpose |
|---|---|
forge_gui.yml | Main screen where players forge |
recipe_book.yml | Recipe book where players inspect loaded recipes |
Both files are static resources: the startup flow creates the bundled copy when the file is missing and never rewrites an existing file
Common template fields
Templates use the CoreLib GUI template format. Top-level fields:
| Field | Type | Required | Default | Allowed values | Description |
|---|---|---|---|---|---|
id | string | Yes | — | Non-blank string | Template id, i.e. the name a recipe references through gui_template. A blank value skips the template |
gui_type | string | No | CHEST | Any Bukkit InventoryType name, case-insensitive | Container type. An unparsable value silently falls back to CHEST |
title | string | object | No | GUI | A string or a text-config object | GUI title. An object is rendered as a text config (useful for dynamic titles); a string supports MiniMessage |
rows | integer | No | 3 | 1 ~ 6 (clamped) | Row count. Only effective when the gui_type supports rows, otherwise the type decides. The bundled forge_gui uses 5 rows and recipe_book 6 |
slots | map | No | empty | Key is a slot group name | Slot group definitions, see Slot group fields. A group whose slots yields no position is dropped |
virtual_items | map | No | empty | Key is a virtual item name | Dynamic display items that occupy no slot, see Virtual items |
texts | map | No | empty | See texts copy | State copy fragments |
Shipped default (head of forge_gui.yml):
yaml
id: "forge_gui"
gui_type: CHEST
title: "<dark_gray>锻造台 - %recipe%</dark_gray>"
rows: 5A minimal copyable custom template:
yaml
id: "my_forge_gui"
gui_type: CHEST
title: "<dark_gray>My forge</dark_gray>"
rows: 6
slots:
blueprint_inputs:
slots: 10
required_materials:
slots: [19, 20, 21]
optional_materials:
slots: [28, 29, 30]
capacity_display:
slots: 16
confirm:
slots: 49Slot group fields
| Field | Type | Required | Default | Allowed values | Description |
|---|---|---|---|---|---|
slots | integer | list<integer> | Yes | — | Valid slot indexes within the container | Slots occupied by this group. A single integer or a list both work; a group that yields no position is dropped entirely |
type | string | No | Inferred from the group name | See the two slot type tables below | Functional type. When omitted it is inferred from the group name (blueprint_inputs, required_materials, optional_materials, capacity_display, confirm_button, recipe_list, prev_page, next_page, close, and so on); an uninferable group is purely decorative |
item | object | string | No | empty | An item source string, or an object with source / components | Default display item for the slot, see Item definition |
amount | integer | No | 1 | >= 1 (values below 1 are raised to 1) | Display amount used when item is not an object |
sounds | map | No | empty | See Click sounds | Click sound configuration. Unknown keys are ignored and recorded as a template issue |
Forge GUI slot types
Functional slots in forge_gui.yml driven by type (the types Forge actually reads):
| type | Purpose |
|---|---|
blueprint_inputs | Blueprint input slots. Forge matches the recipe by the inserted blueprint's item source |
required_materials | Required material input slots |
optional_materials | Optional material input slots; these consume forge capacity |
capacity_display | Shows current capacity, capacity limit, and capacity state |
confirm | Confirm-forge button (a group named confirm_button is also inferred as confirm) |
Groups without a type (the bundled top_frame, side_frame, core_frame) only fill the background
WARNING
The bundled forge_gui provides no target item slot. A target item can only be supplied by an API caller through ForgeInputs.targetItem; on the GUI path you must configure result.success.outputs on the recipe
Recipe book slot types
Functional slots in recipe_book.yml driven by type:
| type | Purpose |
|---|---|
recipe_list | Recipe entry area; slot order is the entry order |
prev_page | Previous page |
next_page | Next page |
close | Close the menu |
Item definition
When item is an object it is handled by the CoreLib configured item parser:
| Field | Type | Required | Default | Allowed values | Description |
|---|---|---|---|---|---|
item.source | string | No | blank | An item source such as anvil or minecraft-anvil | Display item source. Blank means the slot renders no item |
item.amount | integer | No | 1 | >= 1 (values below 1 are raised to 1) | Display amount |
item.components | map | No | empty | Key is a component id, value interpreted by that component | Component patches. custom_name, lore, and tooltip_display are the common ones |
item.$unset | list<string> | No | empty | Component id list | Removes the listed components |
item.$reset | list<string> | No | empty | Component id list | Resets the listed components to their defaults |
yaml
blueprint_inputs:
slots:
- 10
- 19
type: "blueprint_inputs"
item:
source: "guster_banner_pattern"
components:
custom_name: "<light_purple>Insert a blueprint</light_purple>"
lore:
- "<gray>The recipe is matched by the blueprint item source"yaml
confirm:
slots:
- 34
type: "confirm"
item:
source: "ANVIL"
components:
custom_name: "<green>Confirm forge</green>"
lore:
- "<gray>Current capacity: <yellow>%current%/%max%</yellow>"
- "<yellow>Click to run the forge"
sounds:
click:
sound: "ui.button.click"
volume: 1.0
pitch: 1.0Click sounds
Each sounds key is a click type; unknown keys are ignored:
| key | Trigger |
|---|---|
click | Any click |
left_click / right_click | Left / right click |
shift_left_click / shift_right_click | Shift + left / right click |
middle_click | Middle click |
double_click | Double click |
number_key | Number key |
swap_offhand | Swap off hand |
drop / control_drop | Drop / Ctrl + drop |
The value supports sound / volume / pitch; sound accepts a vanilla sound key or a namespaced id
Forge GUI variables
Available in the forge_gui title and in each slot's item copy:
| Variable | Description |
|---|---|
%recipe% | Display name of the currently matched recipe; 通用锻造 when no recipe matched |
%current% | Currently occupied capacity |
%max% | Capacity limit; ? when no recipe matched (limit is 0) |
%capacity_state% | Capacity state copy, taken from texts.capacity_state |
%recipe_count% | Number of candidate recipes the inserted blueprints can match |
%blueprint_requirements% | Blueprint requirement lines, one per entry; when no recipe is fixed they are grouped per recipe (at most 3 groups). The count is "amount placed in the GUI / amount required", not what is in the inventory |
texts.capacity_state has four keys, each falling back to the bundled copy when absent:
| Key | Condition | Bundled fallback |
|---|---|---|
waiting | Limit is 0 (no recipe matched yet) | <gray>等待图纸</gray> |
overflow | Current capacity exceeds the limit | <red>已超限</red> |
warning | Current capacity reaches 80% of the limit or more | <gold>接近上限</gold> |
normal | Anything else | <green>正常</green> |
Recipe book variables
Available in recipe_book slot copy:
| Variable | Description |
|---|---|
%page% | Current page number, 1-based |
%pages% | Total page count |
%recipe_name% | Recipe display name (in virtual_items.recipe_entry only) |
%recipe_id% | Recipe id (in virtual_items.recipe_entry only) |
%unlock_state% | Unlock state copy, from texts.recipe_entry.unlocked / locked |
%crafted_state% | Craft state copy, from texts.recipe_entry.crafted / uncrafted |
%click_hint% | Click hint, from texts.recipe_entry.click_hint |
Virtual items
virtual_items defines dynamic display items that occupy no fixed slot. Forge reads two:
| Field | Type | Required | Default | Allowed values | Description |
|---|---|---|---|---|---|
virtual_items.confirm_blocked.item | object | No | Bundled BARRIER copy | Same as Item definition | Display item that replaces the confirm button when capacity is exceeded |
virtual_items.recipe_entry.item | object | No | Bundled book copy | Same as Item definition | Display item of each recipe book entry |
yaml
virtual_items:
confirm_blocked:
item:
source: "BARRIER"
components:
custom_name: "<red>Cannot forge</red>"
lore:
- "<gray>Current capacity: <yellow>%current%/%max%</yellow></gray>"
- "<red>Optional material capacity is over the limit</red>"texts copy
| Field | Type | Required | Default | Allowed values | Description |
|---|---|---|---|---|---|
texts.capacity_state.waiting | string | No | <gray>等待图纸</gray> | MiniMessage text | Capacity state copy when no recipe matched |
texts.capacity_state.overflow | string | No | <red>已超限</red> | MiniMessage text | Copy when capacity exceeds the limit |
texts.capacity_state.warning | string | No | <gold>接近上限</gold> | MiniMessage text | Copy when capacity reaches 80% of the limit |
texts.capacity_state.normal | string | No | <green>正常</green> | MiniMessage text | Normal state copy |
texts.recipe_entry.unlocked | string | No | <green>可用</green> | MiniMessage text | State copy when the recipe permission is satisfied |
texts.recipe_entry.locked | string | No | <red>未解锁</red> | MiniMessage text | State copy when the recipe permission is not satisfied |
texts.recipe_entry.crafted | string | No | <green>已完成过锻造</green> | MiniMessage text | Copy for an already-crafted recipe |
texts.recipe_entry.uncrafted | string | No | <gray>尚未完成锻造</gray> | MiniMessage text | Copy for a recipe never crafted |
texts.recipe_entry.click_hint | string | No | <yellow>点击打开锻造界面</yellow> | MiniMessage text | Click hint of a recipe entry |
Player experience notes
- Write clearly in the default item copy of the blueprint and material slots what those slots accept
- Use
texts.capacity_stateto distinguish "waiting for a blueprint", "close to the limit", and "over the limit"; it reduces confusion - When capacity is exceeded,
confirm_blockedreplaces the confirm button; state the fix directly in its lore - Decorative groups separate functional areas; when adjusting the layout keep them clear of functional slot indexes