Writing menus

First menu #

Every .yml file under plugins/CrossMenu/menus/ is a menu. The path without .yml becomes its id.

yaml
title: "&8Shop"
rows: 3
open-commands: [shop]

items:
  diamonds:
    slot: 13
    material: DIAMOND
    name: "&bDiamonds"
    lore:
      - "&7Click to buy"
    left-actions:
      - "[console] give {player} diamond 1"
      - "[message] &aPurchased."

Use type: confirm or type: input for confirmation and text-input menus. Bedrock players receive native forms when Geyser or Floodgate is available. Java dialogs are used when the server supports them; otherwise CrossMenu opens the chest version.

Opening a menu without a command #

Besides open-commands, a menu can open when a player joins or clicks with a certain item:

yaml
open-triggers:
  join: true # open shortly after joining
  join-delay-ticks: 40 # default 20, allowed 1-1200
  item:
    material: COMPASS # the item in the main hand
    name: "&aServer menu" # optional; colour codes are ignored when comparing
    click: right # right (default), left or any

The menu's open-permission, open-requirement and open-rate limit apply as usual. A click that matches is cancelled, so the item does nothing else. Only one menu can claim a trigger: if two menus claim the same join or the same item and click, the one whose id comes first wins and the console says so. For a Citizens NPC, give the NPC a player command crossmenu open <menu>.

Components #

Put shared definitions in any .yml file under plugins/CrossMenu/components/. Each top-level key is a component.

yaml
# components/common.yml
close-button:
  material: BARRIER
  name: "&cClose"
  actions: ["[close]"]

dark-pane:
  material: BLACK_STAINED_GLASS_PANE
  name: " "

Use a component in a menu and override only what changes:

yaml
items:
  close:
    component: close-button
    slot: 22

  back:
    extends: [close-button, dark-pane]
    slot: 18
    name: "&eBack"

Components merge from left to right. Keys written in the menu always win. Lists and scalar values are replaced as a whole. An empty local key removes the inherited value. Unknown names, loops and type conflicts are reported with their source file and line.

Matrix layouts #

A matrix makes inventory layouts readable. Each row must contain exactly nine characters. . and spaces are empty cells.

yaml
rows: 3
matrix:
  - "OOOOOOOOO"
  - "O..S.C..O"
  - "OOOOOOOOO"

items:
  shop:
    symbol: S
    material: EMERALD
    name: "&aShop"
  close:
    symbol: C
    component: close-button

fill-item:
  material: GRAY_STAINED_GLASS_PANE
  name: " "

fill-item covers cells that no visible item owns and always renders behind normal items. Slot numbers and symbols can be used in the same menu.

Actions and requirements #

Common actions include player and console commands, messages, broadcasts, sounds, titles, menu navigation, close, refresh, connect, economy changes and item changes.

yaml
left-actions:
  - "[takemoney] 250"
  - "[console] give {player} diamond 1"
  - "[sound] entity.player.levelup"

left-click-requirement:
  requirements:
    funds:
      type: has money
      amount: 250
  deny-actions:
    - "[message] &cYou need $250."

Requirements cover permissions, money, experience, items, comparisons, Java/Bedrock detection, world, gamemode, date/time and logical groups. DeluxeMenus aliases such as perm, hasitem, equals, greater than, not equal to and != are accepted.

[player] runs the command exactly as written. If no plugin registers that command, nothing happens and the player sees no message (DeluxeMenus shows the server's "Unknown command" here). Type a new command yourself once to check it exists.

See the bundled example menus for click types, pagination, animations, calculations, generated lists, locale variants, cooldowns and use limits.