TAB Server Badge¶
Adds a small server tag, like [Build], after a player's name in the tablist so you can see which
server they are on. The tag only shows to people on a different server.
What it does¶
- Registers one TAB placeholder on the Velocity proxy:
%rel_serverbadge%. - The placeholder shows
[Label](dark gray brackets, gray text) after a player who is on a different server from you. Players on your own server show no tag. - Server keys map to these labels:
| Velocity server | Badge |
|---|---|
main |
[Main] |
info |
[Vanilla Hub] |
hub |
[Hub] |
build |
[Build] |
staging |
[Staging] |
events |
[Events] |
Any other server shows its own name with the first letter capitalized, for example lobby shows
[Lobby].
It runs on the proxy because only the proxy can see players on two backends at once. A PlaceholderAPI relational placeholder runs on a backend, which knows nothing about players on other backends, so it cannot do this job.
How players use it¶
Players do not use any commands. They open the tablist (hold Tab). A friend on build reads
[Rank] Name [Build]. A friend on the same server reads [Rank] Name with no badge.
Staff guide¶
There are no commands or permissions.
Turn the badge on or off. The badge appears only where TAB's config uses the placeholder. It
goes in the proxy's plugins/tab/groups.yml, in the _DEFAULT_ group, like this:
_DEFAULT_:
tabsuffix: "%luckperms-suffix%%rel_serverbadge%"
Remove %rel_serverbadge% from that line to hide the badge. Then run btab reload on the proxy
console (or /btab reload in game). No restart is needed for a TAB config change.
Rank groups in groups.yml do not set their own tabsuffix, so the one _DEFAULT_ line covers
every rank. TAB looks up each property separately and falls back to _DEFAULT_.
tagsuffix (the name above a player's head) is left alone on purpose. Nametags only show for
players on the same server, so the badge would always be empty there.
Before editing, fetch the live groups.yml and check whether the placeholder is in it today.
Do not trust this page for the current live value.
Check that it works. Stand on main while a friend is on build. Their tablist entry should
end in [Build]. Players on main should have no badge.
Configuration¶
This plugin has no config file. The server labels are set in code (SERVER_LABELS in
src/main/java/com/snowbirdmv/tabserverbadge/TabServerBadgePlugin.java). To change a label, edit
that map, rebuild, and replace the jar on the proxy. A new jar needs a Velocity restart; Velocity
never hot-loads plugin jars.
Requirements in TAB's own config on the proxy:
global-playerlist.enabled: trueinplugins/tab/config.yml. Without it, players on other servers are not in your tablist at all.%rel_serverbadge%in a TAB property, as shown in the Staff guide.
Data and storage¶
None.
Troubleshooting¶
| Symptom | Cause | Fix |
|---|---|---|
Every name ends in the literal text %rel_serverbadge% |
The jar is not loaded, or it has not re-registered after a TAB reload | Check the proxy log for the lines below. If the plugin is loaded, wait a second; it checks every second and re-registers on its own |
| No badges at all | %rel_serverbadge% is not in tabsuffix, or global-playerlist is off |
Check plugins/tab/groups.yml and plugins/tab/config.yml, then btab reload |
A badge shows the raw key, like [Lobby] |
The server is not in SERVER_LABELS |
Add it in code and rebuild |
Proxy log lines when it is working:
TAB Server Badge plugin loaded.
Registered TAB placeholder %rel_serverbadge%.
Reparsed TAB suffixes for N online player(s).
After btab reload you should also see TAB reload detected. Re-registering %rel_serverbadge%.
followed by the Registered line again.
Maintainer notes¶
- Why it polls. TAB may not be ready when this plugin starts, and
btab reloadthrows away placeholders added through the API. So the plugin checks every second and registers again when needed. - Why it does not trust the reload event alone. TAB 6 can replace its event bus during a reload
before the old
TabLoadEventlistener hears about it. The plugin also notices when TAB hands out a newPlaceholderManager, so the one-second poll recovers even when the event is missed (seen 2026-08-29). - Why it reparses suffixes. TAB parses each player's suffix during reload, before addon placeholders come back. Re-registering alone would leave the literal text in place. After it registers, the plugin sets each online player's suffix again through TAB's API and then clears the override, so TAB reads the original value with the placeholder now available. Custom API suffixes are kept.
- Cost. TAB checks relational placeholders for every pair of players, so the work grows with players squared. The function is only a string compare. The refresh interval is 1000 ms (it must be a multiple of 50).
- How TAB does it:
Property#getFormat(viewer)fills%rel_*%with(viewer, owner), andGlobalPlayerListformats cross-server entries throughPlayerList#getTabFormat(target, viewer), once per viewer. - First deploy bundle, with the
groups.ymldiff and rollback copy:manual_uploads/2026-08-04-tab-server-badge/in the ops repo.
Building¶
JAVA_HOME=/Library/Java/JavaVirtualMachines/temurin-21.jdk/Contents/Home ./gradlew build
Java 21. Output: build/libs/tab-server-badge-1.0.0.jar. Compiles against the Velocity API
3.4.0-SNAPSHOT and TAB-API 6.0.0 (from JitPack). Install it in the proxy's plugins/ folder and
restart Velocity.
Full command, permission and config tables: Reference.