Skip to content

GUI Template ​

The window template plugins/EmakiAccessory/gui/accessory_gui.yml covers what each cell type does, what happens when you click it, and which checks run when the window closes. The accessory panel is described by that file

Slots Must Declare type Explicitly ​

Accessory cells must declare type: "accessory_slot" explicitly; a cell without type is nothing but decoration

Available Types ​

typePurpose
accessory_slotAn accessory cell. The key name must equal a slot instance id
orphan_slotAn orphan cell showing accessories from slots the page no longer declares, for retrieval
page_enableAn enable cell. Clicking makes the current page the active one; only the active page's accessories take effect
page_switchA switch cell. The key name must equal the target page's page_id; clicking opens that page

One layout can be shared by several pages: gui_template in pages/*.yml points at a layout id. When sharing, note that a placed slot instance must be declared in that page's parts, otherwise the cell is unusable for the page

accessory_slot ​

The key name must equal a slot instance id in the form <partId>_<index>, with the index starting at 1 and matching that part's count in parts.yml

For example, a ring part configured with count: 2 needs both ring_1 and ring_2 cells:

yaml
slots:
  ring_1:
    slots: [12]
    type: "accessory_slot"
    item:
      source: "LIGHT_GRAY_STAINED_GLASS_PANE"
      components:
        custom_name: "<gray>Ring</gray>"
        lore:
          - "<dark_gray>Insert an accessory to activate</dark_gray>"
  ring_2:
    slots: [13]
    type: "accessory_slot"

Each accessory_slot may occupy only one cell. If you write several, only the first takes effect and the rest are logged as warnings

Slots declared in parts.yml but not placed here are likewise logged as warnings, and the player cannot use them

A slot's item section defines the placeholder shown while the slot is empty; it is replaced by the real item once an accessory is inserted

orphan_slot ​

Accessories in slots the page no longer declares appear here for the player to retrieve, and cannot be put back once retrieved. If you shrink count in parts.yml, delete a part, or remove a part from a page's parts, you create orphans

yaml
slots:
  orphan:
    slots: "37-43"
    type: "orphan_slot"
    item:
      source: "GRAY_STAINED_GLASS_PANE"
      components:
        custom_name: "<gray>"
        tooltip_display:
          hide_tooltip: true

An orphan area may occupy several cells. The check is based on whether the owning page declares the slot, so accessories on other pages are never treated as orphans

You can skip the orphan area and lose nothing: the data stays in the file, but players then have no in-GUI retrieval entry point and depend on /eacc retrieve <page> or on the configuration being restored

page_enable ​

Clicking it makes the currently open page the active one. Only the active page's accessories provide attributes, skills, and set piece counts; other pages keep their data without contributing

yaml
slots:
  page_enable:
    slots: [8]
    type: "page_enable"
    item:
      source: "lime_dye"

page_switch ​

The key name must equal the target page's page_id; clicking switches to that page. Switching only changes the view, not the active page — to activate the new page you still click page_enable

yaml
slots:
  main:
    slots: [0]
    type: "page_switch"
    item:
      source: "gold_ingot"
  secondary:
    slots: [1]
    type: "page_switch"
    item:
      source: "iron_ingot"

When the target page declares a permission the player lacks, the switch is refused

Decorative Cells ​

Cells without type are pure decoration, such as a frame:

yaml
slots:
  frame:
    slots: "0-8,45-53"
    item:
      source: "BLACK_STAINED_GLASS_PANE"
      components:
        custom_name: "<gray>"
        tooltip_display:
          hide_tooltip: true

Click Behaviour ​

A click on any cell is always cancelled (never handed to vanilla) and then dispatched by type:

ActionResult
Inserting an accessoryThe accessory slot declaration is checked first: without an accessory_slots declaration (and with no optional source matching) it reports gui.not_declared; a declared but non-matching cell reports gui.slot_mismatch. Then unique is checked against the same page and a duplicate reports gui.unique_conflict. On rejection the stack stays on the cursor and never enters the cell
Taking an accessory outA left click with an empty cursor takes the stored accessory
Double click, number key, off-hand swap, drop, control-dropUnsupported, reporting gui.click_unsupported
Quick transfers from the player inventoryUnsupported, reporting gui.transfer_unsupported; move items one cell at a time
Any mutation inside a read-only windowRefused with gui.read_only
Inserting into an orphan cellRefused with gui.orphan_read_only
Clicking page_enable on the already-enabled pageReports gui.page_already_enabled and changes nothing
Clicking the page_switch cell of the current pageDoes nothing; an unknown target reports gui.page_unknown and a missing permission reports gui.page_no_permission
Session data reloaded meanwhileThe edit is refused with gui.session_stale; close and reopen the accessory window

Switching a page closes the current window and opens the target on the next tick; the close path is suppressed during a switch, so the data session stays continuous (no flush and no lease release in between)

Orphan cells fill slot by slot in ascending slot id order; when there are more orphans than cells, the surplus can only be recovered with /eacc retrieve <page>

Validation on Close and Status Markers ​

Closing the window (any close path other than a page switch) runs a declaration check over every page of that player: an item sitting in a slot the page still declares, but no longer inside that slot's declaration, is taken out and returned to the player's inventory (dropped at their feet when the inventory is full) with one gui.invalid_returned message per item. Items in orphan cells are not part of this pass and keep their own take-out-only flow

An item that sits in the right cell but has its effects gated gets one extra status line in the window (rendering only, never written back to the item):

StateLineCause
Conditions unmetgui.condition_unmetThe EmakiItem definition's condition failed, so attributes, skills and set piece count stop applying
Durability exhaustedgui.durability_brokenDurability is used up, so attributes, skills and set piece count stop applying; the item stays in its cell and can be taken out for repair

When these two lines are evaluated is described in integration

Top-Level Keys ​

FieldTypeRequiredDefaultAllowed valuesDescription
idstringYes——Template id, referenced by gui_template in pages/*.yml; when blank the template is not loaded and a page referencing it cannot open (accessory.gui_template_missing)
gui_typestringNoCHESTa Bukkit InventoryType name (case-insensitive); an invalid value falls back to CHESTWindow type
titlestringNo"GUI"—Window title; MiniMessage is supported, and a text-config section (CoreLib text format) is accepted too
rowsintegerNo31–6, values outside the range are clampedRow count; only applies to types that support custom row counts (such as CHEST)
slotsmap<string, object>No{}—Slot definitions, keyed by cell identifier

Slot Keys ​

What slots.<key>'s key name means depends on the type (see "Available Types" above). Nested fields:

FieldTypeRequiredDefaultAllowed valuesDescription
slots.<key>.slotsinteger / list / stringYes—a single cell number, a list of numbers, or a range string such as "1-3,5"; an entry that parses to nothing is ignoredContainer cells this entry occupies, numbered from 0
slots.<key>.typestringNoemptyaccessory_slot / orphan_slot / page_enable / page_switchCell behaviour; empty means pure decoration. accessory_slot and page_switch also depend on the key name, as described above
slots.<key>.itemobject / stringNoempty—Item definition rendered in this cell; a plain item-source string is accepted as shorthand
slots.<key>.item.sourcestringNoempty—Item source (a vanilla material name, an EmakiItem definition, or another CoreLib item-source form); when blank it falls back to the part's icon, and when both are blank a barrier item is shown
slots.<key>.item.amountintegerNo1≥ 1, values below 1 are treated as 1Item amount
slots.<key>.item.componentsmapNo{}—Item component patches keyed by component id; the value is passed through to that component
slots.<key>.item.components.custom_namestringNo——Item name with MiniMessage support (component custom_name)
slots.<key>.item.components.lorelist<string>No——Item lore lines with MiniMessage support (component lore)
slots.<key>.item.components.tooltip_display.hide_tooltipbooleanNo—true / falseHides the item tooltip (a nested field of component tooltip_display)
slots.<key>.soundsmap<string, object>No{}keys are click, left_click, right_click, shift_left_click, shift_right_click, middle_click, double_click, number_key, swap_offhand, drop, control_dropClick sounds; an unrecognised key is reported as an issue and ignored

item.components is CoreLib's generic item-component patch, so it accepts any Minecraft component id in addition to the three listed above. Actual accessory interactions are decided by type; sounds and custom components only affect appearance. See plugins/EmakiAccessory/gui/accessory_gui.yml for the complete shipped sample

Example: one accessory cell on a page, plus an enable cell and a switch cell

yaml
id: "compact_gui"
gui_type: CHEST
title: "<dark_gray>Accessories</dark_gray>"
rows: 3
slots:
  ring_1:
    slots: [11]
    type: "accessory_slot"
    item:
      source: "LIGHT_GRAY_STAINED_GLASS_PANE"
  page_enable:
    slots: [15]
    type: "page_enable"
    item:
      source: "lime_dye"
  main:
    slots: [16]
    type: "page_switch"
    item:
      source: "gold_ingot"