Compatibility
Minecraft: Java Edition
Platforms
Tags
Creators
Details
Requires PacketEvents. Free and open source under GPL-3.0 — source on GitHub.
What it does
Some plugin sends an ugly message and gives you no way to change it. No locale file, no config option, nothing. MessageStyler fixes that from the outside.
It intercepts messages on their way to the player and lets you rewrite the text, move it to the action bar or a title, or delete it entirely — regardless of which plugin sent it or whether that plugin supports formatting at all.
Features
- Works on any message. Vanilla messages, plugin messages, messages from plugins that were never designed to be configurable.
- Automatic message keys. Every message gets a stable 8-character ID generated from its text with numbers stripped out, so
Wait 9m 45sandWait 3m 20sshare one key and one rule. - Keeps the numbers. Values removed to build the key come back as
{0},{1},{2}— restyle a message completely without losing its data. - Reroute anywhere. chat, action bar, title, subtitle, or delete.
- Exact action bar timing. Hold a message for precisely as long as you want, in ticks. Longer than the client's natural fade if you need it.
- Match by key or by text. Text matching searches the raw component JSON too, so vanilla translation keys like
block.minecraft.set_spawnwork directly. - Guided setup. Turn on debug, trigger the message, copy the key from console. That's the whole workflow.
- Stays out of the way. Action bar output from other plugins is ignored by default, and messages already cancelled by another plugin are left alone.
- Clean unload. The packet listener is properly unregistered on disable, so hot-swapping with PlugMan doesn't leak listeners.
Requirements
- Paper or Spigot 1.20.5+
- PacketEvents — required
- Java 21 or newer (26.1+ servers already require Java 25)
- Folia is not supported
Setup
- Install PacketEvents
- Drop MessageStyler in
/plugins - Restart
- Set
debug: truein the config, run/messagestyler reload - Trigger the message you want to change and copy the key from console
- Write a rule, reload, set
debug: false
No rules are active on a fresh install, so nothing changes until you configure it.
Finding a message
With debug: true, every message passing through prints a line like:
[7c0efe5f] "You need to wait #m #s." args=[9, 45] (no rule)
The first part is the key. The quoted part is the message with its numbers replaced by #. The args are the numbers that were taken out — available in replace as {0} and {1}.
Example
rules:
sleep-wait:
key: '7c0efe5f'
replace: '&7Wait &f{0}m &f{1}s &7before sleeping.'
to: actionbar
duration: 60
Rule options
| Option | Description |
|---|---|
match |
Text that must appear in the message. Both the visible text and the raw JSON are searched. |
key |
8-character ID from debug output. Takes priority over match if both are set. |
replace |
New text. Supports & colour codes and &x&R&R&G&G&B&B hex. Omit to keep the original wording. Set to none to delete. |
to |
chat, actionbar, title, subtitle or none |
cancel |
true deletes the message |
fade-in / stay / fade-out |
Title timing in ticks for this rule |
duration |
Action bar hold time in ticks (20 = 1 second) |
to also accepts message, hotbar, overlay, hidden, cancel and delete. Underscores, hyphens and capitals are ignored.
Rules are checked in file order and the first match wins. Rules using title or subtitle must also set replace, since titles are sent as new packets rather than modified in place.
Global settings
| Setting | Default | Description |
|---|---|---|
inspect-action-bar |
false |
Allow rules to match action bar messages. Off by default so other plugins' action bar output is never touched. |
debug |
false |
Print the key and normalised text of every message |
debug-once |
true |
Log each distinct message only once |
debug-ignore |
[] |
Keys or text to exclude from debug logging |
title-times |
10 / 40 / 10 | Default title fade-in, stay and fade-out in ticks |
Commands and permissions
| Command | Permission |
|---|---|
/messagestyler reload (alias /mstyler) |
messagestyler.reload — default op |
How it works
MessageStyler registers a PacketEvents listener on SYSTEM_CHAT_MESSAGE at NORMAL priority, so plugins listening at MONITOR still observe the final text.
Message keys are generated by extracting every text and translate value from the component JSON, stripping colour codes, collapsing whitespace, replacing digit runs with #, and taking the first four bytes of the SHA-256 digest as hex. The removed digits are kept in order and exposed as {0}, {1} and so on.
Only plain JSON strings are touched — no Adventure classes are referenced anywhere, which is what keeps the plugin portable across server versions.
Default config.yml
# MessageStyler
# ==================================================================
# Rewrites, restyles and reroutes the messages your server sends to
# players, so wording, colour and punctuation stay consistent no
# matter which plugin produced them.
#
# Every rule picks out a message and decides what happens to it:
# - rewrite the text
# - move it to the action bar, a title or a subtitle
# - delete it entirely
#
# Out of the box this file contains no active rules, so nothing on
# your server changes until you add one. All the examples near the
# bottom are commented out and ready to copy.
#
#
# QUICK START
# ==================================================================
# 1. Set debug: true below, then run /messagestyler reload
# 2. Trigger the message you want to change, in game
# 3. Watch the console. Every message prints a line like:
#
# [7c0efe5f] "You need to wait #m #s." args=[9, 45] (no rule)
#
# The first part is the key. The quoted part is the message with
# its numbers replaced by #. The args are the numbers that were
# taken out.
# 4. Add a rule using that key (see RULES at the bottom)
# 5. Run /messagestyler reload again
# 6. Set debug: false when you are finished
#
#
# IDENTIFYING A MESSAGE
# ==================================================================
# There are two ways to point a rule at a message. Use one or the
# other. If a rule sets both, "key" wins and "match" is ignored.
#
# key The eight character identifier shown in debug. It is built
# from the message's visible text with numbers replaced by #,
# so the same message always produces the same key even when
# its numbers change. Best for plugin messages, which have no
# translation key of their own.
#
# match Any text that appears in the message. Both the visible text
# and the raw JSON are searched, so vanilla translation keys
# such as block.minecraft.set_spawn work here too, and colour
# codes splitting a message into pieces will not stop a match.
#
# Rules are checked in the order they appear in this file, and the
# first one that matches is the one that applies.
#
#
# KEEPING THE NUMBERS
# ==================================================================
# The numbers removed when the key was generated are available in
# "replace" as {0}, {1}, {2} and so on, in the order they appeared.
# So a message can be completely restyled without losing its values.
#
# original You need to wait 9m 45s.
# replace '&7Wait &f{0}m &f{1}s &7before sleeping.'
# result Wait 9m 45s before sleeping.
#
#
# RULE OPTIONS
# ==================================================================
# match Text that must appear in the message. Required unless
# "key" is set.
#
# key Eight character identifier from debug. Required unless
# "match" is set.
#
# replace New text for the message. Supports & colour codes, and
# &x&R&R&G&G&B&B for hex colours.
# Leave it out to keep the original wording, which is
# useful when you only want to change "to".
# Set it to "none" to delete the message entirely.
#
# to Where the message should appear:
# chat normal chat message (the default)
# actionbar above the hotbar
# title large centre-screen text
# subtitle smaller text below the title
# none delete the message
# Aliases also accepted: message, hotbar, overlay, hidden,
# cancel, delete. Underscores, hyphens and capitals are
# ignored, so action_bar and ACTIONBAR both work.
#
# Titles are sent as new packets, so a rule using title or
# subtitle must also set "replace".
#
# cancel true deletes the message. Same as replace: none.
#
# fade-in
# stay
# fade-out Title timing in ticks for this rule only.
# 20 ticks = 1 second. Defaults come from title-times.
#
# duration How long an action bar message stays on screen, in ticks.
# 20 ticks = 1 second. Only applies when the message ends
# up on the action bar.
# Action bar text normally fades on its own after about
# three seconds. A shorter duration clears it early, and a
# longer one keeps it alive by resending.
# 0, the default, leaves the normal fade alone.
#
#
# GENERAL SETTINGS
# ==================================================================
# Action bar text reaches the client as a system chat message with an
# overlay flag set. Leave this false and such messages are ignored, so
# action bar output from other plugins is never touched. Set it to true
# only if you want rules to be able to match action bar messages too.
inspect-action-bar: false
# Prints the key and normalised text of every message passing through.
# Use it to discover keys, then turn it off again.
debug: false
# Log each distinct message only once instead of every time it is sent.
# Keeps the console readable when a plugin sends the same message over
# and over, for example something updating the action bar every tick.
debug-once: true
# Messages to leave out of debug logging entirely.
# Entries can be a key, or any text contained in the message.
# Useful for silencing one noisy plugin while you look for something else.
debug-ignore: []
# - '7c0efe5f'
# - 'X: '
# Default title timings in ticks. 20 ticks = 1 second.
# Individual rules can override any of these.
title-times:
fade-in: 10
stay: 40
fade-out: 10
# RULES
# ==================================================================
# Add your rules here. Every example below is commented out.
# Rule names (respawn-set, sleep-wait, and so on) are yours to choose
# and only appear in log messages.
rules:
# Restyle a vanilla message, matched by its translation key.
#
# respawn-set:
# match: 'block.minecraft.set_spawn'
# replace: '&7Respawn point set.'
# Restyle a plugin message using its generated key, keeping its
# numbers. {0} and {1} are the values from the original message.
#
# sleep-wait:
# key: '7c0efe5f'
# replace: '&7Wait &f{0}m &f{1}s &7before sleeping.'
# to: actionbar
# Move a message to the action bar but keep its original wording.
# No "replace", so the text is left exactly as it was.
#
# respawn-set-to-hotbar:
# match: 'block.minecraft.set_spawn'
# to: actionbar
# Show a message as a large title instead of a chat line, with
# timings just for this rule.
#
# respawn-set-as-title:
# match: 'block.minecraft.set_spawn'
# replace: '&aRespawn point set'
# to: title
# fade-in: 5
# stay: 30
# fade-out: 5
# Hold something on the action bar for exactly five seconds.
#
# brief-note:
# key: 'abc12345'
# replace: '&7Saved.'
# to: actionbar
# duration: 100
# Use a hex colour.
#
# fancy-note:
# key: 'abc12345'
# replace: '&x&5&5&F&F&A&ASaved.'
# Delete a message so nothing is shown at all.
# Either form works.
#
# hide-something:
# match: 'some.translation.key'
# replace: none
#
# hide-something-else:
# match: 'some.other.key'
# cancel: true


