Multi-line Messages
Any message PhantomBans sends to chat can be written as a list of lines instead of a single string. PhantomBans joins the list into one chat message with a line break between entries, which is how you build a boxed notice with a header, a divider, and a detail line per field.
Available from 1.3.0. Single-line messages keep working exactly as before, so this is opt-in per key.
Where it works
| File | What accepts a list |
|---|---|
messages.yml | Every message key. Command replies, errors, the mute and warn notices, list headers, alerts. |
appearance.yml | format and format-silent on every entry under broadcasts (ban, mute, kick, warn, unban, unmute). |
screens.yml | Already a list of lines by design. See Messages & Screens. |
menus/*.yml | lore is already a list. See Menus. |
discord.* in messages.yml is the one exception: those keys are Discord embed titles, not chat, and stay single-line.
The format
A key is either a string:
mute:
blocked: "<prefix> <red>You are muted.</red> <gray>Expires: <white>{expiry}</white></gray>"Or a list of strings, one per line:
mute:
blocked:
- "<color:#FF3A6E><bold>MUTED</bold></color>"
- "<gray>Reason: <white>{reason}</white></gray>"
- "<gray>Expires: <white>{expiry}</white></gray>"Both are valid for the same key. Switch back and forth whenever you like, then run /phantombans reload.
YAML rules
- Each line is a
-entry, indented under the key. - Quote every line. MiniMessage uses
<and>, and reasons can contain:or#, which unquoted YAML will misread. Single'or double"quotes both work; use single quotes if the line itself contains a double quote. - Keep the indentation consistent. Mixing tabs and spaces breaks YAML parsing, and PhantomBans will log the error on start.
Line rules
- An empty entry (
"") renders as a blank line. Use it to separate a header from the detail block. <prefix>is not added for you. Put it only on the line you want it on. A boxed layout usually drops it entirely and uses a styled header line instead.- Formatting carries across lines. The whole block is parsed as one message, so a
<gray>opened on line one and never closed still applies on line two. Close your tags if you do not want that. <newline>also works inside a single string, if you would rather keep the key on one line."<red>Line one<newline>Line two</red>"produces the same two lines.
Placeholders
The punishment-driven messages all share one placeholder vocabulary: the ban / temp-ban / IP-ban screens, the kick screen, every broadcast, the muted-player notice (mute.blocked), and the warning notice (warn.received).
| Placeholder | Fills in |
|---|---|
{player} | The punished player’s name |
{staff} | Who issued the punishment |
{reason} | The punishment reason |
{duration} | The length of a temporary punishment |
{expiry} | When the punishment expires |
{date} (or {start_date}) | When the punishment was issued |
{server} (or {scope}) | The server or network scope |
{id} | The punishment ID |
{type} | BAN, MUTE, WARN, and so on |
Other keys keep their own placeholders: a list header has {page} and {pages}, an import message has {source} and {count}, and so on. The comment above each key in messages.yml names them.
Player-supplied text such as a punishment reason is escaped before it is shown, so a player cannot inject colours or clickable links into a staff-facing message.
Examples
A boxed mute notice
This is the 1.3.0 default for mute.blocked, in messages.yml:
mute:
blocked:
- "<dark_gray><strikethrough> </strikethrough></dark_gray>"
- "<color:#FF3A6E><bold>MUTED</bold></color> <gray>You cannot send messages right now.</gray>"
- ""
- "<dark_gray>|</dark_gray> <gray>Reason</gray> <dark_gray>»</dark_gray> <white>{reason}</white>"
- "<dark_gray>|</dark_gray> <gray>Staff</gray> <dark_gray>»</dark_gray> <white>{staff}</white>"
- "<dark_gray>|</dark_gray> <gray>Expires</gray> <dark_gray>»</dark_gray> <color:#1AFFB2>{expiry}</color>"
- "<dark_gray><strikethrough> </strikethrough></dark_gray>"The strikethrough run of spaces draws a divider line. Add or remove spaces to change its width.
A two-line command reply
Any ordinary message works the same way:
general:
reloaded:
- "<prefix> <color:#1AFFB2>Configuration reloaded.</color>"
- "<gray>Messages, menus, screens, and templates were re-read from disk.</gray>"A multi-line broadcast
In appearance.yml, under broadcasts:
broadcasts:
ban:
enabled: true
silent: true
format:
- "<color:#FF3A6E><bold>BAN</bold></color> <white>{player}</white> <gray>was banned by <white>{staff}</white>.</gray>"
- "<gray>Reason: <white>{reason}</white></gray>"
format-silent: "<prefix> <dark_gray>[Silent]</dark_gray> <color:#FF3A6E>{player} has been banned by {staff}. <dark_gray>({reason})</dark_gray></color>"format and format-silent are independent: one can be a list while the other stays a string.
What to keep on one line
Row templates. history.line, lists.line, alts.line, notes.line, general.audit-line, and import.breakdown are printed once per row. A list here multiplies by the number of rows and will flood a paginated page. Keep them on one line.
Broadcasts reach every player online. Multi-line works, but two or three lines per punishment fills chat quickly on a busy server. The shipped broadcast defaults stay single-line for that reason.
Applying your changes
/phantombans reloadUpgrading from an earlier version: mute.blocked and warn.received ship as multi-line lists from 1.3.0, but your existing server will not show them. The config updater adds new keys and removes obsolete ones, and it never overwrites a value you already have. To pick up the new defaults, delete plugins/PhantomBans/messages.yml and restart, or hand-edit those two keys into list form. Back the file up first if you have custom wording.