Configuration
Structure
open-command:
name: menu
menu: main
menus:
main:
pause-menu: true
quick-actions: false
title: "<green>Menu</green>"
buttons:
spawn:
label: "<green>Spawn</green>"
actions:
- "player: spawn"Menu and button ids use lowercase [a-z0-9_.-]. Input keys allow [a-zA-Z0-9_.-] and are case-sensitive.
Default config
# CustomMenu configuration
# ========================
#
# STRUCTURE
# menus:
# <menu-id>:
# <menu settings>
# inputs: optional, only useful if a button reads %input_<key>%
# buttons: required, a menu with no valid buttons is skipped entirely
#
# IDS
# Menu and button ids may only use [a-z0-9_.-] and are lowercased.
# Input keys may use [a-zA-Z0-9_.-] and are CASE SENSITIVE:
# "details:" -> %input_details% (not %input_Details%)
#
# TEXT (MiniMessage: https://docs.advntr.dev/minimessage/format.html)
# Hex: <#ff5555>text</#ff5555>
# Gradient: <gradient:#ff5555:#ffaa00>text</gradient>
# Named: <red> <gold> <gray> <aqua> <bold> <italic> <underlined>
#
# SPRITES / CUSTOM GLYPHS
# Native Minecraft sprite (Minecraft 1.21.9+ / Adventure 4.25+):
# <sprite:blocks:block/stone>
# <sprite:"minecraft:items":item/diamond>
# ItemsAdder Font Image:
# <ia:namespace:glyph_id>
# <itemsadder:namespace:glyph_id>
# Regular ItemsAdder :glyph_id: placeholders are also passed through when
# the ItemsAdder API is available.
# Nexo Glyph:
# <glyph:glyph_id>
# <nexo:glyph_id>
#
# These work anywhere this config accepts MiniMessage: titles, button names,
# tooltips, body text, input labels/options and message: actions.
#
# YAML WARNING
# yes / no / on / off / true / false are BOOLEANS in YAML, not text.
# on-true: yes -> the string "true" (wrong)
# on-true: "yes" -> the string "yes" (right)
# Quote any value that is meant to be text but looks like a boolean.
#
# PLACEHOLDERS (usable in player:, console: and message: actions)
# %player% player name
# %uuid% player UUID
# %input_<key>% value of the input with that key
# Player-supplied values are sanitized server-side before they reach a
# command, and tag-escaped before they reach a message.
#
# RELOAD
# /custommenu reload applies: button actions, messages, menu: targets, the
# open-command TARGET menu, and the FULL layout of any menu opened inline
# (menu: action, /custommenu open, the open command).
# Pause menu entries and their layout are baked into the dialog registry at
# startup and sent to clients on join, so those need a server RESTART. The
# open-command NAME is registered at startup too and also needs one.
#
# PAUSE MENU (vanilla client behavior, not configurable server-side)
# exactly one pause-menu: true -> its button-name is a direct button
# two or more -> the client collapses them behind a
# single "Custom Options..." button
#
# QUICK ACTIONS
# quick-actions: true puts a menu behind the client's "Quick Actions" key
# bind. That bind has NO default key: the player has to set one in
# Options -> Controls -> Key Binds -> Miscellaneous -> Quick Actions.
# pause-menu and quick-actions are separate tags; set both to appear in both.
# Player-facing command that opens one menu, separate from the admin
# /custommenu command. Permission: custommenu.use (default: everyone).
# Renaming the command needs a RESTART; the target menu reloads live.
open-command:
# Command name without the slash. [a-z0-9_-], lowercased.
# Set to '' to not register the command at all.
name: menu
# Menu id from 'menus' below. Falls back to the first menu if omitted.
menu: main
menus:
# =====================================================================
# main: the pause menu entry. Demonstrates every action type.
# =====================================================================
main:
# Show this menu in the pause screen. RESTART to change. Default: false
pause-menu: true
# Show this menu under the client's "Quick Actions" key bind (unbound by
# default in Controls -> Miscellaneous). Independent of pause-menu, and
# also baked in at startup, so RESTART to change. Default: false
quick-actions: false
# Label of the pause screen button. Falls back to 'title' if omitted.
button-name: "<gradient:#00e5ff:#7c4dff><bold>Change Me</bold></gradient>"
# Header inside the opened dialog. Falls back to the menu id if omitted.
title: "<gradient:#00e5ff:#7c4dff><bold>Change Me</bold></gradient>"
# What the client does after a button is clicked:
# close close the dialog (default)
# none keep it open (see 'sticky' below)
# wait_for_response show a waiting screen until the server acts
# (see 'forms' below)
after-action: close
# Allow closing with ESC. Default: true
can-close-with-escape: true
# Button grid width. Default: 2, minimum 1
columns: 2
# Bottom exit button. Remove this line entirely for no exit button.
exit-button: "<red>Close</red>"
# Lines shown above the buttons. Optional.
#
# A bare string is a text line. A map may carry an item icon, a text line
# rendered next to that icon, or both:
#
# body:
# - "<gray>A plain text line</gray>"
# - item: ENDER_PEARL # Material name, with or without minecraft:
# text: "<gray>Shown beside the icon</gray>" # optional
# - sprite: item/diamond # native Minecraft 1.21.9+ sprite
# atlas: minecraft:items # optional; omit to use the default atlas
# text: "<gray>Sprite beside text</gray>" # optional
# show-decorations: false # stack count / durability bar, default false
# show-tooltip: true # hover tooltip on the item, default true
# width: 16 # icon size, 1-256, default 16
# height: 16 # icon size, 1-256, default 16
# text-width: 200 # optional, 1-1024
#
# Unknown materials, and materials that have no item form, fall back to the
# text line alone.
body:
- "<gray>Each button below is a different action type.</gray>"
- "<dark_gray>Edit these in plugins/CustomMenu/config.yml</dark_gray>"
buttons:
# "player: <cmd>" runs the command AS the clicking player.
# No leading slash needed. Runs with that player's permissions.
spawn:
label: "<#55ff55>Player command</#55ff55>"
tooltip: "<gray>Runs /spawn as you</gray>" # optional
width: 150 # optional, 1-1024, default 150
actions:
- "player: spawn"
# "console: <cmd>" runs the command from console.
announce:
label: "<#ffaa00>Console command</#ffaa00>"
tooltip: "<gray>Runs a command as console</gray>"
actions:
- "console: say %player% (%uuid%) pressed a button"
# "message: <text>" sends MiniMessage text to the player.
discord:
label: "<#5865f2>Message</#5865f2>"
tooltip: "<gray>Just sends you text</gray>"
actions:
- "message: <gray>Join us at <aqua><underlined>discord.gg/changeme</underlined></aqua></gray>"
# "menu: <menu-id>" opens another menu from this file.
forms:
label: "<gold>Open a submenu</gold>"
tooltip: "<gray>Shows every input type</gray>"
actions:
- "menu: forms"
sticky:
label: "<light_purple>Open sticky menu</light_purple>"
tooltip: "<gray>A menu that stays open</gray>"
actions:
- "menu: sticky"
# Multiple actions run top to bottom.
chained:
label: "<#00e5ff>Chained actions</#00e5ff>"
tooltip: "<gray>A message, then a console command</gray>"
actions:
- "message: <gray>Running two things...</gray>"
- "console: say %player% used the chained button"
# No actions = client-only button. Nothing reaches the server; the
# dialog just does whatever after-action says (here: close).
plain:
label: "<gray>Do nothing</gray>"
tooltip: "<dark_gray>No actions, closes only</dark_gray>"
actions: []
# =====================================================================
# forms: every input type. Values are read back as %input_<key>%.
# Not in the pause menu, so this whole menu reloads live.
# Reached via "menu: forms" or /custommenu open forms
# =====================================================================
forms:
pause-menu: false
title: "<gold><bold>Every Input Type</bold></gold>"
# The client parks on a waiting screen until the server acts. The plugin
# closes it once the clicked button's actions have finished.
after-action: wait_for_response
can-close-with-escape: true
columns: 1
exit-button: "<red>Back</red>"
body:
- "<gray>Fill this in and press Submit.</gray>"
inputs:
# OPTION: single-choice picker. %input_category% = the chosen id.
category:
type: option # alias: single_option
label: "<white>Category</white>"
label-visible: true # optional, default true
width: 200 # optional, 1-1024, default 200
options:
- id: bug
display: "<yellow>Bug report</yellow>" # optional, defaults to the id
initial: true # optional, first entry wins if unset
- id: player
display: "<red>Player report</red>"
- id: other
display: "<gray>Other</gray>"
# A bare value works too and uses the id as its own display:
- question
# TEXT: free typing. Include 'multiline' for a box, omit it for one line.
details:
type: text
label: "<white>Details</white>"
label-visible: true
width: 300
initial: "" # optional, prefilled text
max-length: 250 # optional, default 100
multiline: # remove this whole section for a single line
max-lines: 5 # optional
height: 60 # optional, 1-512
# TEXT again, single line, showing the minimal form.
contact:
type: text
label: "<white>Discord tag</white>"
initial: "@"
max-length: 32
# NUMBER: a slider.
urgency:
type: number # aliases: number_range, slider
label: "<white>Urgency</white>"
width: 200
min: 1
max: 5
step: 1 # must be > 0
initial: 2 # clamped into min..max
# Optional. Two %s: the label and the value. A translation key such as
# "options.generic_value" also works. Omit for the vanilla default.
label-format: "%s: %s"
# BOOLEAN: tick box. on-true / on-false are the strings %input_anonymous%
# resolves to. Quote them, see the YAML warning at the top.
anonymous:
type: boolean # alias: bool
label: "<white>Stay anonymous</white>"
initial: false
on-true: "yes"
on-false: "no"
# Boolean inputs ignore 'width' and 'label-visible'; Paper's builder
# does not expose them.
buttons:
submit:
label: "<green>Submit</green>"
width: 200
actions:
# Each %input_<key>% matches an input key defined above.
- "console: say [Support] %player% | %input_category% | urgency %input_urgency% | anon %input_anonymous% | %input_contact% | %input_details%"
- "message: <green>Sent. Category <white>%input_category%</white>, urgency <white>%input_urgency%</white>.</green>"
back:
label: "<gray>Back</gray>"
actions:
- "menu: main"
# =====================================================================
# sticky: after-action "none" keeps the dialog open after every click,
# which is what you want for toggles. ESC is disabled here, so the
# "close" button below is the only way out. If you copy this menu, keep
# one close button or set can-close-with-escape: true.
# =====================================================================
sticky:
pause-menu: false
title: "<light_purple><bold>Stays Open</bold></light_purple>"
after-action: none
can-close-with-escape: false
columns: 1
# No exit-button on purpose: the 'leave' button does that job.
body:
- "<gray>These buttons do not close the menu.</gray>"
buttons:
day:
label: "<yellow>Set day</yellow>"
tooltip: "<gray>Needs permission for /time</gray>"
actions:
- "player: time set day"
ping:
label: "<aqua>Ping me</aqua>"
actions:
- "message: <aqua>Still here, <white>%player%</white>.</aqua>"
# "close" closes the dialog server-side.
leave:
label: "<red>Close</red>"
width: 200
actions:
- "close"