Skip to content

GUI System

CoreLib provides GUI templates, open requests, session management, slot control, and click handling. Business modules reuse this infrastructure instead of implementing inventory events from scratch.

Used by

ModuleUsage
EmakiForgeForge GUI, recipe book.
EmakiStrengthenStrengthening GUI, material slots, protection slots.
EmakiGemInlay, extraction, socket opening, and upgrade GUI.
EmakiSkillsSkill panel and trigger-selection GUI.
EmakiCookingSteamer, oven, juicer, and fermentation-barrel GUI.
EmakiAttributeAttribute point allocation GUI.
EmakiItemItem repair GUI.
EmakiLevelLevel panel and leaderboard GUI.
EmakiStoragePaged warehouse GUI.

gui.backend in plugins/EmakiCoreLib/config.yml decides how every Emaki menu is presented:

ValueDescription
bukkitDefault. Opens a real server-side container and needs no extra plugin.
packetCoreLib's built-in packet-based virtual menu. It reuses the same window when the row count changes, so the cursor is not reset. Requires PacketEvents; falls back to bukkit when it is missing.
autoUses packet when PacketEvents is installed, otherwise bukkit.

The default stays bukkit, so upgrading CoreLib does not change existing menu behaviour.

Template fields

FieldTypeRequiredDescription
idstringYesTemplate id used by the module. A blank id makes the whole template parse as invalid.
titlestring/objectNoInventory title. MiniMessage strings and TextConfig objects are supported. Defaults to the literal GUI.
gui_typestringNoContainer type, given as a Bukkit InventoryType name. Defaults to CHEST; an invalid value falls back to CHEST silently. When the type does not support custom rows, rows is forced to 0.
rowsintegerNoInventory rows. Defaults to 3 and is clamped into 16, i.e. 9–54 slots.
slotsmapNoSlot definitions keyed by slot name. Omitting it yields an empty map rather than an error.

Slot fields

FieldTypeDescription
keystringSlot key used by business code.
slotslist<number>Inventory indexes covered by this slot definition.
typestringBusiness type label, such as input, output, button, or decoration.
itemobjectShared item definition containing source, amount, and components. Without source, it can act as a pure patch for a runtime item.
soundsmapClick sounds keyed by click type.

Unified item structure

New configs and bundled defaults only write the nested canonical structure:

yaml
item:
  source: minecraft-anvil
  amount: 1
  components:
    custom_name: '<green>Confirm</green>'
    lore:
      - '<gray>Click to execute</gray>'
    item_model: emaki:confirm
    enchantment_glint_override: true
    $unset:
      - repairable
    $reset:
      - attribute_modifiers
  • source accepts every ItemSource shorthand registered in CoreLib; availability depends on the corresponding resolver/plugin.
  • A normal component value means SET; $unset removes a component and $reset restores the material prototype default.
  • Component IDs must be valid namespaced keys. IDs without a namespace default to minecraft:, while explicit namespaces are preserved; the same rule applies to $unset / $reset entries. Unknown IDs and invalid values for supported components are configuration errors.
  • Known components introduced after the current server version are skipped with a warning without linking newer typed classes.
  • Third-party sources are cloned first so source identity, PDC, and unknown components survive; only patches that Paper can safely transfer are applied.
  • Legacy item: <source> plus top-level components, display_name, and lore are still readable compatibility inputs. When both forms exist, nested item wins.
  • Real player-provided targets, materials, and business outputs remain controlled by session state and are not overwritten by template display items.

Automatic migration of legacy GUI item fields

Starting with CoreLib 4.5.11, shared gui/*.{yml,yaml} files undergo a pure structural migration before normal YamlDocument loading and GuiTemplateParser parsing. The migration walks candidate configured-item nodes throughout the document, including regular slots and module-specific containers such as pages/buttons and virtual_items.

The mapping follows the runtime LegacyConfiguredItemConverter contract:

  • Legacy material, item_source / item_sources, and scalar item sources move to item.source; amount moves to item.amount.
  • Legacy display_name, item_name, lore, custom_model_data, enchantments, item_flags, hidden_components, unbreakable, and related display fields move to item.components.
  • Existing canonical item.source, item.amount, and component values win. Legacy values never overwrite modern values in mixed files.
  • A candidate containing components.raw or item.components.raw is skipped as a whole so opaque raw component payloads are not rewritten.
  • Slot layout, sounds, actions, pagination rules, and other non-target business fields remain unchanged. Running the migration again produces no further changes.

Before a changed batch is committed, every original file is backed up under the relevant plugin data directory at migration-backups/configured-item-format/<timestamp>/, preserving its path relative to the gui/ source directory. The migrated YAML is written to a sibling temporary file and parsed again before replacement. If writing, validation, or replacement fails, the original remains intact or is restored from the batch backup, and GUI loading does not continue with an unverified migrated result. BoostedYAML preserves comments on untouched business nodes where its comment model allows, but a full configuration backup is still recommended before production upgrades.

This compatibility layer does not read version values from config.yml, language files, or plugin descriptors, and it is not version-gated. It runs solely when legacy fields are present. The implementation is contained in CoreLib's item.migration.configureditem package, with GuiTemplateLoader as the only GUI production bridge, so it can be removed as a unit after the compatibility window without leaving legacy rules in YamlFiles, YamlDirectoryLoader, or canonical parsers.

Click types

TypeDescription
CLICKGeneric click, used as the fallback when no specific type matches.
LEFTCLICKLeft click.
RIGHTCLICKRight click.
SHIFT_LEFTCLICKShift + left click.
SHIFT_RIGHTCLICKShift + right click.
MIDDLECLICKMiddle click.
DOUBLECLICKDouble click.
NUMBER_KEYNumber-key hotbar swap.
SWAP_OFFHANDOffhand swap key (F by default).
DROPDrop key (Q by default).
CONTROL_DROPCtrl + drop key.

Every type above can be used as a sounds key.

Sound lookup has three levels: an exact match on the current click type first; then one retry through the legacy mapping (SHIFT_LEFTCLICK and DOUBLECLICK fall back to LEFTCLICK, SHIFT_RIGHTCLICK falls back to RIGHTCLICK); only then does it fall back to CLICK.

GUI sessions

A GUI session records the state of the menu a player currently has open. CoreLib manages sessions itself; business modules handle interaction logic through the GuiSessionHandler interface.

A session tracks:

  • Which recipe or flow the player is working on.
  • Which slots are input slots (items may be placed) and which forbid taking items out.
  • Which business flow a button click should invoke.
  • Whether input items must be returned when the menu closes.
  • Temporary state data for the current menu.

The point of the session is to stop players duplicating items or bypassing a flow through rapid clicking, shift-clicking, dragging, or an abnormal close.

Slot index reference

Slot indexes for a six-row inventory:

text
Row 1:  0  1  2  3  4  5  6  7  8
Row 2:  9 10 11 12 13 14 15 16 17
Row 3: 18 19 20 21 22 23 24 25 26
Row 4: 27 28 29 30 31 32 33 34 35
Row 5: 36 37 38 39 40 41 42 43 44
Row 6: 45 46 47 48 49 50 51 52 53

Frequently used positions:

  • Centre of a six-row menu: 22 (middle of row 3) or 31 (middle of row 4).
  • Bottom centre: 49.
  • Corners: 0, 8, 45, 53.

MiniMessage and colours

Use MiniMessage consistently for GUI text:

yaml
item:
  source: minecraft-smithing_table
  components:
    minecraft:custom_name: '<gold>Legendary Forge'
    minecraft:lore:
      - '<gray>Insert the blueprint, materials, and target gear.'
      - '<yellow>Click to start forging.'
      - ''
      - '<dark_gray>Cost: <white>500 coins'

Common MiniMessage tags:

TagEffect
<red>Red text
<green>Green text
<gold>Gold text
<gray>Grey text
<dark_gray>Dark grey text
<yellow>Yellow text
<aqua>Aqua text
<bold>Bold
<italic>Italic
<strikethrough>Strikethrough
<gradient:gold:yellow>Gradient

Where a module still accepts legacy colour codes (&a, §b), migrate to MiniMessage over time to keep one style.

Editing advice

  1. Change display text first.
  2. Then move decorative slots.
  3. Adjust functional slots only after confirming the layout.
  4. Test shift-click, drag, double-click, close handling, and full-inventory cases after each GUI change.