Skip to content

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

MC1.16+
BytecodeJava 8 (runs on whatever JDK your server uses)
PlatformBukkit / Spigot / Paper (any fork)
AdventureBuilt into Paper. On Spigot, bundle adventure-platform-bukkit.

Replace VERSION with the latest release.

build.gradle.kts
repositories {
maven("https://jitpack.io")
}
dependencies {
implementation("com.github.senkex:CenterMessage:VERSION")
}
build.gradle
repositories {
maven { url 'https://jitpack.io' }
}
dependencies {
implementation 'com.github.senkex:CenterMessage:VERSION'
}
pom.xml
<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>

Relocate com.github.senkex.centermessage into your own namespace.

build.gradle.kts
plugins {
id("com.gradleup.shadow") version "8.3.5"
}
tasks {
shadowJar {
relocate("com.github.senkex.centermessage", "my.plugin.libs.centermessage")
}
}
pom.xml
<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>
CenterMessage.send(player, "&aHello &b<bold>World</bold>");
String line = CenterMessage.center("&#FF55AA Centered &ltext");
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));

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 opts = CenterOptions.builder()
.centerPx(80)
.parseMiniMessage(false)
.parsePlaceholders(true)
.build();
CenterMessage.send(player, "&aTitle", opts);
OptionTypeDefaultNotes
centerPxint154Half-width in pixels (chat = 154).
parseLegacyAmpbooleantrueTranslate &x to §x.
parseHexAmpbooleantrueTranslate &#RRGGBB to Spigot hex.
parseMiniMessagebooleantrueParse MiniMessage tags through Adventure.
parsePlaceholdersbooleantrueExpand PlaceholderAPI when a target is given.

Prefabs: CenterOptions.CHAT (154 px), CenterOptions.SIGN (45 px), CenterOptions.BOOK (57 px), CenterOptions.ANVIL (50 px).

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>");

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%");
MethodReturns
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

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);
WelcomeListener.java
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);
}
}
}
String title = CenterMessage.center(
"&6&l" + Bukkit.getServer().getName(),
CenterOptions.builder().centerPx(40).build());
scoreboard.getObjective("display").setDisplayName(title);
Last updated: May 26, 2026 by Senkex in a5eb086