Skip to main content

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​

  1. Scheduled Draws - Draws run on any cron expression (hourly, every 2 hours, daily at noon, ...)
  2. Timezone Support - The schedule and all displayed draw times follow the configured timezone, not the server clock
  3. Weighted Winner Selection - Each ticket is one chance; more tickets means a higher win chance
  4. Lottery GUI - /lottery shows the next draw, prize pool, tax, your tickets, win chance, lifetime stats and the last 5 draws, refreshed every second
  5. 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 (cancel aborts), then confirm the tickets and total cost on a confirmation screen
  6. Ticket Limits and Cooldowns - Optional per-player ticket cap per round and a cooldown between purchases
  7. Tax on Winnings - An optional percentage of the pool is taken before the winner is paid
  8. Winner Rewards - Vault payout (can be turned off) plus console commands with %player%, %amount%, %tax_amount% and %tax_percentage%
  9. Draw Warnings - Broadcasts with sounds 30, 10, 5 and 1 minutes before a draw; add or remove intervals in messages.yml
  10. Winner Announcements - A broadcast and title for everyone, a personal message for the winner, and fireworks around the winner that never hurt anyone
  11. 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
  12. Player Statistics - Tickets bought, lotteries entered and won, money spent and earned, net profit
  13. 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
  14. Admin GUI - /lottery admin opens a hub with settings, statistics, draw history, force draw, alerts for everyone, export and import
  15. PlaceholderAPI - 11 placeholders; the round-wide ones also work without a player (scoreboards, holograms)
  16. Dual Storage - JSON (data.json) or MySQL/MariaDB, with export and import to move between them
  17. 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​

CommandDescriptionPermission
/lotteryOpen the lottery GUI (the console gets the help menu)nexallottery.use
/lottery help [page]Show the help menunexallottery.use
/lottery infoOpen the lottery GUInexallottery.use
/lottery buy \<amount>Buy lottery ticketsnexallottery.buy
/lottery statsView your lottery statisticsnexallottery.stats
/lottery alertsToggle purchase alertsnexallottery.alerts

Admin Commands​

CommandDescriptionPermission
/lottery adminOpen the admin GUI (the console gets the admin commands)nexallottery.admin
/lottery admin help [page]List the admin commandsnexallottery.admin
/lottery admin forceDraw a winner nownexallottery.admin
/lottery admin exportExport players, current tickets and draw history to export/nexallottery.admin
/lottery admin importImport the files in export/ into the current storagenexallottery.admin
/lottery admin alerts on \<player>Enable alerts for a playernexallottery.admin
/lottery admin alerts off \<player>Disable alerts for a playernexallottery.admin
/lottery admin alerts onallEnable alerts for everyone, new players included (sets purchase-alerts-default)nexallottery.admin
/lottery admin alerts offallDisable alerts for everyone, new players included (sets purchase-alerts-default)nexallottery.admin
/lottery admin alerts status \<player>Show a player's alert settingnexallottery.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.yml right 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​

PermissionDescriptionDefault
nexallottery.*All lottery permissionsop
nexallottery.useUse /lottery, the help menu and the GUItrue
nexallottery.buyBuy lottery ticketstrue
nexallottery.statsView lottery statisticstrue
nexallottery.alertsToggle purchase alertstrue
nexallottery.adminThe admin GUI and all admin commandsop

Placeholders​

Requires PlaceholderAPI.

PlaceholderDescription
%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​

ScheduleCron Expression
Every hour0 * * * *
Every hour at :3030 * * * *
Every 2 hours0 */2 * * *
Every 6 hours0 */6 * * *
Every day at noon0 12 * * *
Twice daily0 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​

ColumnTypeKeyDescription
idVARCHAR(36)PKPlayer UUID
tickets_boughtINTTickets bought in total
lotteries_wonINTLotteries won
lotteries_participatedINTLotteries entered
money_spentDOUBLEMoney spent on tickets
money_earnedDOUBLEMoney won
purchase_alerts_enabledBOOLEANWhether the player sees purchase alerts

lottery_entries​

ColumnTypeKeyDescription
player_idVARCHAR(36)PKPlayer UUID
ticket_countINTThe player's tickets in the current round

lottery_draws​

ColumnTypeKeyDescription
idVARCHAR(36)PKDraw ID
timestampBIGINTWhen the draw happened (epoch millis)
winner_idVARCHAR(36)Winner UUID
winner_nameVARCHAR(36)Winner name at the time of the draw
prize_amountDOUBLEMoney paid to the winner
tax_amountDOUBLETax taken from the pool
total_ticketsINTTickets in the round
winner_ticketsINTThe 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​

  1. /lottery admin export
  2. Set storage.type in config.yml
  3. Restart the server
  4. /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​

  1. Install Vault and an economy plugin
  2. Place the plugin JAR in your /plugins folder
  3. (Optional) Install PlaceholderAPI
  4. Start or restart the server
  5. Adjust the settings with /lottery admin or in config.yml