Custom Storage Providers for EzEconomy
EzEconomy supports pluggable storage backends for all economy, bank, and currency operations. You can implement your own provider to use a custom database, cloud service, or any data source.
Overview
A storage provider is any class that implements the StorageProvider interface from the EzEconomy API. This interface defines all required methods for player balances, banks, currencies, and (optionally) transactions.
- Location:
com.skyblockexp.ezeconomy.api.storage.StorageProvider - Purpose: Abstracts all persistent data operations for the plugin
- Use Cases:
- Integrate with a custom SQL/NoSQL database
- Use a remote API or cloud service
- Add advanced caching or sharding
Implementation Steps
-
Implement the Interface
public class MyProvider implements StorageProvider { // Implement all required methods } -
Register Your Provider
Register your provider in your plugin’s
onLoadmethod, before EzEconomy finishes loading:import com.skyblockexp.ezeconomy.api.storage.StorageProvider; import com.skyblockexp.ezeconomy.EzEconomy; public void onLoad() { StorageProvider customProvider = new MyProvider(...); EzEconomy.registerStorageProvider(customProvider); } -
Required Methods
Your provider must implement all methods for:
- Player balances (get, set, deposit, withdraw)
- Bank operations (create, delete, balance, members)
- Currency management
- (Optional) Transaction history
See the Javadoc for
StorageProviderfor method signatures and expected behaviors. -
Legacy Compatibility
For single-currency servers, legacy overloads are provided. You must implement these for full compatibility with older plugins.
Guidelines
- Atomicity: Ensure all balance changes are atomic and thread-safe.
- Performance: Use async IO and caching where possible. Avoid blocking the main server thread.
- Validation: Validate all DTOs (data transfer objects) before writing to storage.
- Error Handling: Throw meaningful exceptions for impossible or failed operations.
- Migration: If replacing the default provider, migrate data before switching in production.
Example: Minimal Provider
public class ExampleProvider implements StorageProvider {
// Implement all required methods...
}
Notes
- Only one custom provider can be registered at a time.
- Register your provider before EzEconomy finishes loading.
- See the EzEconomy source for built-in provider examples (YML, SQLite, MySQL, MongoDB).
StorageProvider Interface Reference
This section documents all methods of the StorageProvider interface. Implement all required methods for a fully functional provider.
Initialization & Lifecycle
void init()
Initialize the storage provider. ThrowStorageInitExceptionon failure.void load()
Load data or establish connections. ThrowStorageLoadExceptionon failure.void save()
Persist any in-memory data. ThrowStorageSaveExceptionon failure.void shutdown()
Clean up and close resources.
Player Balances
double getBalance(UUID uuid, String currency)
Get a player’s balance for a currency.void setBalance(UUID uuid, String currency, double amount)
Set a player’s balance for a currency.boolean tryWithdraw(UUID uuid, String currency, double amount)
Attempt to withdraw from a player’s balance. Return false if insufficient funds.void deposit(UUID uuid, String currency, double amount)
Deposit to a player’s balance.Map<UUID, Double> getAllBalances(String currency)
Get all player balances for a currency.Set<String> cleanupOrphanedPlayers()
Remove balances for unknown players. Default: no-op.
Transactions
void logTransaction(Transaction transaction)
Log a transaction for a player and currency.List<Transaction> getTransactions(UUID uuid, String currency)
Get transaction history for a player and currency.
Transfers
TransferResult transfer(UUID fromUuid, UUID toUuid, String currency, double amount)
Transfer funds between players (default: debit/credit same amount).TransferResult transfer(UUID fromUuid, UUID toUuid, String currency, double debitAmount, double creditAmount)
Transfer custom debit/credit amounts between players.
Bank Operations
boolean createBank(String name, UUID owner)
Create a new bank.boolean deleteBank(String name)
Delete a bank.boolean bankExists(String name)
Check if a bank exists.double getBankBalance(String name, String currency)
Get a bank’s balance for a currency.void setBankBalance(String name, String currency, double amount)
Set a bank’s balance for a currency.boolean tryWithdrawBank(String name, String currency, double amount)
Attempt to withdraw from a bank.void depositBank(String name, String currency, double amount)
Deposit to a bank.Set<String> getBanks()
Get all bank names.boolean isBankOwner(String name, UUID uuid)
Check if a UUID is the owner of a bank.boolean isBankMember(String name, UUID uuid)
Check if a UUID is a member of a bank.boolean addBankMember(String name, UUID uuid)
Add a member to a bank.boolean removeBankMember(String name, UUID uuid)
Remove a member from a bank.Set<UUID> getBankMembers(String name)
Get all member UUIDs of a bank.
Connection & Status
boolean isConnected()
Return true if the provider is connected to its backend (default: false).
Legacy Overloads (Single-Currency)
All legacy methods use the default currency “dollar”. Implement for compatibility with older plugins:
double getBalance(UUID uuid)void setBalance(UUID uuid, double amount)boolean tryWithdraw(UUID uuid, double amount)void deposit(UUID uuid, double amount)Map<UUID, Double> getAllBalances()double getBankBalance(String name)void setBankBalance(String name, double amount)boolean tryWithdrawBank(String name, double amount)void depositBank(String name, double amount)
Thread Safety & Atomicity
- All balance and transfer operations must be atomic and thread-safe.
- Use locking or transactions as appropriate for your backend.
Exceptions
- Throw the appropriate exception (
StorageInitException,StorageLoadException,StorageSaveException) for lifecycle failures. - Throw meaningful runtime exceptions for impossible or failed operations.
See Also: