The interface
Every screen the server writes for you: the sidebar, the action bar, nametags, the five chat channels, the profile card, GUIs and the update book.
The sidebar
The sidebar on the right of your screen is not a shared board. Every online player is put on their own private scoreboard so the numbers on it can be yours rather than the server's. It carries ten distinct score lines; six of them are live values and the rest are labels and spacers.
| Line | What it reads |
|---|---|
| Wallet | The coins you are physically carrying. |
| Bank | The sum of your bank accounts. Savings are excluded, which is the same basis /baltop ranks by. |
| Faction | Your current faction, or nothing if you have none. |
| Votes | Your vote count. |
| Online | How many players are on the server. |
| TPS | The server tick rate the plugin tracks itself. |
A sweep runs every 40 ticks, which is 2 seconds. It does not redraw your board every time: it builds a small snapshot of your faction, wallet, bank, TPS bucket, online count and votes, compares it to the last one, and skips you entirely if nothing moved. TPS is bucketed rather than read to the decimal, so a minor fluctuation does not churn the board.
One consequence is worth knowing. The Faction text line rides the 2 second sweep, but the [TAG] above your head does not: faction changes are pushed to every viewer immediately. If you join a faction and the tag appears before the sidebar line does, that is the design, not a bug.
If you want a number now rather than on the next sweep, /money prints your wallet, home account and all accounts, /tps prints the tracked tick rate and /ping prints your latency. All three act immediately.
The action bar
The line above your hotbar is driven by a single bus. Nothing else in the plugin is allowed to write there; a build guard fails the build if any feature calls the raw send method directly.
The important property is that a contribution carries a number and a label, not a finished string. Formatting happens only at the flush. That is what makes merging work: kill twelve mobs in one tick and you get one line with the total, not twelve segments reading Hunter +12c beside each other.
| Merge policy | Effect |
|---|---|
SUM | Contributions sharing a label collapse into one line carrying the sum. |
MAX | The highest value wins. |
REPLACE | The newest contribution wins. |
RIDER | Money with no label of its own folds into the highest priority labelled money line. It will never fold into a company line, so buff money cannot land inside a firm's receipt. |
Frames are keyed by channel and source, so a feature that files both a money receipt and a status readout under one id keeps them apart. The four channels are MONEY, PROGRESS, STATUS and WARNING. Skill XP arrives as a STATUS component on the same bus rather than starting a timer of its own.
The number on the bar is the number that moved
A money component carries the payout result object and reads the credited figure off it. What you see is the amount that reached you after your faction tax and after any active booster, not the amount the feature asked for. The tax percentage printed beside it is the clamped rate the charge actually used, not the raw stored rate.
If you are clocked in at a company the coins go to the firm instead of your wallet. The bar says so plainly and names the firm, and because nothing was taxed in your wallet there is no tax line invented to sit under it.
An action bar fades after roughly three seconds, so an unchanged frame still has to be re-sent. The flusher runs every tick but re-sends an unchanged frame only every 40 ticks, which is once every 2 seconds. A twenty thousand kill session therefore costs one send every two seconds for as long as it lasts, not twenty thousand sends.
Nametags and the team model
The name above your head is a scoreboard team. The model is deliberately unusual: one team per player, per board. Nobody shares a team with anybody. The team id is bl_ followed by the first twelve hexadecimal characters of your UUID, fifteen characters in total, so it is stable, unique and survives a rename.
| Part of the tag | What it holds |
|---|---|
| Prefix | The [V] vanish marker if a staff member is vanished, then your bought title. |
| Suffix | Your faction [TAG]. |
| Colour | Relation tint first, then your bought nametag colour, then your faction colour, then white. |
| Flags | Friendly fire, collision rule and nametag visibility. |
Because every attribute is a field on your own team rather than a separate team, nothing can evict you from anything. The relation tint is computed per viewer on every resolve, so an ally or war colour cannot go stale: the moment the relation ends the colour is gone, for everyone, without a rebuild.
Faction creates, joins, leaves, kicks, transfers, disbands, relation changes and a bought colour all push instantly, for you and for every bystander. Promotions and demotions do not refresh the tag, because the tag encodes title, bought colour and faction suffix, never rank. Use /f info to read a rank.
What one team per player costs
Several vanilla behaviours are defined between members of the same team, and they cannot survive a model where no two players share one. These are stated plainly rather than left to be discovered.
- Friendly fire is re-implemented by the plugin against the same faction setting, so nothing regresses. One difference: vanilla refused the hit before any event fired, while the plugin cancels an event the combat tagger has already seen, so swinging at a faction mate with friendly fire off now puts you in combat.
canSeeFriendlyInvisibleshas no cross-player effect any more. The flag is still written, but it cannot work without a shared team.- The collision rules
FOR_OWN_TEAMandFOR_OTHER_TEAMSdegenerate.ALWAYS, the default, andNEVERare unaffected. - Tab list grouping is gone. The client sorts the tab list by team name, so faction members are no longer adjacent. This is intrinsic to any per-player team model.
Your bought nametag colour costs 25,000 coins and applies in chat, above your head and in the tab list, whether or not you have a faction. On Bedrock the scoreboard entry is always your raw name including the Floodgate . prefix, because that is the form the client matches.
Chat channels and private messages
There are five chat channels plus private messaging. The channel commands are switches: they act the moment you type them, with no confirmation step, and everything you type afterwards goes to that channel until you switch again.
| Channel | Command | Who hears it | Gate |
|---|---|---|---|
| Global | /gc | Everyone online | none |
| Local | /lc | Players near you | none, but proximity limited |
| Faction | /fc | Your faction | you need a faction |
| Allies | /fac | Your faction and its allies | you need a faction |
| Staff | /sc | Staff | helper permission |
| Private | /msg, /tell, /w | One named player | needs at least a name and a message |
| Reply | /r, /reply | The last player you messaged | no tab completion, so type the message out |
Global chat renders as [G] <tag> <Name> > <message>. Your bought chat tag sits in front of your name and your bought nametag colour wraps the name itself, so your colour in chat is always yours and is never borrowed from anyone else.
Seven chat tags and seven nametag colours are offered. Both lists were trimmed from eight so that a row of seven centres properly in a nine wide inventory row; the tags sit at slots 10 to 16 and the colours at slots 28 to 34. If you already own the dropped ghost tag or the dropped blue colour it stays applied to you, it is simply no longer offered for reselection.
Filters and gates
- A chat cooldown applies to everyone.
- Mutes and maintenance mode gate chat and the chat-like commands, so a mute cannot be routed around by switching channel.
- The profanity filter runs on chat. It also runs on your custom death message: the text is validated before you are charged, it must contain the literal
{player}placeholder and it must be clean. If it fails you stay in setup mode and can retype without paying again.
Every message you receive goes through one funnel. On Java you get the full interactive component, so a command inside a message is clickable. On Bedrock the click and hover parts are stripped, and the visible text of a command is always the command itself: /faction accept rather than a button reading [Accept]. That is deliberate, because a label with the command hidden behind it would leave a Bedrock player holding a word they cannot use.
The profile card
/profile opens a 54 slot card that gathers what is otherwise scattered across several commands. Staff can open it on another player, which shapes one of its design decisions.
Your three job slots sit at slots 29, 31 and 33. Each slot shows the job icon, its proper display name and a Next: <rank> (<xp> XP) line measured against the ladder.
| Rank | XP threshold |
|---|---|
| Apprentice | 0 |
| Journeyman | 5,000 |
| Expert | 20,000 |
| Master | 60,000 |
| Legend | 150,000 |
The third slot shows a red locked placeholder until you buy the third job slot from /shop for 150,000 coins. Once bought it is a real slot everywhere: XP awards, job switching, mastery and ability triggers all honour it.
The card also carries your buff totals and a read-only mob drop mode card showing the mode you are on and the rule it enforces. That card is deliberately not clickable. Because staff open /profile on other players, a click there would silently change the viewer's own mode from somebody else's profile, which is exactly the kind of surprise this plugin spends whole passes removing. Use /mobdrops to change it.
Click identity is resolved through an inventory holder, not by reading the window title, so the screen behaves the same on Bedrock. The barrier at slot 53 closes it.
How the GUIs behave
Almost every screen in the plugin follows one visual grammar: 54 slots, a glass header row across slots 0 to 8 with the title card at slot 4, content restricted to columns 1 to 7, a navigation row at slots 45 to 53, and the border fill painted last.
Content cells are centred by formula, and there are two different formulas because an odd count and an even count cannot centre the same way.
| Items in a row | Slots used |
|---|---|
| 1 | 4 |
| 2 | 3, 5 |
| 3 | 3, 4, 5 |
| 4 | 2, 3, 5, 6 |
| 5 | 2, 3, 4, 5, 6 |
| 6 | 1, 2, 3, 5, 6, 7 |
| 7 | 1 to 7 |
Column 4 is occupied only when the count is odd. Four rows of seven give a 28 cell content grid, which is why paginated screens such as /baltop and the market board show 28 entries per page with previous and next arrows in the navigation row.
The dispatch rules
Each of these is a bug that already shipped in this codebase once, and is now a rule.
- Clicks are cancelled first, before any routing.
DOUBLE_CLICKis ignored, because a double click is how a stack gets gathered off a screen.- Only clicks in the top inventory act. A click in your own inventory is cancelled and dropped.
- Navigation and paging resolve before any grid index arithmetic, so turning a page can never be read as clicking the item that will sit there afterwards.
- Identity comes from a stamp on the item or a shared filtered list, never an index into a live one.
- Your state is re-resolved on every click rather than trusted from when the screen opened.
- No screen takes or gives an item, except the small number of screens that genuinely need an input slot. Those keep exactly one writable slot, cancel everything else, and return the item on every close including a disconnect.
- Opening another screen replaces the window instead of closing it first.
- Every click emits feedback, because a silent success reads as a dead button.
- Drags touching a top inventory slot are cancelled. A drag spreads a stack across several slots in one event and is not a click, so cancelling clicks does nothing to stop it.
Numbers printed on cards are read live from the service that enforces them rather than baked in, so a help page cannot drift away from the price it quotes. Where a value is genuinely unmeasured the card says so instead of showing a zero.
Bedrock: taps, forms and fallbacks
Bedrock players reach the server through Geyser and Floodgate, and the interface is built so that no control is Java only.
Left-click drives everything. Newer screens are left-click only by rule: preset amount buttons, plus and minus steppers, cyclers and confirms. There is no anvil rename and no sign input anywhere in the banking, faction tax, bounty, company or NPC screens. Where a genuinely free-text value is needed, a company name, a payee, a tax expression, the screen hands you a typeable command instead of a text field.
Gestures are treated as unreliable. Geyser sends UNKNOWN click types for a tap, so screens that use shift-click as a Java gesture accept any click on Bedrock for the same action. Paging deliberately accepts a plain left click on both platforms, because requiring shift to turn a page would collide with shift being the Java select gesture.
Forms versus chest screens
Some surfaces have a real Bedrock form. A form is a list of buttons, which brings three consequences:
- Bedrock has no hover, so the whole of a row's lore is folded into its button label. That is where the cost and the affordability verdict live, and dropping it would leave a Bedrock player tapping blind at an expensive purchase. The fold is capped at 1600 characters.
- Form buttons are positional, so a non-clickable row still gets a button. Omitting one would shift every later index and silently mis-route every click below it.
- If a form cannot be sent, the screen falls back to the chest renderer rather than leaving you with no surface at all.
A form cannot accept an item, so any screen with an input slot is a native chest GUI by necessity: the enchant station, the crafting bench and similar screens are rendered by Geyser as chests and are completable end to end that way. Every one of them also has a typeable command path.
Two known gaps, stated rather than hidden. The /updates screens have no form renderer, so on Bedrock you get the Geyser translated chest; nothing is unreachable because delivery uses the form path and /updates has a full chat fallback. And the writs form renderer writes "Page 1 of 3" into the body without emitting page buttons, so a Bedrock player on a paginating writs screen has no way to reach page 2.
The update book
Every release writes an entry into an in-game changelog. At plugin version 1.28.8 there are 62 entries, ids 0 to 61, starting with a Welcome entry and running to the newest release. Ids are never renumbered, because your read position points into that space.
How an entry reaches you
When you join with unread entries, three things happen in a fixed order:
- A chat line goes out first, and its visible text is
/updates. This is deliberate: if the book or the form fails to render for any reason, the notification itself is never lost. - On Java you are handed a transient written book.
- On Bedrock you get a form instead.
Your read position is a high-water mark: the highest id you have seen. It is never compared against a maximum, so if the server is ever rolled back to an older build, entries above your mark simply do not exist yet and you are shown nothing rather than being re-shown things you have already read.
Reading them later
/updates opens the list at any time. It is a standard 54 slot screen: back at slot 45, previous at 47, close at 49 and next at 53. Entries are written for players rather than for operators, name their commands in full so the text is typeable, and carry a Bedrock note wherever the two platforms differ.
The update book is a changelog, not a tutorial. If you want to be walked through the forging system step by step, that is /forge tutorial, which has 10 paths and 19 steps.
Everything else that writes to your screen
A few surfaces sit outside the main four. They are short, but they are the ones people ask about.
| Surface | What it is |
|---|---|
| Server list | A packet listener rewrites the message of the day and the player hover before you ever connect. Maintenance mode swaps in a maintenance message so you can see the server is closed rather than guessing from a failed login. This is why ProtocolLib is the one hard dependency. |
| Spawn screen | A returning player is taken to the spawn screen and given a countdown back to where they logged out, with /tpc to cancel it. The countdown only runs when a return location was actually stored, so a genuine first join simply stays at spawn with nothing to cancel. |
| Rotating broadcasts | A repeating task posts server notices to chat on a configured interval. |
| Boss bars | Used where something is counting down. Clock in at a company and you get one showing live accrual and the real time remaining until your payslip. Boss bars are memory only and are torn down on quit and on shutdown, so a crash cannot leave one stuck on your screen. |
| Titles | Reserved for the few moments that are worth interrupting you for, such as coming within reveal range of a rift and learning its coordinates. |
Connect on Java at blacklight-network.de, or on Bedrock at blacklight-network.de port 19132. The server runs Paper 26.1.2.
Much of the newer interface work is marked in the developer documentation as code-written and not server-verified. Where this page states a slot number, an interval or a threshold, that is what the code does; if you find a screen behaving differently, it is worth reporting rather than assuming the page is right.