Configuration
ChatColor uses multiple YAML files to keep settings, colors, patterns, and messages organized and easy to customize.
config.yml
This file controls general settings and core behavior of the plugin.
settings:
apply-to-message: true # Whether to apply colors to chat messages
apply-to-name: false # Whether to apply colors to the player's display name
default-color: "NONE" # The default color for new players (Key from colors.yml/patterns.yml)
group-defaults: # Group-based default colors
admin: ""
vip: ""
event-priority: "DEFAULT" # The listener priority for the chat event (LOWEST to MONITOR)
chat-hook: "AUTO" # Which chat event to hook (AUTO / MODERN / LEGACY)
late-bind: false # Use if you use %chatcolor_message% in other plugin formats
clean-console: true # Strips color codes from console output
show-standard-colors: true # Toggle standard colors in GUI
show-standard-gradients: true # Toggle standard gradients in GUI
show-standard-patterns: true # Toggle standard patterns in GUI
Settings Detailed
| Setting | Description |
|---|---|
apply-to-message |
Whether to apply the player's selected color to their chat messages. |
apply-to-name |
Whether to apply the color to the player's display name in chat. |
default-color |
A MiniMessage tag applied to players who haven't picked one, e.g. "<gray>". Set to NONE to disable. Overridden by group-defaults when the player matches one. |
group-defaults |
Map of permission-node-suffix: color-tag. Players with chatcolor.group.<suffix> get that color. Evaluated top to bottom — the first match wins, so list staff first. |
event-priority |
Set to DEFAULT to auto-detect, or set one manually (e.g. HIGHEST). See below — you should rarely need to change this. |
chat-hook |
Which chat event to hook. AUTO (recommended), MODERN, or LEGACY. Paper only — Spigot always uses LEGACY. See below. |
late-bind |
Stops ChatColor coloring the message itself, so another plugin can place it via %chatcolor_message%. Enable this only when a chat plugin builds its format from placeholders (LPC), otherwise chat comes out uncolored. |
clean-console |
If true, the plugin strips color codes from its own console output to keep logs readable. /color debug output is escaped so this cannot hide it. |
show-standard-* |
Set to false to skip loading the bundled colors, gradients, or patterns entirely — they disappear from the GUI and from /color set and the API. Custom colors are unaffected. |
Chat Hook (chat-hook)
ChatColor registers exactly one chat listener. This matters more than it sounds.
Paper has two chat pipelines: the modern one built on AsyncChatEvent, and a legacy one built on
the deprecated AsyncPlayerChatEvent. A plugin that registers on both would color the same
message twice on the way through, so ChatColor picks one.
| Value | Behaviour |
|---|---|
AUTO |
Recommended. MODERN on Paper (and Folia), LEGACY on Spigot. |
MODERN |
Always use AsyncChatEvent. ChatColor colors from a chat renderer, which runs after every listener has finished, so nothing downstream can strip it. |
LEGACY |
Always use AsyncPlayerChatEvent. Only needed if a plugin cancels chat on the legacy event and you need ChatColor to run before it. See the warning below. |
The active choice is logged on startup:
[ChatColor] Chat hook: MODERN (AsyncChatEvent), priority HIGHEST
/color reload re-runs this resolution and rebinds the listener, so you do not need a full
restart after changing chat-hook or event-priority.
Why MODERN is safe even when other chat plugins are installed
On Paper, AsyncChatEvent fires for every chat message regardless of what else is installed:
- With no legacy listeners, Paper fires it directly.
- With legacy listeners present, Paper fires
AsyncPlayerChatEventfirst and then feeds the result straight intoAsyncChatEvent.
So the modern event is always last in the chain, which is exactly where a colorizer wants to
be. On top of that, MODERN does not write color codes into the message at all — it installs a
renderer that applies the color after every listener has had its say. A plugin that strips color
codes out of chat therefore has nothing of ours left to strip.
Earlier versions got this wrong.
AUTOused to join whichever event already had listeners on it. That sounds like "go where the chat plugins are", butAsyncPlayerChatEventis also where every plugin that merely captures chat input lives — WorldGuard, mcMMO, HeadDatabase, GUI prompts. On a populated server one of those is always present, soAUTOpickedLEGACYevery time and left ChatColor running before a modern formatter such as EssentialsChat, which then stripped the codes. If you previously worked around this by forcingchat-hook: MODERN, you can safely set it back toAUTO.
When you would still want LEGACY
Only if a plugin cancels or consumes chat on AsyncPlayerChatEvent and you need ChatColor to
act before that happens. Be aware of two costs:
- Colors written on the legacy event can still be stripped by anything reading the modern event
afterwards — EssentialsChat included. This is the exact failure
MODERNwas introduced to fix. - Paper renders legacy-pipeline messages through a shared legacy serializer. On most builds that
serializer has no hex support, so
#FF7F00arrives at the client as the nearest of the 16 named colors (gold). Solid colors are unaffected; only gradients and custom hex are approximated. ChatColor detects this at startup and warns you.
Listener Priority (event-priority)
DEFAULT auto-detects, and what it picks depends on which hook is active:
| Hook | DEFAULT resolves to |
|---|---|
MODERN |
Always HIGHEST. |
LEGACY |
HIGHEST when EssentialsChat, LPC, or DeluxeChat is running, otherwise NORMAL. |
The two rules differ because the hooks work differently. On MODERN, ChatColor installs a chat
renderer and the last plugin to install one wins, so being late is correct no matter what else
is installed — there is nothing to detect. On LEGACY, ChatColor writes color codes into the
message, so it genuinely matters whether a known formatter is going to run before it.
Earlier versions used the plugin-name check on both hooks. That only ever worked for the three plugins named above and missed everything else — including every chat plugin on Folia, since none of those three run there.
ChatColor never takes MONITOR automatically. That priority is reserved for plugins that only
observe an event, and leaving it free means you can still configure something to run after
ChatColor if you need to.
When to override. Only when another plugin is replacing ChatColor's renderer instead of
wrapping it. Run /color debug, say something, and look at ourRendererStillInstalled — if it
reports false, set event-priority: "MONITOR" to get the last word.
Troubleshooting: colors are not showing in chat
Work through this in order.
- Check the startup line. It should read
Chat hook: MODERN (AsyncChatEvent), priority HIGHESTon Paper. If it saysLEGACYand you are on Paper, something setchat-hookexplicitly — set it back toAUTO. - Confirm
apply-to-message: trueandlate-bind: false. Either one turns message coloring off, by design. - Run
/color debugas the affected player, say something, and read the console. See Chat Compatibility for how to interpret it.
A player seeing §xt§xt§xt — orphaned §x markers — in console or chat is the signature of
another plugin stripping hex codes out of a legacy-pipeline message. Switching chat-hook to
AUTO/MODERN fixes it.
Automatic Configuration Updates
ChatColor features an intelligent configuration migrator. When you update the plugin, it will:
- Detect Missing Keys: Automatically add any new configuration options to your existing files while preserving your settings.
- Back Up Old Configs: Create a timestamped backup in a
backups/folder before making changes. - Log Changes: Detailed summaries of added or removed keys will be displayed in the console during startup.
This ensures you always have access to the latest features without having to manually reset your configuration files.
gui/gui.yml
This file allows for deep customization of the GUI, including all titles, items, layouts, and status messages.
See the GUI Customization Guide for more details.
| Section | Description |
|---|---|
titles |
MiniMessage formatted titles for each menu page. |
layouts |
Define inventory size and slot positions for items. |
status |
Text shown in item lore based on player access/state. |
items |
Material, name, and lore for navigational/button items. |
colors/colors.yml
This file defines all your solid colors and gradients.
Solid Colors
Solid colors use a single MiniMessage tag or a hex code.
colors:
red:
display-name: "Red"
tag: ""
permission: "chatcolor.color.red"
icon: "RED_WOOL"
hot-pink:
display-name: "Hot Pink"
tag: "<#FF69B4>"
permission: "chatcolor.color.hot_pink"
icon: "PINK_WOOL"
Gradients
Gradients use the <gradient:color1:color2:...> tag.
gradients:
sunset:
display-name: "Sunset"
tag: ""
permission: "chatcolor.gradient.sunset"
icon: "ORANGE_WOOL"
Custom Colors
The custom-colors section holds anything created with /color create. It starts empty ({})
and you can also hand-edit it. Entries here appear in the GUI alongside the standard colors and
are listed by /color list custom.
custom-colors:
pastel-pink:
display-name: "Pastel Pink"
tag: "<#FCB6E1>"
permission: "chatcolor.custom.pastel-pink"
icon: "PINK_WOOL"
default: "false"
| Key | Required | Notes |
|---|---|---|
display-name |
No | Shown in the GUI. Falls back to the key. |
tag |
Yes | Any MiniMessage tag, including gradients. |
permission |
No | Omit or leave blank to make the color public. You may also write none/public/everyone/all. |
icon |
No | Any placeable Bukkit material. Defaults to WHITE_WOOL. |
default |
No | Bukkit permission default: true, op, or false. Defaults to false. |
The same permission / default rules apply to the colors, gradients, and patterns
sections.
What happens when a permission is revoked
Color selections are resolved fresh on every message rather than trusting the tag stored when the player picked it. So if you revoke someone's access to a color, or delete the entry from YAML, they immediately fall back to their group default (or to no color) without needing to re-pick.
colors/patterns.yml
Patterns cycle colors character-by-character throughout the message.
patterns:
rainbow:
display-name: "Rainbow"
permission: "chatcolor.pattern.rainbow"
icon: "YELLOW_WOOL"
colors:
- ""
- ""
- ""
- ""
- ""
- ""
- ""
lang/messages.yml
All plugin messages can be fully customized with MiniMessage formatting. Use <prefix> to include the defined prefix.
prefix: "[ChatColor] "
color-applied: "Color has been applied!"
color-created: "Custom color '' has been created!"
color-reset: "Your chat color has been reset."
no-permission: "You don't have permission to use that color."
config-reloaded: "Configuration reloaded successfully."