2016-06-14 05:06:58 +02:00
|
|
|
package org.appledash.saneeconomy.economy;
|
|
|
|
|
2016-09-18 10:37:44 +02:00
|
|
|
import org.appledash.saneeconomy.ISaneEconomy;
|
2019-10-31 13:05:22 +01:00
|
|
|
import org.appledash.saneeconomy.SaneEconomy;
|
2016-06-14 05:06:58 +02:00
|
|
|
import org.appledash.saneeconomy.economy.backend.EconomyStorageBackend;
|
2016-07-20 03:20:54 +02:00
|
|
|
import org.appledash.saneeconomy.economy.economable.Economable;
|
2020-01-24 08:06:54 +01:00
|
|
|
import org.appledash.saneeconomy.economy.economable.EconomableConsole;
|
2016-09-21 10:16:36 +02:00
|
|
|
import org.appledash.saneeconomy.economy.transaction.Transaction;
|
|
|
|
import org.appledash.saneeconomy.economy.transaction.TransactionResult;
|
2017-07-05 15:57:26 +02:00
|
|
|
import org.appledash.saneeconomy.event.SaneEconomyTransactionEvent;
|
2017-07-15 22:36:32 +02:00
|
|
|
import org.appledash.saneeconomy.utils.MapUtil;
|
2016-06-15 01:47:14 +02:00
|
|
|
import org.appledash.saneeconomy.utils.NumberUtils;
|
2016-07-12 02:22:07 +02:00
|
|
|
import org.bukkit.Bukkit;
|
2016-06-14 05:06:58 +02:00
|
|
|
|
2019-11-04 10:43:33 +01:00
|
|
|
import java.math.BigDecimal;
|
2016-07-12 02:22:07 +02:00
|
|
|
import java.util.LinkedHashMap;
|
|
|
|
import java.util.Map;
|
2019-11-04 10:49:41 +01:00
|
|
|
import java.util.concurrent.*;
|
2016-07-12 02:22:07 +02:00
|
|
|
|
2016-06-14 05:06:58 +02:00
|
|
|
/**
|
|
|
|
* Created by AppleDash on 6/13/2016.
|
|
|
|
* Blackjack is still best pony.
|
|
|
|
*
|
|
|
|
* Represents our EconomyManager, which manages players' balances.
|
|
|
|
*/
|
|
|
|
public class EconomyManager {
|
2016-09-18 11:11:22 +02:00
|
|
|
private final ISaneEconomy saneEconomy;
|
2016-06-14 10:59:16 +02:00
|
|
|
private final Currency currency;
|
|
|
|
private final EconomyStorageBackend backend;
|
2017-02-14 17:28:04 +01:00
|
|
|
private final String serverAccountName;
|
2016-06-14 05:06:58 +02:00
|
|
|
|
2017-02-14 17:28:04 +01:00
|
|
|
public EconomyManager(ISaneEconomy saneEconomy, Currency currency, EconomyStorageBackend backend, String serverAccountName) {
|
2016-09-18 10:37:44 +02:00
|
|
|
this.saneEconomy = saneEconomy;
|
2016-06-14 05:06:58 +02:00
|
|
|
this.currency = currency;
|
|
|
|
this.backend = backend;
|
2017-02-14 17:28:04 +01:00
|
|
|
this.serverAccountName = serverAccountName;
|
2016-06-14 05:06:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the Currency we're using/
|
|
|
|
* @return Currency
|
|
|
|
*/
|
|
|
|
public Currency getCurrency() {
|
2019-11-04 18:25:17 +01:00
|
|
|
return this.currency;
|
2016-06-14 05:06:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the balance of a player, formatted according to our Currency's format.
|
|
|
|
* @param player Player
|
|
|
|
* @return Formatted balance
|
|
|
|
*/
|
2016-07-20 03:20:54 +02:00
|
|
|
public String getFormattedBalance(Economable player) {
|
2019-11-04 18:25:17 +01:00
|
|
|
return this.currency.formatAmount(this.backend.getBalance(player));
|
2016-06-14 05:06:58 +02:00
|
|
|
}
|
|
|
|
|
2016-06-14 05:29:26 +02:00
|
|
|
/**
|
|
|
|
* Check whether a player has used the economy system before.
|
|
|
|
* @param player Player to check
|
|
|
|
* @return True if they have used the economy system before, false otherwise
|
|
|
|
*/
|
2016-07-20 03:20:54 +02:00
|
|
|
public boolean accountExists(Economable player) {
|
2019-11-04 18:25:17 +01:00
|
|
|
return this.backend.accountExists(player);
|
2016-06-14 05:29:26 +02:00
|
|
|
}
|
|
|
|
|
2016-06-14 05:06:58 +02:00
|
|
|
/**
|
|
|
|
* Get a player's balance.
|
|
|
|
* @param targetPlayer Player to get balance of
|
|
|
|
* @return Player's balance
|
|
|
|
*/
|
2019-11-04 10:43:33 +01:00
|
|
|
public BigDecimal getBalance(Economable targetPlayer) {
|
2020-01-24 08:06:54 +01:00
|
|
|
if (EconomableConsole.isConsole(targetPlayer)) {
|
2019-11-04 10:43:33 +01:00
|
|
|
return new BigDecimal(Double.MAX_VALUE);
|
2016-09-21 10:16:36 +02:00
|
|
|
}
|
|
|
|
|
2019-11-04 18:25:17 +01:00
|
|
|
return this.backend.getBalance(targetPlayer);
|
2016-06-14 05:06:58 +02:00
|
|
|
}
|
|
|
|
|
2016-06-15 01:19:00 +02:00
|
|
|
|
2016-06-14 05:06:58 +02:00
|
|
|
/**
|
|
|
|
* Check if a player has a certain amount of money.
|
|
|
|
* @param targetPlayer Player to check balance of
|
|
|
|
* @param requiredBalance How much money we're checking for
|
|
|
|
* @return True if they have requiredBalance or more, false otherwise
|
|
|
|
*/
|
2019-11-04 10:43:33 +01:00
|
|
|
public boolean hasBalance(Economable targetPlayer, BigDecimal requiredBalance) {
|
2020-01-24 08:06:54 +01:00
|
|
|
return (EconomableConsole.isConsole(targetPlayer)) || (this.getBalance(targetPlayer).compareTo(requiredBalance) >= 0);
|
2016-09-21 10:16:36 +02:00
|
|
|
|
2016-06-14 05:06:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add to a player's balance.
|
2018-05-25 08:27:02 +02:00
|
|
|
* This does not filter the amount.
|
2016-06-14 05:06:58 +02:00
|
|
|
* @param targetPlayer Player to add to
|
|
|
|
* @param amount Amount to add
|
|
|
|
* @throws IllegalArgumentException If amount is negative
|
|
|
|
*/
|
2019-11-04 10:43:33 +01:00
|
|
|
private void addBalance(Economable targetPlayer, BigDecimal amount) {
|
2019-11-04 18:25:17 +01:00
|
|
|
this.setBalance(targetPlayer, this.backend.getBalance(targetPlayer).add(amount));
|
2016-06-14 05:06:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Subtract from a player's balance.
|
|
|
|
* If the subtraction would result in a negative balance, the balance is instead set to 0.
|
2018-05-25 08:27:02 +02:00
|
|
|
* This does not filter the amount.
|
|
|
|
*
|
2016-06-14 05:06:58 +02:00
|
|
|
* @param targetPlayer Player to subtract from
|
|
|
|
* @param amount Amount to subtract
|
|
|
|
* @throws IllegalArgumentException If amount is negative
|
|
|
|
*/
|
2019-11-04 10:43:33 +01:00
|
|
|
private void subtractBalance(Economable targetPlayer, BigDecimal amount) {
|
2018-05-25 08:27:02 +02:00
|
|
|
// Ensure we don't go negative.
|
2019-11-04 18:25:17 +01:00
|
|
|
this.setBalance(targetPlayer, this.backend.getBalance(targetPlayer).subtract(amount).max(BigDecimal.ZERO));
|
2016-06-14 05:06:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2016-09-21 10:16:36 +02:00
|
|
|
* Set a player's balance. This does NOT log.
|
2016-06-14 05:06:58 +02:00
|
|
|
* @param targetPlayer Player to set balance of
|
|
|
|
* @param amount Amount to set balance to
|
|
|
|
* @throws IllegalArgumentException If amount is negative
|
|
|
|
*/
|
2019-11-04 10:43:33 +01:00
|
|
|
public void setBalance(Economable targetPlayer, BigDecimal amount) {
|
2019-11-04 18:25:17 +01:00
|
|
|
amount = NumberUtils.filterAmount(this.currency, amount);
|
2016-06-15 01:47:14 +02:00
|
|
|
|
2020-01-24 08:06:54 +01:00
|
|
|
if (EconomableConsole.isConsole(targetPlayer)) {
|
2016-09-21 10:16:36 +02:00
|
|
|
return;
|
|
|
|
}
|
2016-08-15 08:34:55 +02:00
|
|
|
|
2019-11-04 18:25:17 +01:00
|
|
|
this.backend.setBalance(targetPlayer, amount);
|
2016-06-14 05:06:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2016-09-22 09:54:46 +02:00
|
|
|
* Perform a transaction - a transfer of funds from one entity to another.
|
2016-09-21 10:16:36 +02:00
|
|
|
* @param transaction Transaction to perform.
|
2016-09-22 09:54:46 +02:00
|
|
|
* @return TransactionResult describing success or failure of the Transaction.
|
2016-06-14 05:06:58 +02:00
|
|
|
*/
|
2016-09-21 10:16:36 +02:00
|
|
|
public TransactionResult transact(Transaction transaction) {
|
|
|
|
Economable sender = transaction.getSender();
|
|
|
|
Economable receiver = transaction.getReceiver();
|
2019-11-04 10:43:33 +01:00
|
|
|
BigDecimal amount = transaction.getAmount(); // This amount is validated and filtered upon creation of Transaction
|
2016-09-21 10:16:36 +02:00
|
|
|
|
2018-05-25 08:27:02 +02:00
|
|
|
if (Bukkit.getServer().getPluginManager() != null) { // Bukkit.getServer().getPluginManager() == null from our JUnit tests.
|
2017-07-05 15:59:34 +02:00
|
|
|
SaneEconomyTransactionEvent evt = new SaneEconomyTransactionEvent(transaction);
|
2019-10-31 13:05:22 +01:00
|
|
|
|
2019-11-04 10:49:41 +01:00
|
|
|
if (Bukkit.isPrimaryThread()) {
|
2019-10-31 13:05:22 +01:00
|
|
|
Bukkit.getServer().getPluginManager().callEvent(evt);
|
|
|
|
|
2019-11-04 10:49:41 +01:00
|
|
|
if (evt.isCancelled()) {
|
2019-10-31 13:05:22 +01:00
|
|
|
return new TransactionResult(transaction, TransactionResult.Status.CANCELLED_BY_PLUGIN);
|
|
|
|
}
|
2019-11-04 10:49:41 +01:00
|
|
|
} else {
|
|
|
|
Future<SaneEconomyTransactionEvent> future = Bukkit.getServer().getScheduler().callSyncMethod(SaneEconomy.getInstance(), () -> {
|
|
|
|
Bukkit.getServer().getPluginManager().callEvent(evt);
|
|
|
|
return evt;
|
|
|
|
});
|
|
|
|
|
|
|
|
try {
|
|
|
|
if (future.get().isCancelled()) {
|
|
|
|
return new TransactionResult(transaction, TransactionResult.Status.CANCELLED_BY_PLUGIN);
|
|
|
|
}
|
|
|
|
} catch (InterruptedException | ExecutionException e) {
|
|
|
|
throw new RuntimeException(e);
|
|
|
|
}
|
2019-10-31 13:05:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2017-07-05 15:59:34 +02:00
|
|
|
Bukkit.getServer().getPluginManager().callEvent(evt);
|
|
|
|
if (evt.isCancelled()) {
|
|
|
|
return new TransactionResult(transaction, TransactionResult.Status.CANCELLED_BY_PLUGIN);
|
2019-10-31 13:05:22 +01:00
|
|
|
}*/
|
2017-07-05 15:57:26 +02:00
|
|
|
}
|
|
|
|
|
2016-10-02 17:33:30 +02:00
|
|
|
if (transaction.isSenderAffected()) { // Sender should have balance taken from them
|
2019-11-04 18:25:17 +01:00
|
|
|
if (!this.hasBalance(sender, amount)) {
|
2016-09-22 09:54:46 +02:00
|
|
|
return new TransactionResult(transaction, TransactionResult.Status.ERR_NOT_ENOUGH_FUNDS);
|
2016-09-21 10:16:36 +02:00
|
|
|
}
|
2016-06-14 05:06:58 +02:00
|
|
|
|
2019-11-04 18:25:17 +01:00
|
|
|
this.subtractBalance(sender, amount);
|
2016-06-14 05:06:58 +02:00
|
|
|
}
|
|
|
|
|
2016-10-02 17:33:30 +02:00
|
|
|
if (transaction.isReceiverAffected()) { // Receiver should have balance added to them
|
2019-11-04 18:25:17 +01:00
|
|
|
this.addBalance(receiver, amount);
|
2016-10-02 10:27:47 +02:00
|
|
|
}
|
2016-06-14 05:06:58 +02:00
|
|
|
|
2019-11-04 18:25:17 +01:00
|
|
|
this.saneEconomy.getTransactionLogger().ifPresent((logger) -> logger.logTransaction(transaction));
|
2016-08-15 08:34:55 +02:00
|
|
|
|
2019-11-04 18:25:17 +01:00
|
|
|
return new TransactionResult(transaction, this.getBalance(sender), this.getBalance(receiver));
|
2016-06-14 05:06:58 +02:00
|
|
|
}
|
2016-06-14 14:31:52 +02:00
|
|
|
|
2016-07-12 02:22:07 +02:00
|
|
|
/**
|
|
|
|
* Get the players who have the most money.
|
|
|
|
* @param amount Maximum number of players to show.
|
|
|
|
* @return Map of OfflinePlayer to Double
|
|
|
|
*/
|
2019-11-04 10:43:33 +01:00
|
|
|
public Map<String, BigDecimal> getTopBalances(int amount, int offset) {
|
2019-11-04 18:25:17 +01:00
|
|
|
LinkedHashMap<String, BigDecimal> uuidBalances = this.backend.getTopBalances();
|
2016-07-12 02:22:07 +02:00
|
|
|
|
2018-10-05 10:38:35 +02:00
|
|
|
/* TODO
|
2017-06-10 22:20:27 +02:00
|
|
|
uuidBalances.forEach((uuid, balance) -> {
|
2017-07-15 22:36:32 +02:00
|
|
|
OfflinePlayer offlinePlayer = Bukkit.getServer().getOfflinePlayer(uuid);
|
|
|
|
if (offlinePlayer != null) {
|
2017-11-21 20:01:52 +01:00
|
|
|
if ((this.saneEconomy.getVaultHook() == null) || !this.saneEconomy.getVaultHook().hasPermission(offlinePlayer, "saneeconomy.balancetop.hide")) {
|
2017-07-15 22:36:32 +02:00
|
|
|
playerBalances.put(Bukkit.getServer().getOfflinePlayer(uuid), balance);
|
|
|
|
}
|
2017-06-10 22:20:27 +02:00
|
|
|
}
|
|
|
|
});
|
2018-10-05 10:38:35 +02:00
|
|
|
*/
|
2016-07-12 02:22:07 +02:00
|
|
|
|
2018-10-05 10:38:35 +02:00
|
|
|
return MapUtil.skipAndTake(uuidBalances, offset, amount);
|
2016-07-12 02:22:07 +02:00
|
|
|
}
|
|
|
|
|
2016-06-14 14:31:52 +02:00
|
|
|
public EconomyStorageBackend getBackend() {
|
2019-11-04 18:25:17 +01:00
|
|
|
return this.backend;
|
2016-06-14 14:31:52 +02:00
|
|
|
}
|
2017-02-14 17:28:04 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the name of the "Server" economy account. This account has an infinite balance and deposits do nothing.
|
|
|
|
* @return Server economy account, or null if none.
|
|
|
|
*/
|
|
|
|
public String getServerAccountName() {
|
2019-11-04 18:25:17 +01:00
|
|
|
return this.serverAccountName;
|
2017-02-14 17:28:04 +01:00
|
|
|
}
|
2016-06-14 05:06:58 +02:00
|
|
|
}
|