Frostline Racing
Frostline Racing is a Paper server plugin for ice boat racing. Servers can create arena tracks, let players join races, queue for active arenas, spectate races, track stats and leaderboards, configure race presentation, and optionally use Premium features such as cosmetics, visual setup tools, ranked racing, and PlaceholderAPI expansion values.
Current public version: 1.0
Current server target:
- Paper
1.21.6+, including newer26.xbuilds. - Java 21 on pre-26.1 builds.
- Java 25 on Paper 26.1+ if the server requires it.
Future roadmap includes investigating Paper 1.20+ support, but 1.20 support should not be advertised until the jars are audited and smoke-tested on 1.20.x, 1.21.x, and current 26.x servers.
Editions
Free
Free includes the complete core racing loop:
- Arena racing.
- Multiple arenas.
- Ordered checkpoints.
- Multiple laps.
- Race countdowns.
- Finish placement tracking.
- DNF handling.
- Race timeout.
- Queueing.
- Spectating.
- Arena browser GUI.
- Smart quick join.
- Persistent SQLite stats.
- Race and lap leaderboards.
- Configurable messages, UI, sounds, lobby items, and command rewards.
- Admin arena setup commands.
- Optional per-arena randomized starting-grid assignment.
- Optional WorldEdit selection support for setup commands.
- Optional PlaceholderAPI consumption inside Frostline config strings.
Free is generally feature-frozen except for bug fixes, compatibility work, documentation, shared fixes, and the 1.0 randomized-grid option.
Premium
Premium includes Free plus:
- Cosmetics.
- Cosmetic selection GUI.
- Premium visual setup preview.
- Premium setup wand.
- Premium setup dashboard GUI.
- Ranked racing foundation.
- Premium PlaceholderAPI expansion values.
- Dynamic top 10 PlaceholderAPI leaderboard values.
- Premium setup GUI music preview.
- Customizable Premium GUI icons, including
PLAYER_HEADbase64 textures and texture URLs.
Premium features remain gated to Premium builds or explicitly composed Partner builds.
Commands
Primary command:
/frostline
Legacy alias:
/iceboat
Player Commands
/frostline join <arena>
/frostline join random
/frostline quickjoin
/frostline arenas
/frostline browser
/frostline leave
/frostline spectate <arena>
/frostline status <arena>
/frostline stats [player]
/frostline top <arena>
/frostline toplap <arena>
/frostline music <on|off>
Premium or ranked-gated player commands:
/frostline cosmetics
/frostline join <arena> ranked
/frostline join random ranked
/frostline quickjoin ranked
/frostline quickjoin <player> ranked
/frostline rank [player]
/frostline rankedtop [page]
/frostline ranked history [player] [page]
/frostline quickjoin <player> is an admin queue action and requires frostline.admin.queue.
Admin Commands
/frostline admin about
/frostline admin reload
/frostline admin forcestart <arena>
/frostline admin debug <arena>
/frostline admin testsound [key]
/frostline admin queue [arena]
/frostline admin clearqueue <arena|all>
/frostline admin clearwaiting <arena>
/frostline admin reset <arena>
/frostline admin kick <arena> <player>
/frostline admin items
/frostline admin items all
Setup commands:
/frostline admin validate <arena>
/frostline admin create <arena>
/frostline admin delete <arena> --confirm
/frostline admin setlobby <arena>
/frostline admin setspectator <arena>
/frostline admin addstart <arena>
/frostline admin clearstarts <arena> --confirm
/frostline admin setbounds <arena>
/frostline admin addcheckpoint <arena>
/frostline admin clearcheckpoints <arena> --confirm
/frostline admin setfinish <arena>
/frostline admin setdisplayname <arena> <display name>
/frostline admin setplayers <arena> <min|max> <number>
/frostline admin setlaps <arena> <laps>
/frostline admin setrandomstarts <arena> <enabled|disabled>
/frostline admin setwaitingcountdown <arena> <seconds>
/frostline admin setcountdown <arena> <seconds>
/frostline admin enable <arena>
/frostline admin disable <arena>
Music setup commands:
/frostline admin setmusic <arena> resource-pack <key> [volume] [pitch]
/frostline admin setmusic <arena> nbs <file.nbs> [volume] [pitch]
/frostline admin setmusic <arena> off
/frostline admin previewmusic <arena>
Stats maintenance commands:
/frostline admin stats resetplayer <player> --confirm
/frostline admin stats resetarena <arena> --confirm
/frostline admin stats resetall --confirm
/frostline admin stats pruneinvalid --confirm
/frostline admin stats export [file]
/frostline admin stats import <file> --confirm
Premium admin commands:
/frostline admin preview <arena|off>
/frostline admin wand <arena|off>
/frostline admin setup <arena>
Ranked admin commands:
/frostline admin setranked <arena> <enabled|disabled>
/frostline admin ranked setrating <player> <rating> --confirm
/frostline admin ranked race <race-id>
Permissions
Common player permissions:
| Permission | Default | Purpose |
|---|---|---|
frostline.join | true | Join arenas and quick join. |
frostline.browse | true | Open the arena browser. |
frostline.leave | true | Leave races, waiting lobbies, queues, or spectating. |
frostline.spectate | true | Spectate active races. |
frostline.status | true | View arena status. |
frostline.stats | true | View player stats. |
frostline.top | true | View best race times. |
frostline.toplap | true | View best lap times. |
frostline.music | true | Toggle personal music. |
frostline.ranked.join | true | Join ranked races when ranked is available. |
frostline.ranked.stats | true | View ranked stats. |
frostline.ranked.top | true | View ranked leaderboard. |
frostline.cosmetics | true | Open the Premium cosmetics menu. |
Admin parent permission:
frostline.admin
Admin child permissions:
frostline.admin.about
frostline.admin.reload
frostline.admin.forcestart
frostline.admin.debug
frostline.admin.testsound
frostline.admin.music
frostline.admin.queue
frostline.admin.reset
frostline.admin.kick
frostline.admin.stats
frostline.admin.ranked
frostline.admin.items
frostline.admin.setup
Cosmetic unlock permissions are defined per cosmetic. Bundled examples use nodes such as:
frostline.cosmetics.trail.snow
frostline.cosmetics.finish.sparkle
frostline.cosmetics.win.fireworks
Legacy iceboat.* permission aliases remain available for compatibility.
Dependencies And Soft Hooks
Required:
- Paper server.
Optional:
- WorldEdit: used by arena setup commands that read a player's WorldEdit selection for bounds, checkpoints, and finish regions.
- PlaceholderAPI: lets Frostline config strings consume placeholders from other PlaceholderAPI expansions. Premium builds also register Frostline's own
%frostline_*%expansion.
The plugin should still run without WorldEdit or PlaceholderAPI.
Files And Storage
Runtime data folder:
plugins/FrostlineRacing
Main config files:
| File | Purpose |
|---|---|
config.yml | Core settings, SQLite storage mode, music settings, shared lobby items, command rewards, and Premium defaults after Premium has merged its overlay. |
config-premium.yml | Bundled Premium-only defaults merged into config.yml by Premium builds; not packaged in Free builds. |
config-mysql.yml | Bundled MySQL defaults merged into config.yml when the active edition has the MYSQL gate. |
arenas.yml | Arena definitions and setup data. Runtime arena edits update this file. |
messages.yml | Chat messages, browser labels, item labels, and fallback legacy UI message keys. |
ui.yml | Countdown/race/spectator titles, bossbars, actionbars, and scoreboards. |
sounds.yml | Race sound effects. |
cosmetics.yml | Premium cosmetics definitions and cosmetics GUI layout. |
setup-gui.yml | Premium setup dashboard GUI layout. |
cosmetic-selections.yml | Premium per-player cosmetic selections. |
stats.db | SQLite stats, leaderboards, and ranked tables when SQLite storage is used. |
Config files are automatically updated with missing default keys while preserving existing custom values.
Current config version: 1.0.
Current storage backend:
storage.mode: sqliteis the default backend.storage.mode: mysqlenables current Premium shared persistence work. Current Premium MySQL support writes casual stats and ranked results asynchronously after schema health succeeds and serves player stats plus race/lap/ranked leaderboards from in-memory caches.- MySQL storage is controlled by the
MYSQLfeature gate. Premium ships it by default; Partner builds can opt into it explicitly; Free builds do not package the MySQL provider. - Premium MySQL mode includes connection settings, async health diagnostics, first-version schema migration, async casual race-result writes, async ranked persistence, and cached read refreshes.
storage.mysql.cache-refresh-secondscontrols bounded polling for cached MySQL reads. This is not cross-server coordination or proxy messaging.- Premium MySQL cache warmup registers loaded arena leaderboards and currently online/joining players, then refreshes as soon as schema health is ready.
- Race-result persistence uses an async repository boundary so MySQL writes and cache refreshes do not block race-finish callbacks.
- Premium MySQL mode writes casual race results, total player stats, best race/lap times, ranked ratings, and ranked race history after schema health succeeds. Player stat and leaderboard reads are served from cache.
/frostline rankperforms a targeted read-through for the requested ranked player on Premium MySQL so cross-server Elo changes can appear immediately. Ranked leaderboards and PlaceholderAPI reads remain cache/poll based.- Ranked joins are blocked while stats storage is unavailable.
Arena Model
An arena includes:
enableddisplay-nameleaderboard-keyworldmin-playersmax-playerslapswaiting-countdown-secondscountdown-secondsrace-timeout-secondsrandomize-start-positionsallowed-modes- ranked minimum player settings
- optional music
- lobby spawn
- spectator spawn
- bounds region
- start positions
- ordered checkpoint regions
- finish region
Arena ids come from arenas.yml. Display names may use MiniMessage formatting.
leaderboard-key controls the stats and leaderboard identity for an arena. By default it matches the arena id. Servers that eventually share persistence can keep the same key for replicas of the same track, or use different keys for unrelated tracks with the same local arena id.
randomize-start-positions: true shuffles racers once per countdown attempt across the first N valid start positions in their configured order. The existing roster-lock, cancellation, and insufficient-position behavior remains unchanged.
Arena Setup Workflow
Basic setup flow:
- Create an arena with
/frostline admin create <arena>. - Set lobby and spectator spawns.
- Add enough start positions for the arena's max player count.
- Set arena bounds.
- Add checkpoint regions in order.
- Set the finish region.
- Set player counts, laps, and countdown values.
- Run
/frostline admin validate <arena>. - Enable the arena with
/frostline admin enable <arena>.
WorldEdit can be used for region-based setup commands:
/frostline admin setbounds <arena>/frostline admin addcheckpoint <arena>/frostline admin setfinish <arena>
Premium setup tools add:
/frostline admin preview <arena|off>for visual particle previews./frostline admin wand <arena|off>for in-world setup controls./frostline admin setup <arena>for the setup dashboard GUI.
Race Flow
Common player flow:
- Players join an arena directly, through the arena browser, or through quick join.
- Waiting arenas start a waiting countdown when enough players are present.
- The start countdown teleports racers to start positions and applies the configured movement restriction.
- Racers drive through checkpoints in order for the configured lap count.
- Racers finish, DNF, disconnect, or time out.
- Results are displayed.
- Stats and rewards are processed.
- The arena resets after
settings.post-game-seconds.
If a race is active and the arena is full, players can queue for the next race. Queued players are promoted after reset when space is available.
Spectators can join active races and use spectator items to navigate racers.
Race Rules And Settings
Important settings in config.yml:
| Setting | Default | Purpose |
|---|---|---|
settings.checkpoint-scan-period-ticks | 2 | How often checkpoints and finish regions are checked. |
settings.post-game-seconds | 8 | Delay before reset after a race ends. |
settings.reconnect-grace-seconds | 15 | Time disconnected racers/queued players/spectators can reconnect. |
settings.scoreboards-enabled | true | Global scoreboard toggle. |
settings.clear-inventory-during-race | true | Save and clear inventories during races. |
settings.countdown-movement-mode | locked | Movement rule during countdown: locked, look, or move. |
settings.bounds-teleport-cooldown-seconds | 2 | Cooldown for out-of-bounds return teleport. |
settings.last-racer-behavior | declare_winner | Behavior when only one unfinished racer remains. |
settings.finish-mode | wait_all | Race finish mode: wait_all or first_finish_delay. |
settings.first-finish-delay-seconds | 60 | DNF timer after first finisher when using first_finish_delay. |
Last-racer behavior:
declare_winner: remaining racer wins immediately.cancel: race ends without auto-finishing the remaining racer.continue: remaining racer must finish or hit timeout.
Finish modes:
wait_all: race ends after every non-DNF racer finishes or timeout hits.first_finish_delay: first finisher starts a timer; unfinished racers are DNF when it expires.
Stats And Leaderboards
Frostline records:
- races played
- finished races
- wins
- DNF count
- best race times
- best lap times
Commands:
/frostline stats [player]
/frostline top <arena>
/frostline toplap <arena>
Admin maintenance:
/frostline admin stats resetplayer <player> --confirm
/frostline admin stats resetarena <arena> --confirm
/frostline admin stats resetall --confirm
/frostline admin stats pruneinvalid --confirm
/frostline admin stats export [file]
/frostline admin stats import <file> --confirm
Declared winners receive placement and win credit but do not create artificial race-time or best-lap leaderboard entries.
Reconnect Grace
Disconnect behavior:
- Disconnecting during a race removes the player's boat but keeps progress for the grace window.
- Reconnecting in time returns the racer at their last valid checkpoint or start location.
- Expiring the grace window marks the racer DNF.
- Disconnecting while queued keeps the queue slot for the grace window.
- Disconnecting while waiting removes the player from the waiting lobby immediately.
- Disconnecting while spectating can restore spectator state if the race is still active.
Queued Reload
/frostline admin reload is safe during active sessions:
- If arenas are idle, reload runs immediately.
- If sessions are busy, reload is queued.
- New joins are blocked while reload is pending.
- Active races finish normally.
- Reload runs after all sessions become idle.
Lobby Items
Configurable lobby hotbar items live in config.yml:
- arena selector
- quick join
- Premium cosmetics item
- return-to-lobby item
Admins can toggle lobby items:
/frostline admin items
/frostline admin items all
If lobby-items.clear-inventory-on-join is false, Frostline tries to place items in configured slots and moves or drops occupied items safely.
The return-to-lobby item can run a player or console command.
Race UI And Sounds
Race presentation is configurable through ui.yml:
- countdown title/subtitle
- countdown bossbar
- countdown actionbar
- countdown scoreboard
- race title/subtitle
- race bossbar
- race actionbar
- race scoreboard
- spectator scoreboard
Sound effects are configurable through sounds.yml:
- countdown tick
- final countdown
- race start
- checkpoint
- lap
- finish
- DNF
- personal best
Admins can test sounds:
/frostline admin testsound [key]
Messages And Placeholders
messages.yml controls chat text and many labels. Text supports:
- MiniMessage formatting.
- Legacy
&color codes. - Hex colors.
- Frostline placeholders in both
{name}and%name%styles. {prefix}and%prefix%.- PlaceholderAPI placeholders from other plugins when PlaceholderAPI is installed and a player context is available.
Default chat messages use {prefix}.
The configured prefix lives at:
messages:
prefix:
text: "<gray>[<aqua>Frostline Racing<gray>] "
PlaceholderAPI
Free and Premium can consume external PlaceholderAPI placeholders inside Frostline config strings when PlaceholderAPI is installed.
Premium also registers Frostline's own expansion:
%frostline_*%
Legacy aliases remain available:
%iceboat_*%
Available placeholder groups:
- session state
- arena identity
- race progress
- session counts
- persistent stats
- ranked stats
- dynamic top 10 race-time leaderboards
- dynamic top 10 lap-time leaderboards
See PLACEHOLDERAPI.md for the full placeholder list.
Music
Each arena can have one race song.
Supported music sources:
.nbsfiles inplugins/FrostlineRacing/music.- custom resource-pack sound keys.
Music starts when the race begins and stops when the race ends or a player leaves/DNFs/disconnects outside active grace.
Player toggle:
/frostline music on
/frostline music off
Admin setup:
/frostline admin setmusic <arena> resource-pack <key> [volume] [pitch]
/frostline admin setmusic <arena> nbs <file.nbs> [volume] [pitch]
/frostline admin setmusic <arena> off
/frostline admin previewmusic <arena>
music.preview-seconds controls preview duration.
Music uses SoundCategory.RECORDS, so the client Jukebox/Note Blocks volume slider applies.
Rewards
Command rewards are configured in config.yml and run as console.
Hooks:
- participation
- finish
- dnf
- first-place
- second-place
- third-place
Reward placeholders:
%player%
%uuid%
%arena%
%placement%
%status%
%time%
%best_lap%
Rewards are disabled by default.
Premium Cosmetics
Premium cosmetics include:
- countdown effects
- trails
- lap effects
- finish effects
- win effects
Players open the menu with:
/frostline cosmetics
Cosmetics are configured in cosmetics.yml.
Current behavior:
- Selections are stored in
cosmetic-selections.yml. - Cosmetics can be permission-gated.
- Locked cosmetics can be visible or hidden.
- Left-click selects a cosmetic.
- Right-click previews without saving.
- Selected items use enchanted glint.
- Cosmetic display items can use normal materials or
PLAYER_HEADicons with base64 textures or texture URLs. - Invalid materials or particles warn once and skip that cosmetic.
- Particle counts are capped by config.
Premium Setup Tools
Premium setup tools include:
- visual preview
- setup wand
- setup dashboard GUI
Commands:
/frostline admin preview <arena|off>
/frostline admin wand <arena|off>
/frostline admin setup <arena>
Preview:
- Read-only.
- Sends particles only to the previewing player.
- Shows bounds, checkpoints, finish, start positions, lobby spawn, and spectator spawn.
- Can preview disabled or incomplete arenas from
arenas.yml.
Wand:
- Replaces the admin's inventory while active.
- Restores inventory, armor, offhand item, and selected hotbar slot when exited.
- Sneak-right-click cycles modes.
- Location modes save the player's current location.
- Region modes use left-click and right-click corners.
Setup dashboard:
- Validates setup.
- Toggles preview.
- Equips wand.
- Edits display name.
- Sets lobby, spectator, start, bounds, checkpoints, and finish.
- Clears starts/checkpoints through confirmation screens.
- Adjusts min/max players, laps, waiting countdown, and start countdown.
- Toggles randomized starting-grid assignment.
- Toggles ranked mode when ranked is available.
- Previews arena music.
- Enables or disables the arena.
- Uses
setup-gui.ymlfor GUI layout and item customization.
Ranked Racing
Ranked is Premium-only in the current public builds.
Current ranked scope:
- Casual and ranked race modes.
- Per-arena
allowed-modes. - Per-arena ranked minimum player count.
- Ranked browser mode toggle.
- Ranked join commands.
- Ranked stats and race history in
stats.dbfor SQLite mode, or MySQL tables when Premium MySQL storage is enabled. - Conservative pairwise Elo-style rating updates.
- Configurable rating-derived divisions shared by ranked commands, leaderboards, diagnostics, and placeholders.
- Deterministic player history pagination and admin race inspection with copyable race ids.
- Ranked leaderboards.
- Ranked PlaceholderAPI values.
Commands:
/frostline join <arena> ranked
/frostline join random ranked
/frostline quickjoin ranked
/frostline quickjoin <player> ranked
/frostline rank [player]
/frostline rankedtop [page]
/frostline ranked history [player] [page]
/frostline admin setranked <arena> <enabled|disabled>
/frostline admin ranked setrating <player> <rating> --confirm
/frostline admin ranked race <race-id>
Current ranked limitations:
- No seasons yet.
- No advanced matchmaking yet.
- No team ranked modes yet.
- No native ranked rewards yet.
Admin Diagnostics
Admins can run:
/frostline admin about
The report includes:
- plugin/version/edition
- build artifact and platform metadata
- generated timestamp
- server version
- Bukkit version
- Java version
- database file state
- enabled and reserved feature gates
- active hooks
- arena counts
- arena list
- session counts
- reload-pending state
- important config values
The chat report includes a clickable copy button.
Build And Artifacts
Final artifacts include:
- Free universal
- Premium universal
- Free Linux
- Premium Linux
- Free Mac
- Premium Mac
- Free Windows
- Premium Windows
OS-specific artifacts filter SQLite native libraries for their target platform.
The validation command used during development is:
./gradlew test premiumJar validateArtifactMatrix
Current State
Implemented:
- Free core racing.
- Persistent SQLite stats.
- Arena setup commands.
- WorldEdit setup support.
- Config updater for default keys.
- Race UI and sounds.
- Music.
- Reconnect grace.
- Queued reload.
- Command rewards.
- Lobby items.
- Rebrand to Frostline Racing with
/iceboatcompatibility. - Free/Premium artifact validation.
- Premium cosmetics.
- Premium setup tools.
- Premium ranked foundation.
- Premium PlaceholderAPI expansion.
- Free and Premium PlaceholderAPI config consumption.
- Admin diagnostics.
- Premium Advanced Music phase playlists.
Known current product direction:
- Free gameplay is generally frozen after the 1.0 randomized-grid addition, aside from bugs and compatibility work.
- Release 1.0 adds shared randomized grids plus Premium ranked divisions and history/review tools.
- Advanced Premium Music is gateable through
ADVANCED_MUSICso future Partner builds can include it explicitly. - A future compatibility pass may investigate Paper 1.20+ support.
Recommended next Premium priority:
- Stabilize and multiplayer-test the 1.0 randomized grids and ranked history/divisions.
- Ranked/MySQL polish after live testing.
- Cosmetics/setup polish based on feedback.
- Dynamic arena instances and full multi-arena matchmaking.
- Native reward integrations only if command rewards are insufficient.
Current Limitations
- Multiplayer testing still depends on live server owners/admins/players reporting issues.
- Free has no further planned gameplay additions after the 1.0 randomized-grid option.
- Full network coordination is not implemented; current Premium MySQL support is shared persistence only, including async casual stats writes, async ranked persistence, and cached player stat/leaderboard reads.
- Dynamic arena instances are scaffolded for future composition but not implemented.
- Advanced music currently selects one configured track when a phase begins; Premium setup GUI editing is available, but continuous playlist chaining and drag-and-drop playlist ordering are not implemented yet.
- Ranked seasons and advanced matchmaking are not implemented yet.
- Native economy/crate/permission reward integrations are not implemented yet.
- Paper 1.20+ support is a future investigation, not a current support promise.