CenterMessage
Centers chat messages by measuring the rendered pixel width of the visible glyphs only, so color codes never break the alignment. Accepts legacy & / §, BungeeCord hex &#RRGGBB, Spigot hex §x§R§R§G§G§B§B and MiniMessage tags (<color>, <gradient>, <bold>, …) — mix any of them in the same string and it just works.
GitHub: senkex/CenterMessage · JitPack: jitpack.io/#senkex/CenterMessage
| MC | 1.16+ |
| Bytecode | Java 8 (runs on whatever JDK your server uses) |
| Platform | Bukkit / Spigot / Paper (any fork) |
| Adventure | Built into Paper. On Spigot, bundle adventure-platform-bukkit. |
Installation
Section titled “Installation”Replace VERSION with the latest release.
repositories { maven("https://jitpack.io")}
dependencies { implementation("com.github.senkex:CenterMessage:VERSION")}repositories { maven { url 'https://jitpack.io' }}
dependencies { implementation 'com.github.senkex:CenterMessage:VERSION'}<repositories> <repository> <id>jitpack.io</id> <url>https://jitpack.io</url> </repository></repositories>
<dependency> <groupId>com.github.senkex</groupId> <artifactId>CenterMessage</artifactId> <version>VERSION</version></dependency>Shading
Section titled “Shading”Relocate com.github.senkex.centermessage into your own namespace.
plugins { id("com.gradleup.shadow") version "8.3.5"}
tasks { shadowJar { relocate("com.github.senkex.centermessage", "my.plugin.libs.centermessage") }}<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.6.0</version> <configuration> <relocations> <relocation> <pattern>com.github.senkex.centermessage</pattern> <shadedPattern>my.plugin.libs.centermessage</shadedPattern> </relocation> </relocations> </configuration> <executions> <execution> <phase>package</phase> <goals><goal>shade</goal></goals> </execution> </executions></plugin>Quick start
Section titled “Quick start”CenterMessage.send(player, "&aHello &b<bold>World</bold>");
String line = CenterMessage.center("&#FF55AA Centered <ext");player.sendMessage(line);Adventure Component output for Paper / Adventure-native senders:
Component comp = CenterMessage.centerComponent("<gradient:#f00:#0f0>Hi</gradient>");player.sendMessage(comp);
Component custom = Component.text("Hello").color(NamedTextColor.AQUA);player.sendMessage(CenterMessage.centerComponent(custom));Mixed formats
Section titled “Mixed formats”Every supported color format is unified into MiniMessage internally and parsed once, so you can mix them in the same string:
CenterMessage.send(player, "&6[&aPrefix&6] &#FF55AAhex <bold>+ mini</bold> &land bold");Pipeline order: PlaceholderAPI → &#RRGGBB → &x → legacy-to-MiniMessage → MiniMessage parse.
CenterOptions
Section titled “CenterOptions”CenterOptions opts = CenterOptions.builder() .centerPx(80) .parseMiniMessage(false) .parsePlaceholders(true) .build();
CenterMessage.send(player, "&aTitle", opts);| Option | Type | Default | Notes |
|---|---|---|---|
centerPx | int | 154 | Half-width in pixels (chat = 154). |
parseLegacyAmp | boolean | true | Translate &x to §x. |
parseHexAmp | boolean | true | Translate &#RRGGBB to Spigot hex. |
parseMiniMessage | boolean | true | Parse MiniMessage tags through Adventure. |
parsePlaceholders | boolean | true | Expand PlaceholderAPI when a target is given. |
Prefabs: CenterOptions.CHAT (154 px), CenterOptions.SIGN (45 px), CenterOptions.BOOK (57 px), CenterOptions.ANVIL (50 px).
Multi-line and <center> blocks
Section titled “Multi-line and <center> blocks”centerLines centers every line independently:
String motd = "&6&lWelcome\n" + "&7Use /help for commands.\n" + "&8Powered by CenterMessage";
CenterMessage.sendBlock(player, motd);<center>...</center> lets you center only the lines you want — anything outside the block is sent verbatim:
CenterMessage.sendBlock(player, "<center>&6&lWelcome</center>\n" + "Not centered, sent as-is.\n" + "<center>&7Have fun.</center>");PlaceholderAPI
Section titled “PlaceholderAPI”When PlaceholderAPI is installed, every method that receives a Player or OfflinePlayer expands placeholders against that target before parsing:
CenterMessage.send(player, "&6Balance: &a%vault_eco_balance%");Facade reference
Section titled “Facade reference”| Method | Returns |
|---|---|
center(String, [CenterOptions], [OfflinePlayer]) | String |
center(String, int centerPx) | String |
centerComponent(String / Component, [CenterOptions], [OfflinePlayer]) | Component |
centerLines(String, [CenterOptions], [OfflinePlayer]) | String |
processCenterTags(String, [CenterOptions], [OfflinePlayer]) | String |
send(CommandSender / Audience, String / Component, [CenterOptions]) | void |
sendBlock(CommandSender, String, [CenterOptions]) | void |
broadcast(String, [CenterOptions]) | void |
colorize(String) | String — drop-in for ChatColor.translateAlternateColorCodes |
parse(String, [CenterOptions], [OfflinePlayer]) | Component |
translateAmpHex(String) | String — &#RRGGBB → §x§R§R§G§G§B§B |
Custom font widths
Section titled “Custom font widths”Width is measured against the vanilla Minecraft font. Custom resource packs that ship a different font can override individual characters at runtime:
FontInfo.registerWidth('►', 6);FontInfo.registerWidth('⬛', 8);Example: welcome banner
Section titled “Example: welcome banner”package com.example.plugin.listener;
import com.github.senkex.centermessage.CenterMessage;import org.bukkit.entity.Player;import org.bukkit.event.EventHandler;import org.bukkit.event.Listener;import org.bukkit.event.player.PlayerJoinEvent;
public final class WelcomeListener implements Listener {
private static final String[] BANNER = { "&8&m ", "<gradient:#ff55aa:#55aaff><bold>Nautic Network</bold></gradient>", "&7Welcome back, &f%player_name%&7.", "&7Online: &f%server_online%", "&8&m ", };
@EventHandler public void onJoin(final PlayerJoinEvent event) { final Player player = event.getPlayer(); for (String line : BANNER) { CenterMessage.send(player, line); } }}Example: scoreboard title
Section titled “Example: scoreboard title”String title = CenterMessage.center( "&6&l" + Bukkit.getServer().getName(), CenterOptions.builder().centerPx(40).build());
scoreboard.getObjective("display").setDisplayName(title);