π¨ Appearance
Two files, split by what they answer:
menus.ymlβ where things sit. Titles, rows, slots, dialog labels.items.ymlβ how things look. Material, name, lore.
Every button and every item takes the same fields, so learn them once.
Item fields
send-mail:
slot: 48
item: FEATHER
name: "<#f2c42f>Send mail"
lore:
- "<#E9FDFB>Write a letter and attach items."
amount: 1
glow: false
| Field | Notes |
|---|---|
item | A material, or a custom-item id β see Custom Items. material: is an alias |
name / lore | MiniMessage or legacy codes |
amount | Stack size |
glow | Enchant shimmer without the enchantment |
item-model | Vanilla item model override |
flags | Item flags to hide |
hide-tooltip | Hide the tooltip entirely |
menus.yml
Inbox
inbox:
title: "<dark_gray><b>Mail"
inspect-title: "<dark_gray><b>%player%" # /mail admin
rows: 6
filler-item: BLACK_STAINED_GLASS_PANE
buttons:
send-mail: { slot: 48, ... }
claim-all: { slot: 49, ... } # %count%
clear-mail: { slot: 50, ... }
prev-page: { slot: 45, ... } # %page% %pages%
next-page: { slot: 53, ... }
rows is the whole screen. mail.inbox-rows-per-page from config.yml decides how many of them hold mail; the last one is always the control bar.
Compose
compose:
title: "<dark_gray><b>New mail"
admin-title: "<dark_gray><b>Server mail"
rows: 5
item-slots: [12, 13, 14, 21, 22, 23, 30, 31, 32]
filler-item: BLACK_STAINED_GLASS_PANE
write-letter-button: { slot: 40, ... }
item-slots must hold exactly mail.max-items-per-letter entries. Only these slots accept items; everything else is locked, including drags and shift-clicks that would land outside them.
Dialogs
dialogs:
compose:
title: "<#f2c42f><b>Write a letter"
fields:
recipient: { label: "Player" }
subject: { label: "Subject" }
message: { label: "Message", multiline: true }
money: { label: "Money" }
anonymous: { label: "Send anonymously" }
buttons:
confirm: "<#95d027>Send"
cancel: "<#eb4b30>Cancel"
Three dialogs: compose, compose-admin (no recipient, no anonymous β the audience came from the command) and read-letter.
read-letter is what opens when a player right-clicks a letter item, with %subject%, %sender% and %message%.
items.yml
Inbox entries
The record shown inside the inbox. It never leaves the menu.
| Entry | Used for |
|---|---|
pending / claimed | Player mail |
pending-server / claimed-server | Server mail |
pending-<name> / claimed-<name> | A server-mail entry that names <name> with mail-item |
A missing variant falls back to the plain pair, so you never have to define all of them.
Placeholders
Available in every name and lore:
%subject% %sender% %sent% %claimed% %expires% %money%
%sender% reads Anonymous for an anonymous mail β except in /mail admin, where it reads
Anonymous (Steve). Both wordings are yours:
text:
sender-anonymous: "Anonymous"
sender-anonymous-admin: "Anonymous (%player%)"
%contents% is special. On its own lore line it expands to one row per attachment:
lore:
- "<#E9FDFB>Contents"
- "%contents%"
Item names are rendered by the client, not the server. A vanilla item's name is a translation key rather than a word, and it is passed through untouched β so a player running the game in Spanish reads Diamante and one running it in Russian reads ΠΠ»ΠΌΠ°Π·, from the same config line.
The rows themselves are configurable:
contents:
item: "<#f3842c> β β’ <#b6c1ec>%item%"
letter: "<#289bd0> β β’ <#b6c1ec>A letter"
money: "<#95d027> β β’ <#b6c1ec>%amount%"
Other entries
| Section | What |
|---|---|
text | "Anonymous", "Never", and the %expires% units (d, h, m, s) |
inspect-entry | Lore used in /mail admin, with %state% and %recipient% |
letter-item | The item handed over when letter-type: ITEM |
letter-book | The book written when letter-type: BOOK |