Formats
One file per format under chat/formats/: components, hovers, clicks, the token list, and how a format is chosen.
A format is a whole chat line, described by a file under chat/formats/. The file name is the format
name: vip.yml is the format vip. Two ship — default.yml and msg.yml — and both are rewritten
on the first start if they are missing.
A file is one format, or several
A file with components: at its root is one format, named after the file.
A file without one is read block by block: each top-level block that has a components: section
becomes a format named file.block. That is how msg.yml produces msg.sender and msg.receiver.
A block format never takes part in the weight contest below — it is asked for by name, by the feature
that needs it.
permission: exyliachatcosmetics.chat.format.vip # empty = everybody
weight: 10 # heaviest qualifying format wins
per-viewer: false # true renders the line once per reader
components:
'1':
text: '{tag}{nick} {letters_black}» '
hover:
- '{secondary}Player'
- ' {letters_black}▎ {letters}Name {letters_black}» {info}{name}'
click: 'SUGGEST_COMMAND:/msg {name} '
'2':
text: '{message}'| Key | Default | Meaning |
|---|---|---|
permission | empty | Who may be given this format. Empty means everybody |
weight | 0 | When a player qualifies for several, the heaviest wins |
per-viewer | false | Render the line once per reader even when nothing in it asks for it |
components | — | The pieces of the line, in the order they are written |
The component keys are names, not indices; '1', '2' is a convention, not a requirement. A component
with no text is skipped and reported. A format that ends up with no usable component is dropped, and
if default is the one that failed the console says so and messages are sent bare.
Inside a component
| Key | Holds |
|---|---|
text | What is drawn. Palette tokens, & codes and MiniMessage all work |
hover | One line or a list, shown while the mouse is over this piece |
click | RUN_COMMAND:/x, SUGGEST_COMMAND:/x, OPEN_URL:https://x or COPY:text |
A click that is not one of those four is reported when the file is read, rather than silently
dropped on every message afterwards.
Tokens work in all three. A click carries its tokens as plain text, so
SUGGEST_COMMAND:/msg {name} puts the player's actual name into the chat box rather than the literal
{name}.
Which format a message wears
The channel's own
If the channel names a format and that file loaded, it is used, whoever is talking.
The heaviest one the sender qualifies for
Every top-level format whose permission the sender holds, or that has none. The highest weight
wins. Block formats such as msg.sender never enter this contest.
`default`
When none qualified.
Tokens
Tokens are components, placed into the line directly — no placeholder round-trip, and a tag or a coloured name keeps its own colours instead of being flattened into a string.
| Token | Is |
|---|---|
{message} | The styled message body |
{name} | The plain name |
{nick} | The name in the player's nick colour |
{tag} | The equipped tag, with its format |
{prefix} | The rank prefix, in the player's rank colour |
{suffix} | The rank suffix, in that same colour |
{channel} | The channel's name, parsed, so its own colour survives |
Private-message formats get their own set instead: {message}, {sender}, {sender_nick},
{sender_tag}, {receiver}, {receiver_nick}, {receiver_tag}.
Braces rather than percent signs, so a token can never collide with a placeholder. A brace pair nobody
claims — {primary}, {letters_black} — is left for the text engine, which reads it as a palette
colour.
The colour a line was written in carries across a token: the piece before {nick} opens a colour, the
token is drawn under it as a fallback, and the piece after it continues the same sentence. Anything
that names its own colour, an item's name for one, still wins.
Placeholders and per-viewer
Any %placeholder% ExyliaLib or PlaceholderAPI knows works in text, hover and click. By default
it resolves for the sender, because the line is about them.
Turn per-viewer: true on and the line is rendered once for each reader: %player_…% is then the
reader and %target_…% stays the sender. That is the switch for a line that says something about
whoever is looking at it.
A %rel_…% placeholder makes a format viewer-aware on its own, in text, hover or click, without
per-viewer being set — a relational placeholder has no meaning without a reader.
A viewer-unaware format is rendered once per message and handed to everybody. A viewer-aware one is rendered once per reader. On a busy server that is the difference between one render and a hundred, so turn it on only for a format that needs it.
Padding falls outside the hover and the click
The blanks a component is padded with are taken off both of its ends before the hover and the click go on, and put back afterwards. A gap belongs to neither of the pieces it separates.
Without that, the space in '{nick} ➞ ' sat inside the hover, and hovering the arrow answered
"Player" right where the message began. The peeling happens on the rendered piece rather than on the
written text, so a blank that a placeholder left behind — an empty rank prefix in '{prefix} {nick}' —
falls outside the hover just the same.
This is also why msg.yml has a component that is nothing but a space between the heading and the
message: a deliberate gap that answers to neither.
To check where a hover actually stops, use /cca chat line [message]. It renders your own line, sends
it to you, and writes to the console the same line broken into the stretches that share a hover and a
click.
What ships
default.yml
Three components, and it is a worked example of everything above.
| Component | Draws | Hover | Click |
|---|---|---|---|
'1' | {prefix} {nick}{suffix} | An INFORMATION box: ping through %player_ping%, the rank through {prefix}, and a line inviting a private message | SUGGEST_COMMAND:/msg {name} |
'2' | ➠ | — | — |
'3' | {message} | A WARNING box offering to report the message | RUN_COMMAND:/report {name} offensive_language |
The separator is its own component precisely so that neither the name's hover nor the message's report
click reaches the arrow between them. weight: 0, no permission: everybody gets it unless a heavier
format applies.
/report is not shipped by this plugin. If your server has no such command, change or remove the
click on the third component.
msg.yml
Two blocks, sender and receiver, giving the formats msg.sender and msg.receiver. Each has
three components: a heading — [You ➜ them] on one screen, [them ➜ You] on the other — that hovers
with who the message is with and clicks to SUGGEST_COMMAND:/reply , then a bare space, then
{message} hovering "Click to copy it" with COPY:{message}.
Each screen is rendered with its own reader as the viewer and the other person as the placeholder target, so a hover about "them" is about the right person on both.
Related
The format key that pins a channel to one of these files.
Private messages, which are what msg.yml draws.
The format permission node is on Permissions, and
/cca chat line on Commands.
Something missing on this page? Tell us on Discord