Nexal Lottery
A lottery for Minecraft servers. Players buy tickets with in-game money, every ticket adds to the prize pool, and a draw on a cron schedule picks a winner weighted by ticket count. The winner gets the pool minus an optional tax, the server can run reward commands, and every player's lifetime statistics are tracked. Server owners manage settings, draws and data from an in-game admin GUI.
Features
- Scheduled Draws - Draws run on any cron expression (hourly, every 2 hours, daily at noon, ...)
- Timezone Support - The schedule and all displayed draw times follow the configured timezone, not the server clock
- Weighted Winner Selection - Each ticket is one chance; more tickets means a higher win chance
- Lottery GUI -
/lotteryshows the next draw, prize pool, tax, your tickets, win chance, lifetime stats and the last 5 draws, refreshed every second - Quick-Buy Buttons - Buy 1, 10, 100, 1K or 10K tickets from the GUI in one click, or any amount with Custom Amount: type the number in chat (
cancelaborts), then confirm the tickets and total cost on a confirmation screen - Ticket Limits and Cooldowns - Optional per-player ticket cap per round and a cooldown between purchases
- Tax on Winnings - An optional percentage of the pool is taken before the winner is paid
- Winner Rewards - Vault payout (can be turned off) plus console commands with
%player%,%amount%,%tax_amount%and%tax_percentage% - Draw Warnings - Broadcasts with sounds 30, 10, 5 and 1 minutes before a draw; add or remove intervals in
messages.yml - Winner Announcements - A broadcast and title for everyone, a personal message for the winner, and fireworks around the winner that never hurt anyone
- Purchase Alerts - Players see when others buy tickets and can turn it off with
/lottery alerts; admins can switch them on or off for everyone, new players included - Player Statistics - Tickets bought, lotteries entered and won, money spent and earned, net profit
- Draw History - Each past draw is labelled "1 draw ago", "2 draws ago", ... with the winner, prize, tax, tickets and date, or "No winner" when nobody bought a ticket; the last 100 draws are kept by default
- Admin GUI -
/lottery adminopens a hub with settings, statistics, draw history, force draw, alerts for everyone, export and import - PlaceholderAPI - 11 placeholders; the round-wide ones also work without a player (scoreboards, holograms)
- Dual Storage - JSON (
data.json) or MySQL/MariaDB, with export and import to move between them - Safe Storage - Data is saved in the background; if it cannot be saved, ticket sales pause without taking money and resume once saving works again
Technologies
- Paper API 1.20.1+ - Minecraft server API (Spigot compatible)
- Utilizer - Configuration, messages, GUIs, tasks
- ACF - Command framework
- nexal-core - JSON and SQL persistence (MariaDB/MySQL), help menus
- cron4j - Draw scheduling
- Vault - Economy for buying tickets and paying winners
- PlaceholderAPI - Placeholder integration (optional)
Commands
Alias: /lotto
Player Commands
| Command | Description | Permission |
|---|---|---|
/lottery | Open the lottery GUI (the console gets the help menu) | nexallottery.use |
/lottery help [page] | Show the help menu | nexallottery.use |
/lottery info | Open the lottery GUI | nexallottery.use |
/lottery buy \<amount> | Buy lottery tickets | nexallottery.buy |
/lottery stats | View your lottery statistics | nexallottery.stats |
/lottery alerts | Toggle purchase alerts | nexallottery.alerts |
Admin Commands
| Command | Description | Permission |
|---|---|---|
/lottery admin | Open the admin GUI (the console gets the admin commands) | nexallottery.admin |
/lottery admin help [page] | List the admin commands | nexallottery.admin |
/lottery admin force | Draw a winner now | nexallottery.admin |
/lottery admin export | Export players, current tickets and draw history to export/ | nexallottery.admin |
/lottery admin import | Import the files in export/ into the current storage | nexallottery.admin |
/lottery admin alerts on \<player> | Enable alerts for a player | nexallottery.admin |
/lottery admin alerts off \<player> | Disable alerts for a player | nexallottery.admin |
/lottery admin alerts onall | Enable alerts for everyone, new players included (sets purchase-alerts-default) | nexallottery.admin |
/lottery admin alerts offall | Disable alerts for everyone, new players included (sets purchase-alerts-default) | nexallottery.admin |
/lottery admin alerts status \<player> | Show a player's alert setting | nexallottery.admin |
Admin GUI
/lottery admin opens a hub with:
- Configuration: ticket cost, purchase cooldown, ticket limit and its maximum, winner payout,
tax and its percentage, draw schedule (common presets), timezone, draw history limit and winner
fireworks. Changes are saved to
config.ymlright away. - Statistics: the current round, all-time totals and the top winners.
- Draw History: the last 45 draws, labelled and described like the lottery GUI's.
- Force Draw (shift click), Purchase Alerts for everyone (left click on, right click off), Export Data and Import Data (shift click).
Permissions
| Permission | Description | Default |
|---|---|---|
nexallottery.* | All lottery permissions | op |
nexallottery.use | Use /lottery, the help menu and the GUI | true |
nexallottery.buy | Buy lottery tickets | true |
nexallottery.stats | View lottery statistics | true |
nexallottery.alerts | Toggle purchase alerts | true |
nexallottery.admin | The admin GUI and all admin commands | op |
Placeholders
Requires PlaceholderAPI.
| Placeholder | Description |
|---|---|
%nexallottery_tickets% | The player's tickets in the current round |
%nexallottery_total_tickets% | All tickets in the current round |
%nexallottery_prize_pool% | The current prize pool, before tax |
%nexallottery_next_draw% | The next draw time (e.g. Jan 01, 18:00) |
%nexallottery_win_chance% | The player's win chance in percent |
%nexallottery_wins% | Lotteries the player won |
%nexallottery_participated% | Lotteries the player entered |
%nexallottery_tickets_bought% | Tickets the player bought in total |
%nexallottery_money_spent% | Money the player spent on tickets |
%nexallottery_money_earned% | Money the player won |
%nexallottery_net_profit% | Money earned minus money spent |
total_tickets, prize_pool and next_draw work without a player; the others then show 0.
Configuration
config.yml
# Timezone for the lottery: the cron schedule below runs in it, and draw times are shown in it
timezone: "UTC"
# Lottery draw schedule (cron expression)
# Format: minute hour day month day-of-week
cron-schedule: "0 * * * *"
# Cost per lottery ticket
ticket-cost: 100
# Ticket purchase limit (per player, per round)
ticket-limit:
enabled: false
max: 10
# Purchase cooldown (in seconds)
purchase-cooldown: 10
# Whether players see purchase alerts until they toggle them with /lottery alerts.
# /lottery admin alerts onall|offall and the admin GUI change this together with every stored player.
purchase-alerts-default: true
# Tax on lottery winnings
tax:
enabled: true
percentage: 10
# Disable Vault payout (if true, no money will be given to winners)
disable-vault-payout: false
# Fireworks launched around the winner when they are online at the draw, one every half second.
# They never damage the winner or anyone nearby.
winner-fireworks:
enabled: true
amount: 5 # 0 to 20
# Number of past draws kept in the draw history; older draws are removed. 0 keeps every draw.
draw-history-limit: 100
# Storage type: "json" or "sql"
storage:
type: json
sql:
host: localhost
port: 3306
database: minecraft
username: root
password: ""
# Commands to run when a player wins the lottery
# Placeholders: %player%, %amount%, %tax_amount%, %tax_percentage%
winner-commands:
# - "crates givekey %player% lottery_key 1"
config.yml reloads by itself when saved: the schedule restarts and the current round is kept.
Cron schedule examples
| Schedule | Cron Expression |
|---|---|
| Every hour | 0 * * * * |
| Every hour at :30 | 30 * * * * |
| Every 2 hours | 0 */2 * * * |
| Every 6 hours | 0 */6 * * * |
| Every day at noon | 0 12 * * * |
| Twice daily | 0 12,18 * * * |
messages.yml
All messages are fully customizable with MiniMessage colors and gradients, sounds and titles. The
colors are listed at the top of the file for find-and-replace. The Custom Amount button, chat prompt
and confirmation screen are under custom-amount. Keys missing from an older messages.yml fall
back to the plugin's defaults; the file itself is not changed. lottery-warnings holds one entry
per warning, keyed by the seconds before the draw.
Database Schema
With storage.type: json everything is kept in data.json, one collection per table below. With
sql, the plugin creates these tables:
lottery_users
| Column | Type | Key | Description |
|---|---|---|---|
id | VARCHAR(36) | PK | Player UUID |
tickets_bought | INT | Tickets bought in total | |
lotteries_won | INT | Lotteries won | |
lotteries_participated | INT | Lotteries entered | |
money_spent | DOUBLE | Money spent on tickets | |
money_earned | DOUBLE | Money won | |
purchase_alerts_enabled | BOOLEAN | Whether the player sees purchase alerts |
lottery_entries
| Column | Type | Key | Description |
|---|---|---|---|
player_id | VARCHAR(36) | PK | Player UUID |
ticket_count | INT | The player's tickets in the current round |
lottery_draws
| Column | Type | Key | Description |
|---|---|---|---|
id | VARCHAR(36) | PK | Draw ID |
timestamp | BIGINT | When the draw happened (epoch millis) | |
winner_id | VARCHAR(36) | Winner UUID | |
winner_name | VARCHAR(36) | Winner name at the time of the draw | |
prize_amount | DOUBLE | Money paid to the winner | |
tax_amount | DOUBLE | Tax taken from the pool | |
total_tickets | INT | Tickets in the round | |
winner_tickets | INT | The winner's tickets |
Key Legend: PK = Primary Key
If the storage cannot be loaded at startup (for example, the database is unreachable), the plugin disables itself. If saving fails while running, ticket sales pause and the plugin retries every 30 seconds; nothing is lost and sales resume once saving works again.
Moving between JSON and SQL
/lottery admin export- Set
storage.typeinconfig.yml - Restart the server
/lottery admin import
Dependencies
- Required for buying tickets: Vault and an economy plugin. Without them the plugin loads, but no ticket can be bought and winners cannot be paid.
- Optional: PlaceholderAPI
- Server: Paper or Spigot 1.20+
Installation
- Install Vault and an economy plugin
- Place the plugin JAR in your
/pluginsfolder - (Optional) Install PlaceholderAPI
- Start or restart the server
- Adjust the settings with
/lottery adminor inconfig.yml