-
Notifications
You must be signed in to change notification settings - Fork 5
Economy
ServerTools ships a full Vault economy provider, so you can drop EssentialsX Economy and let ServerTools handle balances, /pay, /eco, and every %vault_eco_*% placeholder.
Requires: Vault (hard requirement - economy won't load without it).
ServerTools registers itself as the Vault economy provider. During onLoad it hands a ServerToolsEconomy (a Vault AbstractEconomy) to Bukkit's ServicesManager at ServicePriority.Highest, so /pay, PlaceholderAPI's %vault_eco_*% placeholders, shops, and anything else that talks to Vault reads straight from us.
A few things that make it solid:
-
Whole cents, no floats. Every balance lives in SQLite as a whole-cent
long. We only convert to thedoubleVault demands at the API boundary. That kills the classic$0.1 + $0.2rounding bugs. SeeMoney.java. -
SQLite storage. Balances go in
plugins/ServerTools/data/economy.db, tablebalances (uuid, cents, name). Reads hit an in-memory cache; writes queue onto a single background thread so the main thread never blocks on disk IO. SeeEconomyStorage.java. - UUID-keyed. Everything's keyed by UUID, so offline players and name changes just work. The deprecated name-based Vault methods resolve a UUID first.
-
sqlite-jdbc is runtime-loaded by Paper, not shaded. It's declared in
plugin.ymlunderlibraries:(org.xerial:sqlite-jdbc:3.46.1.3), so Paper pulls it at startup.
Note: there's no bank support (hasBankSupport() returns false).
- Install Vault. Without it the economy skips loading entirely (it logs
Economy enabled but Vault is not installed - skipping.and moves on). Vault's the only hard requirement here. - Set
Economy.Enabled: true(it's on by default). - Tune
StartingBalance,CurrencySymbol, and the currency name. - Restart. You should see
Economy provider registered with Vault.in console.
Heads up on how Vault's required: the code doesn't use a @RequiresPlugin annotation. It's a plain runtime check in Main.setupEconomy():
if (Bukkit.getPluginManager().getPlugin("Vault") == null) {
Util.consoleMSG("&cEconomy enabled but Vault is not installed - skipping.");
return;
}In plugin.yml, Vault sits under softdepend, so ServerTools still boots without it - the economy module just stays off.
Permission nodes come from the config, not hardcoded, so you can remap them.
| Command | What it does | Permission |
|---|---|---|
/pay <player> <amount> |
Send money to another player | servertools.pay |
/eco <give|take|set> <player> <amount> |
Admin balance management | servertools.eco.admin |
/balance [player] |
Check your balance or someone else's | (none by default) |
/baltop |
Top balances leaderboard | (none by default) |
Notes:
-
/payis atomic and cent-accurate - it callsstorage.transfer()directly instead of round-tripping through Vault's double API. You can't pay yourself, and the payee has to have joined before. -
/ecoacceptsgive/add,take/remove, andset. Tab-completes the action and online player names. Aliased to/economy. -
/balancealiases:bal,money./baltopaliases:balancetop,moneytop. Both share one executor and branch on the label.
The real Economy: block from config.yml. The Messages list is trimmed here (there are ~19 keys) but the shape's the same - &-color codes plus %player% %amount% %balance% %input% placeholders (%rank% only works in BalTop.Line). Every message defaults to what's shown in code, so a missing key won't break anything.
Economy:
# ServerTools acts as the Vault economy provider.
# Balances are stored in economy.db (SQLite) as whole cents, so no float rounding bugs.
# Needs Vault installed. PlaceholderAPI %vault_eco_balance_formatted% reads from here.
Enabled: true
StartingBalance: 0.0
CurrencySymbol: '$'
CurrencyNameSingular: 'Dollar'
CurrencyNamePlural: 'Dollars'
Pay:
# /pay <player> <amount>
Enabled: true
Permission: servertools.pay
Admin:
# /eco <give|take|set> <player> <amount> (admin)
Enabled: true
Permission: servertools.eco.admin
Balance:
# /balance [player] and /baltop
Enabled: true
# All economy messages. &-color codes and these %placeholders% are supported:
# %player% %amount% %balance% %input% (%rank% only in BalTop.Line)
Messages:
PlayersOnly: '&c[!] Only players can pay.'
NotEnabled: '&c[!] The economy is not enabled.'
NeverJoined: '&c[!] &f%player% &chas never joined the server.'
InvalidAmount: '&c[!] &f%input% &cis not a valid amount.'
PaySent: '&aYou paid &f%player% %amount%&a. New balance: &f%balance%'
PayReceived: '&aYou received %amount% &afrom &f%player%&a. New balance: &f%balance%'
PayInsufficient: "&c[!] You can't afford that. Balance: &f%balance%"
PayOverflow: '&c[!] That would put them over the balance limit.'
EcoSet: "&aSet &f%player%&a's balance. Now: &f%balance%"
EcoOverflow: '&c[!] That exceeds the balance limit.'
# ...more keys, see config.yml
BalTop:
Limit: 10
Header: '&e&lTop Balances'
Line: '&e%rank%. &f%player% &7- &a%balance%'
Empty: '&7No accounts yet.'BalTop.Limit caps how many rows /baltop shows (default 10).
Once ServerTools is the Vault provider, PAPI's Vault expansion reads from it. So %vault_eco_balance_formatted% gives a player's balance formatted with your currency symbol. This is called out right in the config comment: # Needs Vault installed. PlaceholderAPI %vault_eco_balance_formatted% reads from here.
There's a hard ceiling so a single account can't overflow a long:
public static final long MAX_CENTS = 100_000_000_000_000L; // 1 trillion dollarsHow it's enforced:
-
Input parsing (
Money.parse) rejects anything overMAX_CENTS, plus negatives, exponent notation like1e3, and amounts finer than a cent like10.999. It does accept$, commas, and decimals ("1,000.99","$5"). -
Deposits,
set, and transfers check the cap before applying. If it'd blow pastMAX_CENTS, they returnOVERFLOWinstead of mutating. - That
OVERFLOWresult is what surfaces thePayOverflowmessage (/pay) andEcoOverflowmessage (/eco). So a payment or admin grant that'd push someone over the cap just gets refused - nothing wraps around or corrupts.
Withdrawals check funds and return INSUFFICIENT_FUNDS if you're short.
Getting started
Features
- Core Features
- Chat
- World and Mob Protections
- Moderation
- Events, Cooldowns and Tasks
- Utilities and Misc
- Hopper Optimization