
LPC – LuckPerms Chat Formatter ✨
A flexible chat formatting plugin with MiniMessage support for LuckPerms
Modern chat formatting powered by MiniMessage, full LuckPerms metadata support, group/track formats, and PlaceholderAPI.
🧩 Compatibility
| Minecraft | 26.1.2 |
| Server | Paper (recommended) or Spigot |
| Java | 25+ |
🔧 Requirements
- LuckPerms (Required) – Permissions plugin
- PlaceholderAPI (Optional) – Additional placeholders
✅ Features
Formatting
- Full MiniMessage support, with group- and track-specific formats
- Optional PlaceholderAPI integration and
[item]placeholder (hover tooltip on Paper) - Per-rank message styling and per-rank gradient names (
{gradient-name}) - Per-world toggle via
disabled-worlds
Social (on by default)
- @Mention pings – highlight online names + sound/action-bar ping (Paper)
- Emoji shortcuts – e.g.
:heart:→ ❤ (fully configurable) - Clickable links – URLs become
openUrllinks on Paper, coloured on Spigot
Moderation (off by default)
- Anti-spam cooldown, repeated-message blocker, caps filter, profanity mask, anti-advertising
- Per-player mute (
/lpc mute) + LuckPerms mute node for punishment plugins
Server messages (off by default)
- MiniMessage join / quit / first-join / death messages
Quality of life
/lpc reload · version · help · mute · unmutewith tab completion- Built-in Modrinth update checker
- Safe by design – player messages can never inject
click/hover/command components - Works on both Paper (Adventure rendering) and Spigot (legacy fallback)
⌨️ Commands
| Command | Permission | Description |
|---|---|---|
/lpc reload |
lpc.reload |
Reload the configuration |
/lpc version |
– | Show the installed version |
/lpc help |
– | List available commands |
/lpc mute <player> [duration] |
lpc.mute |
Mute a player (e.g. 10m, 2h; omit for permanent) |
/lpc unmute <player> |
lpc.mute |
Unmute a player |
🧑💼 Permissions
| Permission | Default | Description |
|---|---|---|
lpc.reload |
op | Reload the configuration |
lpc.chatcolor |
false | Use colour codes & cosmetic MiniMessage tags in chat |
lpc.itemplaceholder |
false | Use the [item] placeholder in chat |
lpc.update |
op | Receive an update notification on join |
lpc.emoji |
true | Use emoji shortcuts (only enforced if emoji.require-permission) |
lpc.chatlinks |
true | Have URLs turned into clickable links |
lpc.mention.exempt |
false | Opt out of receiving mention pings |
lpc.mute |
op | Use /lpc mute and /lpc unmute |
lpc.muted |
false | Marks a player as muted (usually set by a punishment plugin) |
lpc.bypass.spam / .repeat / .caps / .profanity / .advert |
op | Bypass the matching moderation filter |
ℹ️ Even with
lpc.chatcolor, only cosmetic tags (colours, decorations, and optionally gradients/rainbow) are honoured in player messages. Interactive tags (click,hover,insertion, …) are always stripped.
⚙️ Configuration (config.yml)
# Main chat format (MiniMessage!)
chat-format: "{prefix}{name}<dark_gray> »<reset> {message}"
# Per-group formats (optional)
group-formats:
# default: "<gray>[User]</gray> {name}<dark_gray> »<reset> {message}"
# admin: "<red>[Admin]</red> {name}<dark_gray> »<reset> {message}"
# Per-track formats (optional) – groups take priority over tracks
track-formats:
# staff_track: "<gold>[Staff]</gold> {name}<dark_gray> »<reset> {message}"
# Enable the [item] placeholder
use-item-placeholder: true
# Allow <gradient> / <rainbow> for players with lpc.chatcolor
allow-gradient-tags: true
# Worlds where LPC does NOT format chat
disabled-worlds: []
# Check Modrinth for updates on startup
update-checker: true
# Reload message
reload-message: "<green>Reloaded LPC configuration!"
🪄 Available Placeholders
| Placeholder | Description |
|---|---|
{message} |
The chat message (inserted safely, never re-parsed) |
{name} |
Player's name |
{displayname} |
Display name / nickname |
{world} |
Player's current world |
{prefix} / {suffix} |
Highest priority prefix / suffix |
{prefixes} / {suffixes} |
All prefixes / suffixes, highest priority first |
{username-color} / {message-color} |
Colour values from LuckPerms meta |
ℹ️ All colour values (prefix, suffix, etc.) must be in MiniMessage format – no legacy codes (
&a,§b).
🚀 Installation
- Stop your server
- Drop
LPC-<version>.jarinto your/pluginsfolder - Start the server to generate
config.yml - Edit the config to your liking
- Run
/lpc reloadto apply changes ✅
🛠️ Building
./gradlew shadowJar
# output: build/libs/LPC-<version>.jar
Requires JDK 25.
📌 Notes
- Not affiliated with LuckPerms – please do not contact the LuckPerms author for support.
- Legacy version available at: GitHub Legacy LPC
📸 Previews
Chat Format Example

[ITEM] Placeholder Example

🚀 Installation
- Stop your server
- Place the
LPC.jarinto your/pluginsfolder - Start the server to generate configuration files
- Edit the
config.ymlto your liking - Use
/lpc reloadto apply your changes ✅
All Versions
+ Add VersionNo more picking the right build. LPC 4.4.0 ships a **single universal jar** that runs on **Paper 1.21.x (incl. 1.21.11) AND Paper 26.2**. Just download
LPC-4.4.0.jar and it works on your server, whatever the version.### Why one jar works
Compiled once against Paper 1.21 / Adventure 4 / Java 21 (
api-version: 1.21):api-version: 1.21is accepted by Paper 26.2 (forward-compatibility)- Java 21 bytecode runs on Java 25
- the Adventure APIs LPC uses stay binary-compatible across Adventure 4 → 5
A new
crossCompatTest CI task proves this every build by running the Adventure-4-compiled tests against an Adventure 5 runtime — the exact thing a Paper 26.2 server does. (It already caught and fixed one real incompatibility.)### 🐛 [item] permission fix
[item] needs the lpc.itemplaceholder permission — which previously defaulted to false, tripping up users (even admins) who only enabled the config. Now:lpc.itemplaceholderdefaults to **op** → ops can use[item]immediately- players who type
[item]without the permission get a friendly **in-chat hint** - to enable
[item]for everyone:/lp group default permission set lpc.itemplaceholder true
### Platform detection
- startup log:
Running on Paper (API 1.21-R0.1) on Java 21 [Paper/Adventure chat] /lpc versionnow shows the build target **and** the live runtime (API + Java) — great for support
### Still includes
- the 4.2.0 chat click/hover/insertion exploit fix (defence-in-depth sanitizer)
- MiniMessage chat formatting, LuckPerms group/track formats, PlaceholderAPI, @mentions, emojis, clickable links, [item], moderation toolkit
### Requirements
- [LuckPerms](https://luckperms.net/) (required) · [PlaceholderAPI](https://www.spigotmc.org/resources/placeholderapi.6245/) (optional)
- Paper 1.21.x – 26.2, Folia or Spigot · Java 21+
- Full changelog:** https://github.com/Ayont/LPC-with-minimessage/compare/4.3.0...4.4.0
This release ships **two jars** so LPC runs on both old and new servers. Pick the one for your platform on the [Modrinth download page](https://modrinth.com/plugin/lpc-chat) (Modrinth's game-version filter shows the right one automatically):
| Build | Minecraft | Java | Adventure | api-version |
|---|---|---|---|---|
| **
LPC-4.3.0.jar** *(default)* | 26.2 | 25 | 5.2.0 | 26.2 || **
LPC-4.3.0-legacy.jar** | 1.21.x *(incl. 1.21.11)* | 21 | 4.23.0 | 1.21 |### Why two jars?
Adventure 4 (bundled by Paper 1.21) and Adventure 5 (bundled by Paper 26.2) are **binary-incompatible** — a single jar cannot reliably run on both. The same LPC source now compiles + passes all tests against **both** Adventure versions; the Gradle
-Ptarget=modern|legacy switch selects the platform.### 🔒 Still includes the 4.2.0 security fix
The defence-in-depth
ComponentSanitizer (strips click/hover/insertion from player & item-name output) is in **both** builds.### Bug fixes & UX
- Fixes the recurring **\"Unsupported API version\"** / **\"plugin won't load on 1.21.11\"** reports — use the
-legacyjar on Paper 1.21.x / Java 21. /lpc versionnow reports the **build target** (e.g.Build: Minecraft 1.21.x · Java 21 · Adventure 4.23.0 (legacy)) so support can tell which jar you installed.build.ymlCI runs a modern + legacy matrix on every PR.
### Installation
- Paper 26.2 / Java 25** → download
LPC-4.3.0.jar - Paper 1.21.x / Java 21** (incl. 1.21.11) → download
LPC-4.3.0-legacy.jar
Requires [LuckPerms](https://luckperms.net/). [PlaceholderAPI](https://www.spigotmc.org/resources/placeholderapi.6245/) optional.
- Full changelog:** https://github.com/Ayont/LPC-with-minimessage/compare/4.2.0...4.3.0
This release ships **two jars** so LPC runs on both old and new servers. Pick the one for your platform on the [Modrinth download page](https://modrinth.com/plugin/lpc-chat) (Modrinth's game-version filter shows the right one automatically):
| Build | Minecraft | Java | Adventure | api-version |
|---|---|---|---|---|
| **
LPC-4.3.0.jar** *(default)* | 26.2 | 25 | 5.2.0 | 26.2 || **
LPC-4.3.0-legacy.jar** | 1.21.x *(incl. 1.21.11)* | 21 | 4.23.0 | 1.21 |### Why two jars?
Adventure 4 (bundled by Paper 1.21) and Adventure 5 (bundled by Paper 26.2) are **binary-incompatible** — a single jar cannot reliably run on both. The same LPC source now compiles + passes all tests against **both** Adventure versions; the Gradle
-Ptarget=modern|legacy switch selects the platform.### 🔒 Still includes the 4.2.0 security fix
The defence-in-depth
ComponentSanitizer (strips click/hover/insertion from player & item-name output) is in **both** builds.### Bug fixes & UX
- Fixes the recurring **\"Unsupported API version\"** / **\"plugin won't load on 1.21.11\"** reports — use the
-legacyjar on Paper 1.21.x / Java 21. /lpc versionnow reports the **build target** (e.g.Build: Minecraft 1.21.x · Java 21 · Adventure 4.23.0 (legacy)) so support can tell which jar you installed.build.ymlCI runs a modern + legacy matrix on every PR.
### Installation
- Paper 26.2 / Java 25** → download
LPC-4.3.0.jar - Paper 1.21.x / Java 21** (incl. 1.21.11) → download
LPC-4.3.0-legacy.jar
Requires [LuckPerms](https://luckperms.net/). [PlaceholderAPI](https://www.spigotmc.org/resources/placeholderapi.6245/) optional.
- Full changelog:** https://github.com/Ayont/LPC-with-minimessage/compare/4.2.0...4.3.0
### Security (important — fixes chat click-command exploit)
- Defence-in-depth sanitizer** against chat click / hover / insertion exploits. A new
ComponentSanitizerrecursively stripsclickEvent/hoverEvent/insertionfrom **player message** and **item-name** output. - Closes the exploit reported on Discord where players could type
<click:run_command:…>that executes when clicked. The restricted cosmetic parser already rejected these tags; the sanitizer is a belt-and-suspenders guarantee that no interactive event can ever reach chat — even via nested children or a crafted anvil-renamed item. - Cosmetic styling (colours, decorations) is preserved. Legacy/Spigot output is inherently safe (serializes to
§-codes that cannot carry events). - Tests: 43 (incl. 7 new sanitizer cases), 0 failures.
### Platform
- Minecraft 26.2** (Paper 26.2),
api-version: 26.2 - Adventure 5.2.0** — the version Paper 26.2 bundles (Paper 26.1 shipped Adventure 4.x, so 4.2.0 requires Paper 26.2+)
- Java 25**
> ⚠️ If you get
Unsupported API version 26.2 or the plugin won't load: update to **Paper 26.2 + Java 25**. Older servers (1.21.x / Java 21) cannot run this build.### Dependency updates (folds in the open Renovate PRs)
- LuckPerms
5.4 → 5.5, PlaceholderAPI2.11.6 → 2.12.2, Gson2.13.2 → 2.14.0, JUnit5.11.4 → 5.14.4, Gradle8.14 → 8.14.5,actions/setup-java v5,gradle/actions v6
### Build & CI
- New
build.yml** runsclean buildon every push/PR (there was no CI before). - Fixed
publish.yml: Gradle 8.14 cannot run on Java 25 (its Groovy rejects class file major 69), so Gradle now runs on **Java 21** and compiles via the **Java 25 toolchain** (auto-provisioned by the newfoojay-resolver-convention).
### Branding & UX
- Author rebranded **Varilx-Development → Veylor-Development** (the team behind veylor.net — free plugins on Modrinth).
/lpc versionnow reports the detected platform + target (MC 26.2 · Java 25 · Adventure 5).- README: compatibility table + "Unsupported API version" guidance + a direct answer to "can players use MiniMessage in chat?".
### Issues closed
- #22 (PlaceholderAPI placeholder in
chat-formatcrashing) — fixed by the 2.0 pipeline. - #26 (non-op parsing placeholders) — fixed; player messages are never passed through PlaceholderAPI.
- #37 (/msg question) — answered; LPC is a chat formatter, pair it with EssentialsX/HuskChat.
- Full changelog:** https://github.com/Ayont/LPC-with-minimessage/compare/4.1.0...4.2.0
## 4.1.0 — Folia Support
- Minecraft:** 26.1.2 · **Java:** 25 · **API version:** 26.1.2
Native Folia support with region-aware scheduling while retaining full Paper/Spigot compatibility.
### Added
folia-supported: trueinplugin.yml.- Cross-platform scheduler abstraction in
de.ayont.lpc.scheduler: Schedulerinterface withrun,runAsync,runDelayedandrunOnEntity.PaperSchedulerImplusingGlobalRegionScheduler,AsyncSchedulerandEntityScheduler.BukkitSchedulerImplfallback for plain Spigot/Bukkit.- Runtime platform detection via
Schedulers.create(...). - Folia detection in
LPCwith dedicated log output. onDisablecancels all scheduled tasks cleanly.
### Changed
UpdateCheckernow schedules its network request viaplugin.getScheduler().runAsync(...).MentionService.pingAllnow schedules per-target pings viaplugin.getScheduler().runOnEntity(...).
### Compatibility
- Verified on Folia 26.1.2 build 8.
- Paper/Spigot fallback remains intact.
> **Note:** LPC itself is now Folia-compatible, but LuckPerms must also be a Folia-compatible build, otherwise Folia will refuse to load the dependency.
## 4.0.0
- Released:** 2026-06-15
- Minecraft:** 26.1.2 · **Java:** 25 · **API version:** 26.1.2
Major rewrite release with a new MiniMessage chat formatter, an integrated moderation toolkit, and a much more flexible configuration.
### Added
- New MiniMessage chat formatter** with a clear separation between trusted format strings and player messages.
- Group & track formats** per LuckPerms group or track (
group-formats,track-formats). [item]placeholder** – shows the held item in chat (hover tooltip on Paper).- Placeholder support:**
{prefix},{suffix},{prefixes},{suffixes},{world},{displayname},{username-color},{message-color}, and{gradient-name}. - Optional PlaceholderAPI integration** for formats.
- @Mentions** with highlighting, sound + action-bar ping on Paper (Spigot gets highlighting only).
- Emoji replacement** via configurable shortcuts like
:heart:→ ❤. - Clickable links** in chat (
openUrl, clickable on Paper, colored/underlined on Spigot). - Per-rank message styles** – groups/tracks can get their own message coloring without needing MiniMessage permissions.
- Gradient names** via LuckPerms meta or per group (
{gradient-name}). - Join / quit / first-join / death messages** in MiniMessage format, individually toggleable.
- Integrated moderation toolkit** (all toggleable):
- Anti-spam cooldown
- Repeat-message filter
- Caps filter (BLOCK or LOWERCASE)
- Profanity filter (BLOCK or MASK)
- Anti-advertising / anti-IP (BLOCK or REDACT)
- Mute system** with
/lpc mute <player> [duration]and/lpc unmute <player>, plus support for external mute permission nodes. - Modrinth update checker** with in-game notification for players with
lpc.update. - Paper & Spigot compatibility** with automatic fallback to legacy rendering.
- Unit tests** for emoji replacement, legacy colors, mentions, player messages, URL linkification, moderation text checks, and version comparison.
### Changed
- Complete rewrite of chat rendering: player messages are inserted as pre-built components and are never re-parsed.
- Interactive tags (
click,hover,insertion, …) in player messages are always stripped. - Default config bumped to
config-version: 3.
### Security
- Player messages cannot inject MiniMessage tags or PlaceholderAPI placeholders.
- Prefix/suffix values and format strings are parsed in a trusted context.
- Gradient specifications are validated against an allowed character set.
### Permissions
lpc.reload,lpc.chatcolor,lpc.itemplaceholder,lpc.updatelpc.emoji,lpc.chatlinks,lpc.mention.exemptlpc.mute,lpc.mutedlpc.bypass.spam,lpc.bypass.repeat,lpc.bypass.caps,lpc.bypass.profanity,lpc.bypass.advert
### Known Limitations
- Legacy color codes (
&a,§b) in prefixes/suffixes are not supported – use MiniMessage.
>
- Updated to the newest Gradle #8
### Important: Hoverevent with the **Spigot** is at the moment not working!

### - Some Fixes and 1.21.4 Supprot!
- Support my New Project: https://dev.varilx.de/**
### - Some Fixes and 1.21.4 Supprot!
- Support my New Project: https://dev.varilx.de/
- Added Track Formatting.
### - Fixed Group-formats null check error.
- Optimized Code.**
- Added a config option for the [item] placeholder
- Added a permission for the [item] placeholder
- Fix for the [item] placeholder triggering for individual characters
- e.g. sending a message with just "i" would also trigger the placeholder
- Fix for the [item] placeholder adding the hoverevent to the entire message
- Added a config option for the reload Message.