🔌 API Documentation
Essentials Plus provides a comprehensive Economy API that allows other plugins and mods to interact with the player balance system. This guide will help you integrate the API into your own projects.
📦 Installation
Maven
Add the Essentials Plus JAR as a system dependency to your pom.xml:
<dependencies>
<dependency>
<groupId>de.fof1092</groupId>
<artifactId>essentialsplus</artifactId>
<version>1.15.13</version>
<scope>system</scope>
<systemPath>${project.basedir}/libs/essentialsplus-1.15.13.jar</systemPath>
</dependency>
</dependencies>TIP
Place the Essentials Plus JAR file in a libs folder in your project root, or adjust the systemPath to point to your JAR location.
Gradle
Add the JAR as a file dependency to your build.gradle:
dependencies {
compileOnly files('libs/essentialsplus-1.15.13.jar')
}TIP
Place the Essentials Plus JAR file in a libs folder in your project root, or adjust the path accordingly.
Important
Essentials Plus is not open source and not available via public repositories. You must:
- Obtain the JAR file from the official source
- Include it as a soft dependency in your project
- Use
systemscope (Maven) orcompileOnly(Gradle) to ensure it's not bundled - Ensure Essentials Plus is installed on the server separately
💰 Economy API
The Economy API provides asynchronous access to player balances with full event support and transaction logging.
Features
- ✅ Fully Asynchronous - All operations return
CompletableFuture - ✅ Event System - Cancellable
BalanceChangeEventbefore every transaction - ✅ Thread-Safe - Dedicated thread pool for economy operations
- ✅ Transaction Logging - Detailed logging for auditing and debugging
- ✅ Configurable Limits - Min/max balance validation
- ✅ UUID & Name Support - Query by player UUID or username
Quick Start
import de.fof1092.essentialsplus.economy.EconomyAPI;
import java.util.UUID;
public class MyPlugin {
public void rewardPlayer(UUID playerUUID, double amount) {
// Add money to player's balance
EconomyAPI.increaseBalance(playerUUID, amount, "Quest Reward")
.thenAccept(newBalance -> {
System.out.println("New balance: " + EconomyAPI.formatCurrency(newBalance));
})
.exceptionally(ex -> {
System.err.println("Failed to add balance: " + ex.getMessage());
return null;
});
}
}📚 API Reference
Balance Queries
Get Balance
// By UUID
CompletableFuture<Double> getBalance(UUID playerUUID)
// By username
CompletableFuture<Double> getBalance(String playerName)Example:
EconomyAPI.getBalance(playerUUID)
.thenAccept(balance -> {
System.out.println("Player has: " + balance);
});Check Sufficient Balance
// By UUID
CompletableFuture<Boolean> hasBalance(UUID playerUUID, double amount)
// By username
CompletableFuture<Boolean> hasBalance(String playerName, double amount)Example:
EconomyAPI.hasBalance(playerUUID, 1000.0)
.thenAccept(hasEnough -> {
if (hasEnough) {
System.out.println("Player can afford this item!");
}
});Balance Modifications
Set Balance
Sets the player's balance to an exact amount.
// By UUID
CompletableFuture<Double> setBalance(UUID playerUUID, double newBalance, String reason)
// By username
CompletableFuture<Double> setBalance(String playerName, double newBalance, String reason)Example:
EconomyAPI.setBalance(playerUUID, 5000.0, "Admin reset")
.thenAccept(newBalance -> {
System.out.println("Balance set to: " + newBalance);
})
.exceptionally(ex -> {
System.err.println("Error: " + ex.getMessage());
return null;
});Increase Balance
Adds a positive amount to the player's balance.
// By UUID
CompletableFuture<Double> increaseBalance(UUID playerUUID, double amount, String reason)
// By username
CompletableFuture<Double> increaseBalance(String playerName, double amount, String reason)Example:
EconomyAPI.increaseBalance(playerUUID, 250.0, "Daily reward")
.thenAccept(newBalance -> {
player.sendMessage("You received 250$! New balance: " + newBalance);
});TIP
The amount must be positive. Use changeBalance() for negative amounts.
Decrease Balance
Subtracts a positive amount from the player's balance.
// By UUID
CompletableFuture<Double> decreaseBalance(UUID playerUUID, double amount, String reason)
// By username
CompletableFuture<Double> decreaseBalance(String playerName, double amount, String reason)Example:
EconomyAPI.decreaseBalance(playerUUID, 100.0, "Item purchase")
.thenAccept(newBalance -> {
player.sendMessage("Purchase successful! Remaining: " + newBalance);
})
.exceptionally(ex -> {
player.sendMessage("Purchase failed: " + ex.getMessage());
return null;
});Change Balance
Changes the balance by a positive or negative amount.
// By UUID
CompletableFuture<Double> changeBalance(UUID playerUUID, double changeAmount, String reason)
// By username
CompletableFuture<Double> changeBalance(String playerName, double changeAmount, String reason)Example:
// Add money
EconomyAPI.changeBalance(playerUUID, 500.0, "Bonus");
// Remove money
EconomyAPI.changeBalance(playerUUID, -500.0, "Tax");Transfers
Transfer Balance
Transfer money from one player to another.
// By UUID
CompletableFuture<Void> transferBalance(UUID fromUUID, UUID toUUID, double amount, String reason)
// By username
CompletableFuture<Void> transferBalance(String fromName, String toName, double amount, String reason)Example:
EconomyAPI.transferBalance(senderUUID, receiverUUID, 100.0, "Payment")
.thenRun(() -> {
sender.sendMessage("Transfer successful!");
receiver.sendMessage("You received 100$!");
})
.exceptionally(ex -> {
sender.sendMessage("Transfer failed: " + ex.getMessage());
return null;
});Leaderboard
Get Top Balances
Retrieve a sorted list of the richest players.
CompletableFuture<LinkedHashMap<UUID, Double>> getTopBalances(int minRank, int maxRank)Example:
// Get top 10 players
EconomyAPI.getTopBalances(1, 10)
.thenAccept(topBalances -> {
int rank = 1;
for (Map.Entry<UUID, Double> entry : topBalances.entrySet()) {
System.out.println(rank + ". " + entry.getKey() + ": " + entry.getValue());
rank++;
}
});Utility Methods
Format Currency
String formatCurrency(double amount)Example:
String formatted = EconomyAPI.formatCurrency(1234.56);
// Output: "1234.56$"Get Currency Information
String getCurrencySymbol() // Returns: "$"
String getCurrencyNameSingular() // Returns: "Dollar"
String getCurrencyNamePlural() // Returns: "Dollars"
boolean isEnabled() // Returns: true if economy is enabled🎯 Practical Examples
Shop System
public class ShopManager {
public void buyItem(Player player, String itemName, double price) {
UUID playerUUID = player.getUuid();
// Check if player has enough money
EconomyAPI.hasBalance(playerUUID, price).thenAccept(hasEnough -> {
if (!hasEnough) {
player.sendMessage("You don't have enough money!");
return;
}
// Deduct money and give item
EconomyAPI.decreaseBalance(playerUUID, price, "Bought " + itemName)
.thenAccept(newBalance -> {
giveItemToPlayer(player, itemName);
player.sendMessage("Purchased " + itemName + " for " +
EconomyAPI.formatCurrency(price));
player.sendMessage("New balance: " +
EconomyAPI.formatCurrency(newBalance));
})
.exceptionally(ex -> {
player.sendMessage("Purchase failed: " + ex.getMessage());
return null;
});
});
}
public void sellItem(Player player, String itemName, double price) {
UUID playerUUID = player.getUuid();
if (!hasItemInInventory(player, itemName)) {
player.sendMessage("You don't have this item!");
return;
}
removeItemFromPlayer(player, itemName);
EconomyAPI.increaseBalance(playerUUID, price, "Sold " + itemName)
.thenAccept(newBalance -> {
player.sendMessage("Sold " + itemName + " for " +
EconomyAPI.formatCurrency(price));
player.sendMessage("New balance: " +
EconomyAPI.formatCurrency(newBalance));
});
}
private void giveItemToPlayer(Player player, String itemName) {
// Implementation
}
private void removeItemFromPlayer(Player player, String itemName) {
// Implementation
}
private boolean hasItemInInventory(Player player, String itemName) {
// Implementation
return false;
}
}Quest System with Rewards
public class QuestManager {
public void completeQuest(Player player, Quest quest) {
UUID playerUUID = player.getUuid();
double reward = quest.getReward();
EconomyAPI.increaseBalance(playerUUID, reward, "Quest: " + quest.getName())
.thenAccept(newBalance -> {
player.sendMessage("Quest completed!");
player.sendMessage("Reward: " + EconomyAPI.formatCurrency(reward));
player.sendMessage("Total balance: " +
EconomyAPI.formatCurrency(newBalance));
// Unlock next quest, save progress, etc.
unlockNextQuest(player, quest);
})
.exceptionally(ex -> {
// This should rarely happen, but handle it gracefully
player.sendMessage("Error processing quest reward. Please contact an admin.");
System.err.println("Quest reward error: " + ex.getMessage());
return null;
});
}
private void unlockNextQuest(Player player, Quest quest) {
// Implementation
}
}Player-to-Player Trading
public class TradeManager {
public void executeTrade(Player player1, Player player2,
double amount1, double amount2) {
UUID uuid1 = player1.getUuid();
UUID uuid2 = player2.getUuid();
// Check both players have enough money
CompletableFuture<Boolean> check1 = EconomyAPI.hasBalance(uuid1, amount1);
CompletableFuture<Boolean> check2 = EconomyAPI.hasBalance(uuid2, amount2);
CompletableFuture.allOf(check1, check2).thenRun(() -> {
if (!check1.join() || !check2.join()) {
player1.sendMessage("Trade cancelled: Insufficient funds");
player2.sendMessage("Trade cancelled: Insufficient funds");
return;
}
// Execute both transfers
CompletableFuture<Void> transfer1 =
EconomyAPI.transferBalance(uuid1, uuid2, amount1, "Trade");
CompletableFuture<Void> transfer2 =
EconomyAPI.transferBalance(uuid2, uuid1, amount2, "Trade");
CompletableFuture.allOf(transfer1, transfer2).thenRun(() -> {
player1.sendMessage("Trade completed!");
player2.sendMessage("Trade completed!");
}).exceptionally(ex -> {
player1.sendMessage("Trade failed: " + ex.getMessage());
player2.sendMessage("Trade failed: " + ex.getMessage());
return null;
});
});
}
}Leaderboard Display
public class LeaderboardCommand {
public void showTopPlayers(Player player) {
EconomyAPI.getTopBalances(1, 10).thenAccept(topBalances -> {
player.sendMessage("=== Top 10 Richest Players ===");
int rank = 1;
for (Map.Entry<UUID, Double> entry : topBalances.entrySet()) {
String playerName = getPlayerName(entry.getKey());
String balance = EconomyAPI.formatCurrency(entry.getValue());
player.sendMessage(rank + ". " + playerName + " - " + balance);
rank++;
}
});
}
private String getPlayerName(UUID uuid) {
// Get player name from UserManager or cache
return "Player";
}
}🎪 Event System
The Economy API fires cancellable events before every balance change, allowing you to implement custom logic like taxes, limits, or logging.
Balance Change Event
import de.fof1092.essentialsplus.economy.BalanceChangeEvent;
import com.hypixel.hytale.server.core.HytaleServer;
public class EconomyEventListener {
public void register() {
HytaleServer.get().getEventBus().registerGlobal(
BalanceChangeEvent.class,
this::onBalanceChange
);
}
private void onBalanceChange(BalanceChangeEvent event) {
// Event information
UUID playerUUID = event.getPlayerUUID();
String playerName = event.getPlayerName();
double oldBalance = event.getOldBalance();
double newBalance = event.getNewBalance();
double change = event.getChangeAmount();
BalanceChangeEvent.ChangeType type = event.getChangeType();
String reason = event.getReason();
// Example: Log all transactions
System.out.println(playerName + " balance changed from " +
oldBalance + " to " + newBalance + " (" + reason + ")");
// Example: Cancel if player would exceed limit
if (newBalance > 1000000.0) {
event.setCancelled(true);
// Notify player
}
}
}Change Types
The ChangeType enum indicates the type of balance operation:
SET- Balance was set to a specific valueINCREASE- Balance was increasedDECREASE- Balance was decreasedTRANSFER_SEND- Balance was transferred to another player (sender)TRANSFER_RECEIVE- Balance was transferred from another player (receiver)CHANGE- Balance was changed by an unknown amount
Tax System Example
public class TaxSystem {
private static final double TAX_RATE = 0.10; // 10%
private static final double TAX_THRESHOLD = 1000.0;
public void register() {
HytaleServer.get().getEventBus().registerGlobal(
BalanceChangeEvent.class,
this::applyTax
);
}
private void applyTax(BalanceChangeEvent event) {
// Only tax on income (increases)
if (event.getChangeType() != BalanceChangeEvent.ChangeType.INCREASE) {
return;
}
// Only tax large amounts
if (event.getChangeAmount() < TAX_THRESHOLD) {
return;
}
// Calculate tax
double tax = event.getChangeAmount() * TAX_RATE;
double netIncome = event.getChangeAmount() - tax;
// Cancel original transaction
event.setCancelled(true);
// Apply net income instead
EconomyAPI.increaseBalance(
event.getPlayerUUID(),
netIncome,
event.getReason() + " (after " + (int) (TAX_RATE * 100) + "% tax)"
).thenAccept(newBalance -> {
// Optional: Notify player about tax
Player player = getPlayer(event.getPlayerUUID());
if (player != null) {
player.sendMessage("Tax deducted: " +
EconomyAPI.formatCurrency(tax));
}
});
}
private Player getPlayer(UUID uuid) {
// Get player from server
return null;
}
}Transaction Logger Example
public class TransactionLogger {
private final List<Transaction> transactionHistory = new ArrayList<>();
public void register() {
HytaleServer.get().getEventBus().registerGlobal(
BalanceChangeEvent.class,
this::logTransaction
);
}
private void logTransaction(BalanceChangeEvent event) {
// Don't log cancelled transactions
if (event.isCancelled()) {
return;
}
Transaction transaction = new Transaction(
event.getPlayerUUID(),
event.getPlayerName(),
event.getOldBalance(),
event.getNewBalance(),
event.getChangeType(),
event.getReason(),
System.currentTimeMillis()
);
transactionHistory.add(transaction);
// Optional: Save to database
saveToDatabase(transaction);
}
public List<Transaction> getPlayerTransactions(UUID playerUUID) {
return transactionHistory.stream()
.filter(t -> t.playerUUID.equals(playerUUID))
.collect(Collectors.toList());
}
private void saveToDatabase(Transaction transaction) {
// Implementation
}
private static class Transaction {
final UUID playerUUID;
final String playerName;
final double oldBalance;
final double newBalance;
final BalanceChangeEvent.ChangeType type;
final String reason;
final long timestamp;
Transaction(UUID playerUUID, String playerName, double oldBalance,
double newBalance, BalanceChangeEvent.ChangeType type,
String reason, long timestamp) {
this.playerUUID = playerUUID;
this.playerName = playerName;
this.oldBalance = oldBalance;
this.newBalance = newBalance;
this.type = type;
this.reason = reason;
this.timestamp = timestamp;
}
}
}⚙️ Configuration
The Economy system can be configured in the config.json file:
{
"economy": {
"enabled": true,
"startBalance": 100.0,
"minBalance": 0.0,
"maxBalance": 100000000.0,
"transactionLogging": true,
"currencySymbol": "$",
"currencyNameSingular": "Dollar",
"currencyNamePlural": "Dollars"
}
}Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
enabled | boolean | true | Enable/disable the economy system |
startBalance | double | 100.0 | Initial balance for new players |
minBalance | double | 0.0 | Minimum allowed balance |
maxBalance | double | 100000000.0 | Maximum allowed balance |
transactionLogging | boolean | true | Log all transactions to console |
currencySymbol | string | "$" | Currency symbol |
currencyNameSingular | string | "Dollar" | Singular currency name |
currencyNamePlural | string | "Dollars" | Plural currency name |
🔒 Best Practices
1. Always Handle Exceptions
// ❌ Bad
EconomyAPI.increaseBalance(playerUUID, 100.0, "Reward");
// ✅ Good
EconomyAPI.increaseBalance(playerUUID, 100.0, "Reward")
.exceptionally(ex -> {
System.err.println("Failed to reward player: " + ex.getMessage());
return null;
});2. Use Meaningful Reasons
// ❌ Bad
EconomyAPI.decreaseBalance(playerUUID, 50.0, null);
// ✅ Good
EconomyAPI.decreaseBalance(playerUUID, 50.0, "Shop: Bought Diamond Sword");3. Check Balance Before Transactions
// ✅ Good practice
EconomyAPI.hasBalance(playerUUID, cost)
.thenAccept(hasEnough -> {
if (hasEnough) {
EconomyAPI.decreaseBalance(playerUUID, cost, "Purchase")
.thenAccept(newBalance -> {
// Give item
});
} else {
player.sendMessage("Insufficient funds!");
}
});4. Use UUID Instead of Username
// ❌ Slower, name might change
EconomyAPI.getBalance("PlayerName");
// ✅ Faster, always correct
EconomyAPI.getBalance(playerUUID);5. Chain Operations Properly
// ✅ Good - Sequential operations
EconomyAPI.getBalance(playerUUID)
.thenCompose(balance -> {
if (balance >= 100.0) {
return EconomyAPI.decreaseBalance(playerUUID, 100.0, "Upgrade");
} else {
return CompletableFuture.failedFuture(
new Exception("Not enough money")
);
}
})
.thenAccept(newBalance -> {
player.sendMessage("Upgrade purchased!");
})
.exceptionally(ex -> {
player.sendMessage("Purchase failed: " + ex.getMessage());
return null;
});❗ Error Handling
Exception Hierarchy
All economy exceptions inherit from EconomyException:
EconomyException (base)
├── PlayerNotFoundException
├── InsufficientBalanceException
├── BalanceLimitExceededException
└── BalanceChangeCancelledExceptionSpecific Exceptions
PlayerNotFoundException
Thrown when a player is not found in the system.
Properties:
getPlayerUUID()- UUID of the missing player (can be null)getPlayerName()- Name of the missing player (can be null)
Example:
EconomyAPI.getBalance(playerUUID)
.exceptionally(ex -> {
Throwable cause = ex.getCause();
if (cause instanceof PlayerNotFoundException) {
PlayerNotFoundException pnf = (PlayerNotFoundException) cause;
System.err.println("Player not found: " + pnf.getPlayerUUID());
// Maybe create the player account?
}
return 0.0;
});InsufficientBalanceException
Thrown when a player doesn't have enough balance for an operation.
Properties:
getPlayerUUID()- UUID of the playergetCurrentBalance()- Current balancegetRequiredBalance()- Required balancegetDeficit()- How much money is missing
Example:
EconomyAPI.decreaseBalance(playerUUID, 1000.0, "Purchase")
.exceptionally(ex -> {
Throwable cause = ex.getCause();
if (cause instanceof InsufficientBalanceException) {
InsufficientBalanceException ibe = (InsufficientBalanceException) cause;
player.sendMessage("You need " +
EconomyAPI.formatCurrency(ibe.getDeficit()) + " more!");
player.sendMessage("Current: " +
EconomyAPI.formatCurrency(ibe.getCurrentBalance()));
}
return null;
});BalanceLimitExceededException
Thrown when a balance operation would exceed configured limits (min/max).
Properties:
getPlayerUUID()- UUID of the playergetAttemptedBalance()- The balance that was attemptedgetLimitValue()- The limit that was exceededgetLimitType()-MINIMUMorMAXIMUMisMinimumExceeded()- Returns true if minimum was exceededisMaximumExceeded()- Returns true if maximum was exceeded
Example:
EconomyAPI.setBalance(playerUUID, 999999999.0, "Test")
.exceptionally(ex -> {
Throwable cause = ex.getCause();
if (cause instanceof BalanceLimitExceededException) {
BalanceLimitExceededException ble = (BalanceLimitExceededException) cause;
if (ble.isMaximumExceeded()) {
player.sendMessage("Balance cannot exceed " +
EconomyAPI.formatCurrency(ble.getLimitValue()));
} else {
player.sendMessage("Balance cannot go below " +
EconomyAPI.formatCurrency(ble.getLimitValue()));
}
}
return null;
});BalanceChangeCancelledException
Thrown when a balance change operation is cancelled by an event listener.
Properties:
getPlayerUUID()- UUID of the playergetOldBalance()- Balance before the attempted changegetNewBalance()- Balance that was attempted
Example:
EconomyAPI.increaseBalance(playerUUID, 10000.0, "Lottery Win")
.exceptionally(ex -> {
Throwable cause = ex.getCause();
if (cause instanceof BalanceChangeCancelledException) {
BalanceChangeCancelledException bcc = (BalanceChangeCancelledException) cause;
player.sendMessage("Transaction was blocked by server anti-cheat!");
System.err.println("Suspicious transaction detected for " +
bcc.getPlayerUUID());
}
return null;
});Advanced Exception Handling
Handle Multiple Exception Types
EconomyAPI.decreaseBalance(playerUUID, cost, "Item Purchase")
.thenAccept(newBalance -> {
giveItemToPlayer(player);
player.sendMessage("Purchase successful! New balance: " +
EconomyAPI.formatCurrency(newBalance));
})
.exceptionally(ex -> {
Throwable cause = ex.getCause();
if (cause instanceof PlayerNotFoundException) {
player.sendMessage("Account not found! Please rejoin the server.");
} else if (cause instanceof InsufficientBalanceException) {
InsufficientBalanceException ibe = (InsufficientBalanceException) cause;
player.sendMessage("You need " +
EconomyAPI.formatCurrency(ibe.getDeficit()) + " more!");
} else if (cause instanceof BalanceLimitExceededException) {
player.sendMessage("This transaction would exceed balance limits!");
} else if (cause instanceof BalanceChangeCancelledException) {
player.sendMessage("Transaction was blocked by the server!");
} else {
player.sendMessage("An error occurred: " + cause.getMessage());
cause.printStackTrace();
}
return null;
});Type-Safe Exception Handling
public class ShopManager {
public void buyItem(Player player, String itemName, double price) {
UUID playerUUID = player.getUuid();
EconomyAPI.decreaseBalance(playerUUID, price, "Shop: " + itemName)
.thenAccept(newBalance -> {
giveItemToPlayer(player, itemName);
player.sendMessage("Purchased " + itemName);
})
.exceptionally(ex -> {
handlePurchaseError(player, ex.getCause(), price);
return null;
});
}
private void handlePurchaseError(Player player, Throwable cause, double price) {
if (cause instanceof InsufficientBalanceException ibe) {
player.sendMessage("Not enough money!");
player.sendMessage("You have: " +
EconomyAPI.formatCurrency(ibe.getCurrentBalance()));
player.sendMessage("You need: " +
EconomyAPI.formatCurrency(price));
player.sendMessage("Missing: " +
EconomyAPI.formatCurrency(ibe.getDeficit()));
} else if (cause instanceof PlayerNotFoundException) {
player.sendMessage("Your account was not found!");
player.sendMessage("Please contact an administrator.");
} else {
player.sendMessage("Purchase failed: " + cause.getMessage());
}
}
private void giveItemToPlayer(Player player, String itemName) {
// Implementation
}
}Exception-Based Flow Control
public class LotterySystem {
public void buyTicket(Player player, double ticketCost) {
UUID playerUUID = player.getUuid();
// Try to purchase ticket
EconomyAPI.decreaseBalance(playerUUID, ticketCost, "Lottery Ticket")
.thenCompose(newBalance -> {
// Success! Generate ticket
String ticketNumber = generateTicketNumber();
player.sendMessage("Ticket purchased: " + ticketNumber);
player.sendMessage("Remaining balance: " +
EconomyAPI.formatCurrency(newBalance));
return CompletableFuture.completedFuture(ticketNumber);
})
.exceptionally(ex -> {
Throwable cause = ex.getCause();
if (cause instanceof InsufficientBalanceException ibe) {
// Offer alternative: cheaper ticket
double cheaperTicket = ticketCost / 2;
if (ibe.getCurrentBalance() >= cheaperTicket) {
player.sendMessage("You can't afford a full ticket (" +
EconomyAPI.formatCurrency(ticketCost) + ")");
player.sendMessage("But you can buy a half-ticket for " +
EconomyAPI.formatCurrency(cheaperTicket));
} else {
player.sendMessage("Insufficient funds! You need " +
EconomyAPI.formatCurrency(ibe.getDeficit()) + " more.");
}
} else {
player.sendMessage("Could not purchase ticket: " +
cause.getMessage());
}
return null;
});
}
private String generateTicketNumber() {
return "TICKET-" + System.currentTimeMillis();
}
}Common Exceptions
IllegalArgumentException
Thrown when:
- Amount is negative for
increaseBalanceordecreaseBalance - Invalid rank range for
getTopBalances
Example:
try {
EconomyAPI.increaseBalance(playerUUID, -100.0, "Test"); // Throws!
} catch (IllegalArgumentException e) {
System.err.println("Invalid amount: " + e.getMessage());
}Handling API Not Initialized
try {
EconomyAPI.getBalance(playerUUID)
.thenAccept(balance -> {
// ...
});
} catch (IllegalStateException e) {
System.err.println("Economy API not initialized! Is Essentials Plus installed?");
}🐛 Troubleshooting
Economy API not available
Problem: IllegalStateException: EconomyAPI has not been initialized yet!
Solution:
- Ensure Essentials Plus is installed on the server
- Make sure your plugin loads after Essentials Plus
- Check if economy is enabled in
config.json
Transactions not working
Problem: Balance changes don't persist or throw exceptions
Solution:
- Check server logs for error messages
- Verify
economy.enabledistruein config - Ensure player exists in the system (joined at least once)
- Check min/max balance limits
Events not firing
Problem: Your event listener is not being called
Solution:
// Make sure you register the listener
HytaleServer.get()
.getEventBus()
.registerGlobal(
BalanceChangeEvent.class,
this::onBalanceChange
);Performance issues
Problem: Economy operations are slow
Solution:
- Use UUID instead of player name for lookups
- Batch operations when possible
- Avoid synchronous
.join()calls on the main thread - Check if transaction logging is causing issues (can be disabled)
📝 Version Compatibility
| Essentials Plus Version | API Version | Hytale Version |
|---|---|---|
| 1.11.0+ | 1.0 | Latest |
💬 Support
Need help? Found a bug? Have suggestions?
- Discord: Join our Discord Server
- Documentation: Full Documentation
📄 License
Essentials Plus and its API are provided as-is. Please refer to the main plugin license for usage terms.