MegaBlock Survivors Leaderboard
MegaBlock Survivors records qualifying runs to a persistent leaderboard stored in plugins/MegaBlockSurvivors/leaderboard.yml. Cheated runs (any match where /mbs cheat was used) are explicitly excluded.
The plugin reads and validates the existing file before adding a result. If reading fails, it refuses the new result and displays the last successfully loaded entries. Saves replace the file atomically; a failed save preserves the previous file and does not apply the new result. Check the server log for these failures.
What Gets Recorded
Only one outcome per mode produces an entry:
| Mode | Recorded on | Not recorded |
|---|---|---|
| Challenge | Victory (the final boss in WORLD_4 dies) | Dying mid-run, quitting, or disconnecting |
| Endless | Death (Endless has no victory path) | Quitting or disconnecting |
A dead Challenge attempt does not rank. Runs flagged by /mbs cheat are skipped in both modes. /mbs skipworld currently has no permission requirement and does not set that flag, so the filter does not establish that every ranked run followed normal world progression.
Categories
Each entry carries a game mode and a difficulty tag, so the leaderboard is split into 6 independent buckets:
| Mode | Difficulty |
|---|---|
| Challenge | Easy |
| Challenge | Medium |
| Challenge | Hard |
| Endless | Easy |
| Endless | Medium |
| Endless | Hard |
Buckets are ranked independently, and each bucket holds up to 100 entries on disk. The top 10 are surfaced to players.
Ranking Rules
| Mode | Primary sort | Tiebreaker |
|---|---|---|
| Challenge | Fastest completion time (ascending) | Newer entries win ties |
| Endless | Highest wave reached (descending) | Time survived (longer ranks higher), then newer entries win ties |
This split makes sense because Challenge mode has a fixed endpoint (the final boss), so "fastest completion" is the obvious skill metric. Endless has no end, so "highest wave reached" is the meaningful measure.
Because highestWave comes from elapsed time, Endless entries that tie on wave survived for similar times. The longer of those runs ranks first. MegaBlock Survivors sorts entries each time it reads them, so runs already saved in leaderboard.yml follow this order too.
In-World Hologram
A single TextDisplay hologram is spawned in the mbs_spawn lobby world (at world coordinates ~4.5, 67, -14.5). The hologram is bottom-anchored -- the bottom edge of the text always sits at the anchor Y so adding new sections grows the display upward rather than downward through the floor.
The hologram renders up to six sections (Challenge x {Easy, Medium, Hard} followed by Endless x {Easy, Medium, Hard}). Sections with zero entries are silently skipped so a fresh server doesn't display six empty buckets. If every bucket is empty, a single "no highscores yet" line is shown instead.
The hologram is maintained automatically:
- On plugin enable / reload.
- After a new leaderboard entry, an existing display's text is refreshed. A stale tracked entity is respawned; if no display was ever spawned, this refresh does not create one.
- When the anchor chunk in
mbs_spawnreloads (Paper removes non-persistent display entities on chunk unload, so the listener re-spawns the hologram every time the lobby chunk comes back).
If mbs_spawn is not loaded, spawning is skipped and an informational message is logged.
Per-Run Chat Display
When a qualifying non-cheated run is recorded, the player sees the top 10 of its bucket as a chat block. Quits and failed Challenge attempts do not call this leaderboard display. The player's own row is highlighted (> #N). If the player's rank is 11-100, an ellipsis row is shown followed by their rank. An entry trimmed outside the retained top 100 has no rank line.
Cheated victories show a "Leaderboard not updated (cheating detected)" notice instead.
Entry Schema
Each entry tracks:
| Field | Description |
|---|---|
playerName | The Bukkit account name (Player.getName()) at run-end. |
playerUUID | The player's UUID. |
timeSeconds | Total duration of the run in seconds. |
kills | Total kills for the run. Bosses count; ghost-army mobs do not (they are reward-disabled and award no kill credit). |
level | Player's final level. |
highestWave | Wave level at run end -- max(1, secondsSurvived / 36). Primary stat for Endless. |
gameMode | CHALLENGE or ENDLESS. |
difficulty | EASY, MEDIUM, or HARD. |
timestamp | Epoch seconds when the run ended (Instant.now().getEpochSecond()). Also used as the tiebreaker key. |
Legacy entries from before this split are auto-tagged with Challenge / Medium on read so old leaderboards continue to render.
Clearing the Leaderboard
There is no in-game command to wipe the leaderboard. To reset, stop the server and delete plugins/MegaBlockSurvivors/leaderboard.yml.