Skip to main content

Nexal KOTL (King of the Ladder)

A competitive event where players race to a zone and hold it. Every game tick a player spends inside counts; when the match ends, whoever held the zone longest wins and the arena's winner commands run. Arenas, zones, schedules and rewards are managed from an in-game menu.

Features​

  1. Tick-accurate time tracking - Every game tick (1/20 s) in the zone counts; a player who logs out or dies stops scoring at once
  2. Multiple concurrent arenas - Run several matches at the same time, each with its own zone, duration and schedule
  3. Flexible zone definition - Use the block you stand on, or left-click two corners
  4. Cron scheduling - Start matches automatically with cron expressions (0 18 * * * for daily at 18:00)
  5. Custom winner rewards - Console commands per arena with %player%, %arena%, %ticks% and %seconds%
  6. Tie handling - One random winner among the tied players, or all of them
  7. Boss bar - The current leader (or the players in the zone), how many are in the zone and the time left
  8. Countdown warnings - Chat warnings and final countdown titles before a match ends, all configurable
  9. Arena holograms - Floating text above each arena with the leader, the time left or the next scheduled match
  10. Statistics and leaderboards - Wins, matches played and time in the zone, per arena and overall
  11. Admin menu - A hub with a settings screen and an arena editor: zone, duration, schedule, rewards, rename, delete, start and stop
  12. PlaceholderAPI - Stats, match state, schedules and leaderboards for scoreboards and holograms
  13. Dual storage - JSON or MySQL/MariaDB, with export and import to move between them
  14. History retention - Optionally remove matches older than a number of days or beyond a maximum count; stats and leaderboards are kept
  15. Customizable messages - Every message, title and sound in messages.yml

Technologies​

  • Paper API 1.20.1+ - Minecraft server API (Spigot compatible)
  • Utilizer - Configuration, messages, menus, holograms, tasks
  • ACF - Command framework
  • nexal-core - JSON and SQL persistence (MariaDB/MySQL), help menus
  • cron4j - Match schedules
  • PlaceholderAPI - Placeholder integration (optional)

Commands​

Player Commands​

CommandDescriptionPermission
/kotl or /kotl help [page]Show the help menuNone
/kotl listList all arenas and whether a match is runningNone
/kotl info [arena]Show an arena, or the running matches when no arena is givenNone
/kotl stats [player]Show wins, matches played, time in zones and win rateNone
/kotl leaderboard \<arena>Show the top 10 winners of an arena (aliases: lb, top)None

/kingoftheladder works in place of /kotl.

Admin Commands​

CommandDescriptionPermission
/kotl adminOpen the admin menu (Configuration and Arenas); from the console, show the admin helpnexalkotl.admin
/kotl admin help [page]Show the admin commands in chatnexalkotl.admin
/kotl admin cancelCancel a zone selection in progressnexalkotl.admin
/kotl admin exportExport all data to JSON files in plugins/NexalKOTL/export/nexalkotl.admin
/kotl admin importImport the JSON files from plugins/NexalKOTL/export/nexalkotl.admin

Admin Menu​

  • Configuration - Default duration, multiple winners, countdown, the boss bar (on/off, color, style, who it shows) and the history limits. Saved to config.yml; running matches keep going.
  • Arenas - Create an arena where you stand, then edit it: set the zone, the duration (presets or typed), the cron schedule, the winner commands, rename it, delete it, and start or stop a match.

Arena names use letters, digits, - and _, up to 32 characters, and cannot be global. Typed answers to menu prompts expire after 60 seconds; type cancel to stop early. Deleting an arena stops its match and schedule; its match history (subject to the history limits) and the players' stats are kept.

Permissions​

PermissionDescriptionDefault
nexalkotl.adminAdmin menu and admin commandsop

Placeholders​

Requires PlaceholderAPI. Arena names may contain _ and are matched ignoring case. Leaderboards are cached for 30 seconds.

Player Statistics​

PlaceholderDescription
%nexalkotl_wins%Total wins
%nexalkotl_wins_\<arena>%Wins in one arena
%nexalkotl_matches%Matches played (matches where the player entered the zone)
%nexalkotl_matches_\<arena>%Matches played in one arena
%nexalkotl_time%Total time in zones, formatted (1m 30s)
%nexalkotl_time_seconds%Total time in zones, in seconds
%nexalkotl_time_\<arena>%Time in one arena's zone, formatted
%nexalkotl_time_seconds_\<arena>%Time in one arena's zone, in seconds
%nexalkotl_winrate%Win rate (42.5%)

A running match counts toward matches played and time, with the time held so far.

Active Match​

PlaceholderDescription
%nexalkotl_active_\<arena>%yes while a match is running
%nexalkotl_remaining_\<arena>%Time left, formatted
%nexalkotl_remaining_seconds_\<arena>%Time left, in seconds
%nexalkotl_players_\<arena>%Players in the zone
%nexalkotl_inzone_\<arena>%yes if the player is in the zone

Schedule​

PlaceholderDescription
%nexalkotl_schedule_\<arena>%Time until the next scheduled match (N/A without a schedule)
%nexalkotl_schedule_seconds_\<arena>%Seconds until the next scheduled match (-1 without a schedule)

Leaderboards​

PlaceholderDescription
%nexalkotl_top_\<arena>_\<pos>_name%Player name at a position (1 to 100)
%nexalkotl_top_\<arena>_\<pos>_wins%Wins at a position
%nexalkotl_top_\<arena>_\<pos>_uuid%Player UUID at a position
%nexalkotl_top_global_\<pos>_name%Name at a position, across all arenas
%nexalkotl_top_global_\<pos>_wins%Wins at a position, across all arenas
%nexalkotl_top_global_\<pos>_uuid%UUID at a position, across all arenas

Arena Info​

PlaceholderDescription
%nexalkotl_arena_count%Number of arenas

Winner Command Placeholders​

PlaceholderDescription
%player%Winner's name
%arena%Arena name
%ticks%Time at the top, in ticks
%seconds%Time at the top, in seconds

Configuration​

config.yml​

# Most settings can also be changed in game: /kotl admin > Configuration.
# Changes apply without a restart and do not stop running matches;
# a storage change needs a restart.

storage:
type: json # json or sql
sql:
host: localhost
port: 3306
database: minecraft
username: root
password: ""

# Old matches can be removed with their zone entries and exits, on startup and after each
# match ends. Stats and leaderboards are kept; running matches are never removed.
history:
max-age-days: 0 # remove matches that ended more than this many days ago; 0 keeps them forever
max-entries: 0 # keep at most this many matches across all arenas, newest first; 0 for no limit

# Default match duration in seconds (each arena can override it in the menu)
default-duration: 300

# true: every player tied for first wins; false: one of them at random
allow-multiple-winners: false

bossbar:
enabled: true
color: YELLOW # RED, BLUE, GREEN, YELLOW, PURPLE, PINK, WHITE
style: SOLID # SOLID, SEGMENTED_6, SEGMENTED_10, SEGMENTED_12, SEGMENTED_20
# %arena%, %players% (names, see display-mode), %count% (players in the zone), %time% (seconds left)
title: "<gradient:#FF6B00:#FF8C00>\<bold>KOTL\</bold>\</gradient> \<gray>|\</gray> \<white>%players%\</white> \<gray>|\</gray> \<white>%count% in zone\</white> \<gray>|\</gray> \<white>%time%s\</white>"
display-mode: leader # leader: longest holder; current: players in the zone now
no-one-text: "No one"

countdown:
enabled: true
warnings: [60, 30, 10] # message keys countdown-\<X>s
final: [5, 4, 3, 2, 1] # message keys countdown-final-\<X>

messages.yml​

All messages are customizable with MiniMessage colors, sounds and titles, including the command output, the menu prompts and the hologram lines. Messages added in an update fall back to the defaults until you add them to your file.

Storage Migration​

  1. Export your data: /kotl admin export
  2. Change the storage type in config.yml (e.g. type: json to type: sql)
  3. Restart the server
  4. Import your data: /kotl admin import

Database Schema​

When using SQL storage, the plugin creates the following tables:

kotl_arenas​

ColumnTypeKeyDescription
idVARCHAR(64)PKArena name
worldVARCHAR(64)World name
minX, minY, minZINTZone minimum corner
maxX, maxY, maxZINTZone maximum corner
winnerCommandsTEXTJSON array of winner commands
cronScheduleVARCHAR(64)Cron expression for automatic matches
defaultDurationTicksINTArena duration in ticks (null = default)

kotl_matches​

ColumnTypeKeyDescription
idVARCHAR(36)PKMatch UUID
arena_idVARCHAR(64)FK → kotl_arenas.idArena
start_timeBIGINTStart timestamp (ms)
end_timeBIGINTEnd timestamp (ms)
duration_ticksINTMatch duration in ticks
winnersTEXTJSON array of winner UUIDs

kotl_zone_events​

ColumnTypeKeyDescription
idVARCHAR(36)PKEvent UUID
match_idVARCHAR(36)FK → kotl_matches.idMatch
player_idVARCHAR(36)Player UUID
event_typeVARCHAR(10)ENTER or EXIT
tickBIGINTMatch tick of the event

kotl_archived_stats​

Totals from matches removed by the history limits, so stats do not change when history is removed.

ColumnTypeKeyDescription
idVARCHAR(110)PK\<player UUID>:\<arena>
player_idVARCHAR(36)Player UUID
arena_idVARCHAR(64)Arena
winsINTWins in removed matches
matches_playedINTRemoved matches played
ticksBIGINTTime in the zone in removed matches, in ticks

Key Legend: PK = Primary Key, FK = Foreign Key

Installation​

  1. Download the plugin JAR
  2. Place it in the plugins folder (optionally with PlaceholderAPI)
  3. Start or restart the server
  4. Run /kotl admin, open Arenas and create your first arena
  5. Adjust config.yml or use Configuration in the admin menu