Skip to content

v5 Menu Config

Jake Moore edited this page Aug 30, 2026 · 5 revisions

Menu Configuration

⚠️ Usage ⚠️

Available in spigot-utils and its inheritors (spigot-jar).

Menus can be defined in YAML and loaded at runtime, so server owners can move icons around without you rebuilding. Each menu type has its own loader.

SimpleMenu menu = SimpleMenuLoader.loadMenu(config, "myMenu").build(player);
menu.modifyIcons(icons -> icons.setMenuClick("exit", data -> data.getPlayer().closeInventory()));
menu.open();

Loaders return a builder, not a finished menu, so you attach click handlers by icon id before building.

  • SimpleMenuLoader.loadMenu(section[, key])
  • PaginatedMenuLoader.loadMenu(section[, key][, layout])
  • OneClickMenuLoader.loadMenu(section[, key])

Migrating from v3: the single KamiMenuLoader was replaced by one loader per menu type. Pick the type you intend to use. All three loaders were already in place in v4.

A full example

myMenu:
  title: "&6My Menu"
  rows: 6
  filler:
    material: GRAY_STAINED_GLASS_PANE
    name: " "
  icons:
    diamond:
      material: DIAMOND
      name: "&6Diamond"
      lore:
        - "&7Worth a lot"
      slot: 0
    emerald:
      materials: [EMERALD, EMERALD_BLOCK]
      name: "&aEmerald"
      typeCycleTicks: 20
      slot: [1, 2]
    exit:
      material: BARRIER
      name: "&cExit"
      slotInLastRow: 4

Every key under icons becomes an icon whose id is the config key. Use that id from code:

icons.setMenuClick("exit", data -> data.getPlayer().closeInventory());

Menu keys

key type default notes
title String falls back to name, then a space format auto-detected
name String none fallback for title only
type String none an InventoryType name. Tried first, and only when the value is a string. An invalid value is ignored silently and rows is used
rows int none used when type is absent or invalid
row int none alias, checked after rows
filler section default filler a full icon section; its id is forced to filler
icons section none each child key becomes an icon id

Size resolution runs typerowsrow, and throws IllegalStateException naming the config path if none resolve.

icons is optional. A menu section without it loads normally and has no icons beyond the filler, which is a reasonable way to define a purely decorative menu.

Icon keys

Identity and cycling

key type default notes
enabled boolean true a disabled icon is never placed
typeCycleTicks int 20 ticks between materials, only meaningful with several

Slot, first match wins

key type notes
slotInLastRow int highest priority. 0 is the first slot of the last row, 8 the last
slot int or list of int
slots list of int or int checked after slot

Negative values are ignored.

⚠️ An icon whose slot keys resolve to nothing is registered but never rendered. It will not appear and nothing will tell you why. The filler is the deliberate exception.

Item

The rest of an icon section is an item definition, identical to the one documented on the ItemBuilder page: material / materials, data, amount, damage, name, lore, unbreakable, item-flags, enchantments, glow, skull-owner, hide-attributes.

Three behaviours worth repeating here, because menus are where they bite:

  • A typo behaves differently depending on the form. material: DIMAOND throws IllegalArgumentException; materials: [DIMAOND] is dropped with a warning naming the config path.
  • data applies to every entry of a multi-material list.
  • hide-attributes falls back to a global default of true when absent, and the v4 spelling hideAttributes is no longer read at all, so an old config silently takes the global default.

name and lore go through format auto-detection, so &6 codes and MiniMessage both work, but not in the same line. See Text and Components.

Per-player titles

A title read from config can carry a placeholder you fill when you know the player:

myMenu:
  title: "&6{player}'s bag"
SimpleMenuLoader.loadMenu(config, "myMenu")
        .titleReplacement("{player}", player.getName())
        .build(player)
        .open();

Paginated menus

PaginatedMenuLoader takes an optional PaginationLayout; without one it uses PaginatedMenuLoader.Config's default. Icons defined in the icons section are static furniture on every page. The paged contents are added from code with modifyPageIcons(...).

Clone this wiki locally