Skip to content

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 ​

FilePurpose
forge_gui.ymlMain screen where players forge
recipe_book.ymlRecipe 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:

FieldTypeRequiredDefaultAllowed valuesDescription
idstringYes—Non-blank stringTemplate id, i.e. the name a recipe references through gui_template. A blank value skips the template
gui_typestringNoCHESTAny Bukkit InventoryType name, case-insensitiveContainer type. An unparsable value silently falls back to CHEST
titlestring | objectNoGUIA string or a text-config objectGUI title. An object is rendered as a text config (useful for dynamic titles); a string supports MiniMessage
rowsintegerNo31 ~ 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
slotsmapNoemptyKey is a slot group nameSlot group definitions, see Slot group fields. A group whose slots yields no position is dropped
virtual_itemsmapNoemptyKey is a virtual item nameDynamic display items that occupy no slot, see Virtual items
textsmapNoemptySee texts copyState copy fragments

Shipped default (head of forge_gui.yml):

yaml
id: "forge_gui"
gui_type: CHEST
title: "<dark_gray>锻造台 - %recipe%</dark_gray>"
rows: 5

A 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: 49

Slot group fields ​

FieldTypeRequiredDefaultAllowed valuesDescription
slotsinteger | list<integer>Yes—Valid slot indexes within the containerSlots occupied by this group. A single integer or a list both work; a group that yields no position is dropped entirely
typestringNoInferred from the group nameSee the two slot type tables belowFunctional 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
itemobject | stringNoemptyAn item source string, or an object with source / componentsDefault display item for the slot, see Item definition
amountintegerNo1>= 1 (values below 1 are raised to 1)Display amount used when item is not an object
soundsmapNoemptySee Click soundsClick 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):

typePurpose
blueprint_inputsBlueprint input slots. Forge matches the recipe by the inserted blueprint's item source
required_materialsRequired material input slots
optional_materialsOptional material input slots; these consume forge capacity
capacity_displayShows current capacity, capacity limit, and capacity state
confirmConfirm-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:

typePurpose
recipe_listRecipe entry area; slot order is the entry order
prev_pagePrevious page
next_pageNext page
closeClose the menu

Item definition ​

When item is an object it is handled by the CoreLib configured item parser:

FieldTypeRequiredDefaultAllowed valuesDescription
item.sourcestringNoblankAn item source such as anvil or minecraft-anvilDisplay item source. Blank means the slot renders no item
item.amountintegerNo1>= 1 (values below 1 are raised to 1)Display amount
item.componentsmapNoemptyKey is a component id, value interpreted by that componentComponent patches. custom_name, lore, and tooltip_display are the common ones
item.$unsetlist<string>NoemptyComponent id listRemoves the listed components
item.$resetlist<string>NoemptyComponent id listResets 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.0

Click sounds ​

Each sounds key is a click type; unknown keys are ignored:

keyTrigger
clickAny click
left_click / right_clickLeft / right click
shift_left_click / shift_right_clickShift + left / right click
middle_clickMiddle click
double_clickDouble click
number_keyNumber key
swap_offhandSwap off hand
drop / control_dropDrop / 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:

VariableDescription
%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:

KeyConditionBundled fallback
waitingLimit is 0 (no recipe matched yet)<gray>等待图纸</gray>
overflowCurrent capacity exceeds the limit<red>已超限</red>
warningCurrent capacity reaches 80% of the limit or more<gold>接近上限</gold>
normalAnything else<green>正常</green>

Recipe book variables ​

Available in recipe_book slot copy:

VariableDescription
%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:

FieldTypeRequiredDefaultAllowed valuesDescription
virtual_items.confirm_blocked.itemobjectNoBundled BARRIER copySame as Item definitionDisplay item that replaces the confirm button when capacity is exceeded
virtual_items.recipe_entry.itemobjectNoBundled book copySame as Item definitionDisplay 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 ​

FieldTypeRequiredDefaultAllowed valuesDescription
texts.capacity_state.waitingstringNo<gray>等待图纸</gray>MiniMessage textCapacity state copy when no recipe matched
texts.capacity_state.overflowstringNo<red>已超限</red>MiniMessage textCopy when capacity exceeds the limit
texts.capacity_state.warningstringNo<gold>接近上限</gold>MiniMessage textCopy when capacity reaches 80% of the limit
texts.capacity_state.normalstringNo<green>正常</green>MiniMessage textNormal state copy
texts.recipe_entry.unlockedstringNo<green>可用</green>MiniMessage textState copy when the recipe permission is satisfied
texts.recipe_entry.lockedstringNo<red>未解锁</red>MiniMessage textState copy when the recipe permission is not satisfied
texts.recipe_entry.craftedstringNo<green>已完成过锻造</green>MiniMessage textCopy for an already-crafted recipe
texts.recipe_entry.uncraftedstringNo<gray>尚未完成锻造</gray>MiniMessage textCopy for a recipe never crafted
texts.recipe_entry.click_hintstringNo<yellow>点击打开锻造界面</yellow>MiniMessage textClick 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_state to distinguish "waiting for a blueprint", "close to the limit", and "over the limit"; it reduces confusion
  • When capacity is exceeded, confirm_blocked replaces 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