From bfc77f76ea2059c758033f2593b9df04cc127bcf Mon Sep 17 00:00:00 2001 From: LlmDl Date: Wed, 22 May 2024 15:37:56 -0500 Subject: [PATCH] Fix the TownyTransactionEvent assuming a player is involved. Alters Transactions to no longer use a Player and instead try to use a TownyObject. Rethink Transaction to adopt a Account instead of a TownyObject and Name. Fix javadoc Fix Account initializing TownyObject null. Add helper method to Transaction. Clean up EconomyAccount, move the TownyServerAccount instance to Account. Alter Transaction again in order to add both Receiving and Sending accounts. Remove getName/getTownyObject from Transaction, change TownyObject in Account over to EconomyHandler. Return government field to BankAccount. Throw the TownyTransactionEvent earlier, so that we can better support the new sender and receiver fields in the Transaction. Fix flipped sender/receiver. Notify observers of payTo/payFromServer only when the transaction is a success. A very hacky way to get the TownyServerAccount to implement EconomyHandler. Change transaction package, adopt new builder pattern, deprecate existing Transaction and TransactionType classes. Reduce diff and a couple better javadocs --- .../bukkit/towny/TownyEconomyHandler.java | 64 ++++++------------- .../event/economy/BankTransactionEvent.java | 2 +- .../economy/NationPreTransactionEvent.java | 2 +- .../event/economy/NationTransactionEvent.java | 2 +- .../economy/TownPreTransactionEvent.java | 2 +- .../event/economy/TownTransactionEvent.java | 2 +- .../economy/TownyPreTransactionEvent.java | 21 ++---- .../event/economy/TownyTransactionEvent.java | 2 +- .../bukkit/towny/object/EconomyAccount.java | 21 +++--- .../bukkit/towny/object/Government.java | 2 +- .../bukkit/towny/object/Resident.java | 2 +- .../bukkit/towny/object/Transaction.java | 5 ++ .../bukkit/towny/object/TransactionType.java | 5 ++ .../bukkit/towny/object/economy/Account.java | 39 ++++++++--- .../towny/object/economy/BankAccount.java | 6 +- .../towny/object/economy/BankTransaction.java | 2 +- .../economy/GovernmentAccountAuditor.java | 2 +- .../object/economy/TownyServerAccount.java | 57 +++++++++++++++-- .../TownyServerAccountEconomyHandler.java | 23 +++++++ .../economy/transaction/Transaction.java | 58 +++++++++++++++++ .../transaction/TransactionBuilder.java | 55 ++++++++++++++++ .../economy/transaction/TransactionType.java | 15 +++++ .../bukkit/towny/tasks/DailyTimerTask.java | 6 +- .../towny/tasks/TeleportWarmupTimerTask.java | 2 +- .../bukkit/towny/utils/MoneyUtil.java | 17 +++-- .../bukkit/towny/utils/SpawnUtil.java | 5 +- .../bukkit/towny/utils/TownRuinUtil.java | 2 +- 27 files changed, 306 insertions(+), 115 deletions(-) create mode 100644 Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/TownyServerAccountEconomyHandler.java create mode 100644 Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/transaction/Transaction.java create mode 100644 Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/transaction/TransactionBuilder.java create mode 100644 Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/transaction/TransactionType.java diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/TownyEconomyHandler.java b/Towny/src/main/java/com/palmergames/bukkit/towny/TownyEconomyHandler.java index 5956c3ab8cb..5a81ebb8187 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/TownyEconomyHandler.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/TownyEconomyHandler.java @@ -2,14 +2,14 @@ import com.palmergames.bukkit.config.ConfigNodes; import com.palmergames.bukkit.towny.event.economy.TownyPreTransactionEvent; -import com.palmergames.bukkit.towny.event.economy.TownyTransactionEvent; import com.palmergames.bukkit.towny.object.economy.adapter.ReserveEconomyAdapter; import com.palmergames.bukkit.towny.object.Nation; import com.palmergames.bukkit.towny.object.Resident; import com.palmergames.bukkit.towny.object.Town; -import com.palmergames.bukkit.towny.object.Transaction; -import com.palmergames.bukkit.towny.object.TransactionType; +import com.palmergames.bukkit.towny.object.economy.transaction.Transaction; +import com.palmergames.bukkit.towny.object.economy.Account; import com.palmergames.bukkit.towny.object.economy.TownyServerAccount; +import com.palmergames.bukkit.towny.object.economy.TownyServerAccountEconomyHandler; import com.palmergames.bukkit.towny.object.economy.adapter.EconomyAdapter; import com.palmergames.bukkit.towny.object.economy.adapter.VaultEconomyAdapter; import com.palmergames.bukkit.util.BukkitTools; @@ -18,9 +18,7 @@ import net.milkbowl.vault.economy.Economy; import net.tnemc.core.Reserve; -import org.bukkit.Bukkit; import org.bukkit.World; -import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.RegisteredServiceProvider; import org.jetbrains.annotations.Nullable; @@ -98,6 +96,12 @@ public static void initialize(Towny plugin) { TownyEconomyHandler.plugin = plugin; } + public static TownyServerAccount initializeTownyServerAccount() { + TownyServerAccountEconomyHandler economyHandler = new TownyServerAccount(); + TownyServerAccount account = new TownyServerAccount(economyHandler); + return account; + } + /** * @return the economy type we have detected. */ @@ -211,7 +215,7 @@ public static boolean hasEnough(String accountName, double amount, World world) private static boolean runPreChecks(Transaction transaction, String accountName) { TownyPreTransactionEvent preEvent = new TownyPreTransactionEvent(transaction); - if (BukkitTools.isEventCancelled(preEvent)) { + if (BukkitTools.isEventCancelled(preEvent) && transaction.getPlayer() != null) { TownyMessaging.sendErrorMsg(transaction.getPlayer(), preEvent.getCancelMessage()); return false; } @@ -219,28 +223,22 @@ private static boolean runPreChecks(Transaction transaction, String accountName) checkNewAccount(accountName); return true; } - /** * Attempts to remove an amount from an account * - * @param accountName name of the account to modify + * @param account the Account losing money. * @param amount amount of currency to remove from the account * @param world name of the world in which to check in (TNE Reserve) * @return true if successful */ - public static boolean subtract(String accountName, double amount, World world) { + public static boolean subtract(Account account, double amount, World world) { - Player player = Bukkit.getServer().getPlayerExact(accountName); - Transaction transaction = new Transaction(TransactionType.SUBTRACT, player, amount); - TownyTransactionEvent event = new TownyTransactionEvent(transaction); - - if (!runPreChecks(transaction, accountName)) { + if (!runPreChecks(Transaction.subtract(amount).paidBy(account).build(), account.getName())) { return false; } - if (economy.subtract(accountName, amount, world)) { - BukkitTools.fireEvent(event); + if (economy.subtract(account.getName(), amount, world)) { return true; } @@ -250,23 +248,18 @@ public static boolean subtract(String accountName, double amount, World world) { /** * Add funds to an account. * - * @param accountName account to add funds to + * @param account the Account receiving money. * @param amount amount of currency to add * @param world name of world (for TNE Reserve) * @return true if successful */ - public static boolean add(String accountName, double amount, World world) { + public static boolean add(Account account, double amount, World world) { - Player player = Bukkit.getServer().getPlayerExact(accountName); - Transaction transaction = new Transaction(TransactionType.ADD, player, amount); - TownyTransactionEvent event = new TownyTransactionEvent(transaction); - - if (!runPreChecks(transaction, accountName)) { + if (!runPreChecks(Transaction.add(amount).paidTo(account).build(), account.getName())) { return false; } - if (economy.add(accountName, amount, world)) { - BukkitTools.fireEvent(event); + if (economy.add(account.getName(), amount, world)) { return true; } @@ -297,27 +290,6 @@ public static String getFormattedBalance(double balance) { } - /** - * Adds money to the server account (used for towny closed economy.) - * - * @param amount The amount to deposit. - * @param world The world of the deposit. - * @return A boolean indicating success. - */ - public static boolean addToServer(double amount, World world) { - return add(getServerAccount(), amount, world); - } - - /** - * Removes money to the server account (used for towny closed economy.) - * - * @param amount The amount to withdraw. - * @param world The world of the withdraw. - * @return A boolean indicating success. - */ - public static boolean subtractFromServer(double amount, World world) { - return subtract(getServerAccount(), amount, world); - } private static void checkNewAccount(String accountName) { // Check if the account exists, if not create one. diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/event/economy/BankTransactionEvent.java b/Towny/src/main/java/com/palmergames/bukkit/towny/event/economy/BankTransactionEvent.java index 7cfd13022da..ab9691a69ef 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/event/economy/BankTransactionEvent.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/event/economy/BankTransactionEvent.java @@ -2,7 +2,7 @@ import com.palmergames.bukkit.towny.object.economy.Account; import com.palmergames.bukkit.towny.object.economy.BankAccount; -import com.palmergames.bukkit.towny.object.Transaction; +import com.palmergames.bukkit.towny.object.economy.transaction.Transaction; import org.bukkit.Bukkit; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/event/economy/NationPreTransactionEvent.java b/Towny/src/main/java/com/palmergames/bukkit/towny/event/economy/NationPreTransactionEvent.java index b4ff2d30d63..d4d67a56519 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/event/economy/NationPreTransactionEvent.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/event/economy/NationPreTransactionEvent.java @@ -2,7 +2,7 @@ import com.palmergames.bukkit.towny.event.CancellableTownyEvent; import com.palmergames.bukkit.towny.object.Nation; -import com.palmergames.bukkit.towny.object.Transaction; +import com.palmergames.bukkit.towny.object.economy.transaction.Transaction; import com.palmergames.bukkit.towny.object.economy.BankAccount; import org.bukkit.event.HandlerList; diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/event/economy/NationTransactionEvent.java b/Towny/src/main/java/com/palmergames/bukkit/towny/event/economy/NationTransactionEvent.java index 1824f05289c..a17f5a90373 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/event/economy/NationTransactionEvent.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/event/economy/NationTransactionEvent.java @@ -1,7 +1,7 @@ package com.palmergames.bukkit.towny.event.economy; import com.palmergames.bukkit.towny.object.Nation; -import com.palmergames.bukkit.towny.object.Transaction; +import com.palmergames.bukkit.towny.object.economy.transaction.Transaction; import com.palmergames.bukkit.towny.object.economy.BankAccount; /** diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/event/economy/TownPreTransactionEvent.java b/Towny/src/main/java/com/palmergames/bukkit/towny/event/economy/TownPreTransactionEvent.java index 3c9eae19ce5..74a4f841724 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/event/economy/TownPreTransactionEvent.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/event/economy/TownPreTransactionEvent.java @@ -2,7 +2,7 @@ import com.palmergames.bukkit.towny.event.CancellableTownyEvent; import com.palmergames.bukkit.towny.object.Town; -import com.palmergames.bukkit.towny.object.Transaction; +import com.palmergames.bukkit.towny.object.economy.transaction.Transaction; import com.palmergames.bukkit.towny.object.economy.BankAccount; import org.bukkit.event.HandlerList; diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/event/economy/TownTransactionEvent.java b/Towny/src/main/java/com/palmergames/bukkit/towny/event/economy/TownTransactionEvent.java index 00ed52100e8..d0c1d101e7a 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/event/economy/TownTransactionEvent.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/event/economy/TownTransactionEvent.java @@ -1,7 +1,7 @@ package com.palmergames.bukkit.towny.event.economy; import com.palmergames.bukkit.towny.object.Town; -import com.palmergames.bukkit.towny.object.Transaction; +import com.palmergames.bukkit.towny.object.economy.transaction.Transaction; import com.palmergames.bukkit.towny.object.economy.BankAccount; /** diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/event/economy/TownyPreTransactionEvent.java b/Towny/src/main/java/com/palmergames/bukkit/towny/event/economy/TownyPreTransactionEvent.java index 9a7322e56ea..27b0947bf79 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/event/economy/TownyPreTransactionEvent.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/event/economy/TownyPreTransactionEvent.java @@ -1,8 +1,7 @@ package com.palmergames.bukkit.towny.event.economy; -import com.palmergames.bukkit.towny.TownyEconomyHandler; import com.palmergames.bukkit.towny.event.CancellableTownyEvent; -import com.palmergames.bukkit.towny.object.Transaction; +import com.palmergames.bukkit.towny.object.economy.transaction.Transaction; import com.palmergames.bukkit.towny.object.economy.Account; import org.bukkit.event.HandlerList; @@ -40,19 +39,11 @@ public Transaction getTransaction() { * @return the future balance of the {@link Account} if this event is not * cancelled. */ - public int getNewBalance() { - switch (transaction.getType()) { - case ADD: - return (int) (TownyEconomyHandler.getBalance(transaction.getPlayer().getName(), - transaction.getPlayer().getWorld()) + transaction.getAmount()); - case SUBTRACT: - return (int) (TownyEconomyHandler.getBalance(transaction.getPlayer().getName(), - transaction.getPlayer().getWorld()) - transaction.getAmount()); - default: - break; - } - - return 0; + public double getNewBalance() { + return switch (transaction.getType()) { + case ADD, DEPOSIT -> transaction.getReceivingAccount().getHoldingBalance() + transaction.getAmount(); + case SUBTRACT, WITHDRAW -> transaction.getReceivingAccount().getHoldingBalance() - transaction.getAmount(); + }; } public static HandlerList getHandlerList() { diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/event/economy/TownyTransactionEvent.java b/Towny/src/main/java/com/palmergames/bukkit/towny/event/economy/TownyTransactionEvent.java index 089ae790ebd..b32ae4182a5 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/event/economy/TownyTransactionEvent.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/event/economy/TownyTransactionEvent.java @@ -1,6 +1,6 @@ package com.palmergames.bukkit.towny.event.economy; -import com.palmergames.bukkit.towny.object.Transaction; +import com.palmergames.bukkit.towny.object.economy.transaction.Transaction; import org.bukkit.Bukkit; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/object/EconomyAccount.java b/Towny/src/main/java/com/palmergames/bukkit/towny/object/EconomyAccount.java index 35e739af6ce..8b6da4617ca 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/object/EconomyAccount.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/object/EconomyAccount.java @@ -2,37 +2,36 @@ import com.palmergames.bukkit.towny.TownyEconomyHandler; import com.palmergames.bukkit.towny.object.economy.Account; -import com.palmergames.bukkit.towny.object.economy.TownyServerAccount; +import com.palmergames.bukkit.towny.object.economy.BankAccount; import org.bukkit.World; /** - * Economy object which provides an interface with the Economy Handler. + * An Account object representing a Player's account. In contrast to the + * {@link BankAccount} that represents Towns' and Nations' Accounts. * * @author ElgarL * @author Shade * @author Suneet Tipirneni (Siris) + * @author LlmDl */ public class EconomyAccount extends Account { - public static final TownyServerAccount SERVER_ACCOUNT = new TownyServerAccount(); private World world; - protected EconomyAccount(String name, World world) { - super(name); + protected EconomyAccount(Resident resident, String name, World world) { + super(resident, name); this.world = world; } @Override protected synchronized boolean addMoney(double amount) { - return TownyEconomyHandler.add(getName(), amount, world); + + return TownyEconomyHandler.add(this, amount, world); + } @Override protected synchronized boolean subtractMoney(double amount) { - return TownyEconomyHandler.subtract(getName(), amount, world); - } - - protected EconomyAccount(String name) { - super(name); + return TownyEconomyHandler.subtract(this, amount, world); } public World getWorld() { diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/object/Government.java b/Towny/src/main/java/com/palmergames/bukkit/towny/object/Government.java index 07d7e5652e6..fc4e892b20d 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/object/Government.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/object/Government.java @@ -266,7 +266,7 @@ public final synchronized void depositToBank(Resident resident, int amount) thro if (!TownyEconomyHandler.isActive()) { throw new TownyException(Translation.of("msg_err_no_economy")); } - if (!resident.getAccount().payTo(amount, getAccount(), "Deposit from " + resident.getName())) { + if (!resident.getAccount().payTo(amount, this, "Deposit from " + resident.getName())) { throw new TownyException(Translation.of("msg_insuf_funds")); } } diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/object/Resident.java b/Towny/src/main/java/com/palmergames/bukkit/towny/object/Resident.java index e776580a19e..7595bc76979 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/object/Resident.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/object/Resident.java @@ -818,7 +818,7 @@ public Account getAccount() { world = BukkitTools.getWorlds().get(0); } - account = new EconomyAccount(accountName, world); + account = new EconomyAccount(this, accountName, world); } return account; diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/object/Transaction.java b/Towny/src/main/java/com/palmergames/bukkit/towny/object/Transaction.java index 78a77c466de..5197962f7ef 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/object/Transaction.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/object/Transaction.java @@ -2,6 +2,11 @@ import org.bukkit.entity.Player; + +/** + * @deprecated since 0.100.3.1 use {@link com.palmergames.bukkit.towny.object.economy.transaction.Transaction} instead. + */ +@Deprecated public class Transaction { private final TransactionType type; private final Player player; diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/object/TransactionType.java b/Towny/src/main/java/com/palmergames/bukkit/towny/object/TransactionType.java index bd1723cfb33..be746a0f130 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/object/TransactionType.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/object/TransactionType.java @@ -1,5 +1,10 @@ package com.palmergames.bukkit.towny.object; + +/** + * @deprecated since 0.100.3.1 use {@link com.palmergames.bukkit.towny.object.economy.transaction.TransactionType} instead. + */ +@Deprecated public enum TransactionType { DEPOSIT("Deposit"), WITHDRAW("Withdraw"), ADD("Add"), SUBTRACT("Subtract"); diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/Account.java b/Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/Account.java index e946474cccb..17753445f1a 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/Account.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/Account.java @@ -7,6 +7,7 @@ import com.palmergames.bukkit.towny.object.EconomyAccount; import com.palmergames.bukkit.towny.object.EconomyHandler; import com.palmergames.bukkit.towny.object.Nameable; +import com.palmergames.bukkit.towny.object.economy.transaction.Transaction; import com.palmergames.bukkit.util.BukkitTools; import org.bukkit.World; @@ -24,17 +25,20 @@ * @see EconomyAccount */ public abstract class Account implements Nameable { + public static final TownyServerAccount SERVER_ACCOUNT = TownyEconomyHandler.initializeTownyServerAccount(); private static final long CACHE_TIMEOUT = TownySettings.getCachedBankTimeout(); private static final AccountObserver GLOBAL_OBSERVER = new GlobalAccountObserver(); private final List observers = new ArrayList<>(); + private final EconomyHandler economyHandler; private AccountAuditor auditor; protected CachedBalance cachedBalance = null; String name; World world; - public Account(String name) { + public Account(EconomyHandler economyHandler, String name) { this.name = name; + this.economyHandler = economyHandler; // ALL account transactions will route auditing data through this // central auditor. @@ -49,8 +53,8 @@ public Account(String name) { } } - public Account(String name, World world) { - this(name); + public Account(EconomyHandler economyHandler, String name, World world) { + this(economyHandler, name); this.world = world; } @@ -72,6 +76,7 @@ public synchronized boolean deposit(double amount, String reason) { if (TownySettings.getBoolean(ConfigNodes.ECO_CLOSED_ECONOMY_ENABLED)) return payFromServer(amount, reason); + BukkitTools.fireEvent(Transaction.add(amount).paidTo(this).asTownyTransactionEvent()); return true; } @@ -92,6 +97,7 @@ public synchronized boolean withdraw(double amount, String reason) { if (TownySettings.getBoolean(ConfigNodes.ECO_CLOSED_ECONOMY_ENABLED)) return payToServer(amount, reason); + BukkitTools.fireEvent(Transaction.subtract(amount).paidBy(this).asTownyTransactionEvent()); return true; } @@ -111,15 +117,19 @@ public synchronized boolean payTo(double amount, EconomyHandler collector, Strin } protected synchronized boolean payToServer(double amount, String reason) { - notifyObserversDeposit(EconomyAccount.SERVER_ACCOUNT, amount, reason); // Put it back into the server. - return TownyEconomyHandler.addToServer(amount, getBukkitWorld()); + boolean success = Account.SERVER_ACCOUNT.addToServer(this, amount, getBukkitWorld()); + if (success) + notifyObserversDeposit(Account.SERVER_ACCOUNT, amount, reason); + return success; } protected synchronized boolean payFromServer(double amount, String reason) { - notifyObserversWithdraw(EconomyAccount.SERVER_ACCOUNT, amount, reason); // Remove it from the server economy. - return TownyEconomyHandler.subtractFromServer(amount, getBukkitWorld()); + boolean success = Account.SERVER_ACCOUNT.subtractFromServer(this, amount, getBukkitWorld()); + if (success) + notifyObserversWithdraw(Account.SERVER_ACCOUNT, amount, reason); + return success; } /** @@ -136,7 +146,10 @@ public synchronized boolean payTo(double amount, Account collector, String reaso return false; } - return withdraw(amount, reason) && collector.deposit(amount, reason); + boolean success = withdraw(amount, reason) && collector.deposit(amount, reason); + if (success) + BukkitTools.fireEvent(Transaction.add(amount).paidBy(this).paidTo(collector).asTownyTransactionEvent()); + return success; } /** @@ -214,11 +227,19 @@ public void removeAccount() { if (TownySettings.isEcoClosedEconomyEnabled()) { double balance = TownyEconomyHandler.getBalance(getName(), getBukkitWorld()); if (balance > 0) - TownyEconomyHandler.addToServer(balance, getBukkitWorld()); + Account.SERVER_ACCOUNT.addToServer(this, balance, getBukkitWorld()); } TownyEconomyHandler.removeAccount(getName()); } + /** + * @return the EconomyHandler that this Account represents. Could be a Resident, + * Town, Nation or the TownyServerAccount. + */ + public EconomyHandler getEconomyHandler() { + return economyHandler; + } + @Override public String getName() { return name; diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/BankAccount.java b/Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/BankAccount.java index b4e21c66ffd..42b7c956230 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/BankAccount.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/BankAccount.java @@ -32,7 +32,7 @@ public class BankAccount extends Account { * @param government Town or Nation that is getting a BankAccount. */ public BankAccount(String name, World world, Government government) { - super(name, world); + super(government, name, world); this.government = government; } @@ -71,7 +71,7 @@ protected synchronized boolean subtractMoney(double amount) { } // Otherwise continue like normal. - return TownyEconomyHandler.subtract(getName(), amount, world); + return TownyEconomyHandler.subtract(this, amount, world); } @Override @@ -84,7 +84,7 @@ protected synchronized boolean addMoney(double amount) { return removeDebt(amount); // Otherwise continue like normal. - return TownyEconomyHandler.add(getName(), amount, world); + return TownyEconomyHandler.add(this, amount, world); } @Override diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/BankTransaction.java b/Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/BankTransaction.java index d4e1e4d0542..28bd373f1ec 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/BankTransaction.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/BankTransaction.java @@ -2,7 +2,7 @@ import java.text.SimpleDateFormat; -import com.palmergames.bukkit.towny.object.TransactionType; +import com.palmergames.bukkit.towny.object.economy.transaction.TransactionType; public class BankTransaction { private static final SimpleDateFormat dateFormat = new SimpleDateFormat("MMM d ''yy '@' HH:mm:ss"); diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/GovernmentAccountAuditor.java b/Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/GovernmentAccountAuditor.java index 010202f99c3..c43d67824d8 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/GovernmentAccountAuditor.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/GovernmentAccountAuditor.java @@ -7,7 +7,7 @@ import com.palmergames.bukkit.util.Colors; import com.palmergames.bukkit.towny.Towny; import com.palmergames.bukkit.towny.TownyEconomyHandler; -import com.palmergames.bukkit.towny.object.TransactionType; +import com.palmergames.bukkit.towny.object.economy.transaction.TransactionType; public class GovernmentAccountAuditor implements AccountAuditor { diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/TownyServerAccount.java b/Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/TownyServerAccount.java index d85b6417dd4..7dbab586614 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/TownyServerAccount.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/TownyServerAccount.java @@ -2,19 +2,28 @@ import java.util.UUID; +import org.bukkit.World; + import com.palmergames.bukkit.config.ConfigNodes; import com.palmergames.bukkit.towny.TownyEconomyHandler; import com.palmergames.bukkit.towny.TownySettings; +import com.palmergames.bukkit.towny.object.economy.transaction.Transaction; +import com.palmergames.bukkit.util.BukkitTools; /** * For internal use only. */ -public class TownyServerAccount extends Account { +public class TownyServerAccount extends Account implements TownyServerAccountEconomyHandler { + private final static UUID uuid = UUID.fromString("a73f39b0-1b7c-4930-b4a3-ce101812d926"); private final static String name = TownySettings.getString(ConfigNodes.ECO_CLOSED_ECONOMY_SERVER_ACCOUNT); public TownyServerAccount() { - super(name); + super(null, name); + } + + public TownyServerAccount(TownyServerAccountEconomyHandler economyHandler) { + super(economyHandler, name); } public static UUID getUUID() { @@ -23,11 +32,51 @@ public static UUID getUUID() { @Override protected synchronized boolean addMoney(double amount) { - return TownyEconomyHandler.add(getName(), amount, world); + return TownyEconomyHandler.add(this, amount, world); } @Override protected synchronized boolean subtractMoney(double amount) { - return TownyEconomyHandler.subtract(getName(), amount, world); + return TownyEconomyHandler.subtract(this, amount, world); + } + + + /** + * Adds money to the server account (used for towny closed economy.) + * + * @param account Account sending money to the server. + * @param amount The amount to deposit. + * @param world The world of the deposit. + * @return A boolean indicating success. + */ + @Override + public boolean addToServer(Account account, double amount, World world) { + boolean success = TownyEconomyHandler.add(this, amount, world); + if (success) + BukkitTools.fireEvent(Transaction.add(amount).paidBy(account).paidToServer().asTownyTransactionEvent()); + + return success; } + + /** + * Removes money to the server account (used for towny closed economy.) + * + * @param amount The amount to withdraw. + * @param world The world of the withdraw. + * @return A boolean indicating success. + */ + @Override + public boolean subtractFromServer(Account account, double amount, World world) { + boolean success = TownyEconomyHandler.subtract(this, amount, world); + if (success) + BukkitTools.fireEvent(Transaction.subtract(amount).paidByServer().paidTo(account).asTownyTransactionEvent()); + + return success; + } + + @Override + public Account getAccount() { + return this; + } + } diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/TownyServerAccountEconomyHandler.java b/Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/TownyServerAccountEconomyHandler.java new file mode 100644 index 00000000000..247063dc447 --- /dev/null +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/TownyServerAccountEconomyHandler.java @@ -0,0 +1,23 @@ +package com.palmergames.bukkit.towny.object.economy; + +import org.bukkit.World; + +import com.palmergames.bukkit.towny.object.EconomyHandler; + +/** + * Defines methods necessary for the TownyServerAccount, used mainly in the + * closed economy feature. + */ +public interface TownyServerAccountEconomyHandler extends EconomyHandler { + /** + * Gets the account associated with the TownyServerAccount + * + * @return The TownyServerAccount + */ + @Override + Account getAccount(); // Covariant return type of Account from superinterface + + public boolean addToServer(Account account, double amount, World world); + + public boolean subtractFromServer(Account account, double amount, World world); +} diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/transaction/Transaction.java b/Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/transaction/Transaction.java new file mode 100644 index 00000000000..0cf264e3808 --- /dev/null +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/transaction/Transaction.java @@ -0,0 +1,58 @@ +package com.palmergames.bukkit.towny.object.economy.transaction; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.Nullable; + +import com.palmergames.bukkit.towny.object.economy.Account; + +public class Transaction { + private final TransactionType type; + private final Account receivingAccount; + private final Account sendingAccount; + private final double amount; + + public Transaction(TransactionBuilder builder) { + this.type = builder.type; + this.receivingAccount = builder.receivingAccount; + this.sendingAccount = builder.sendingAccount; + this.amount = builder.amount; + } + + public static TransactionBuilder add(double amount) { + return new TransactionBuilder(amount, TransactionType.ADD); + } + + public static TransactionBuilder subtract(double amount) { + return new TransactionBuilder(amount, TransactionType.SUBTRACT); + } + + public static TransactionBuilder deposit(double amount) { + return new TransactionBuilder(amount, TransactionType.DEPOSIT); + } + + public static TransactionBuilder withdraw(double amount) { + return new TransactionBuilder(amount, TransactionType.WITHDRAW); + } + + public TransactionType getType() { + return type; + } + + public Account getReceivingAccount() { + return receivingAccount; + } + + public Account getSendingAccount() { + return sendingAccount; + } + + @Nullable + public Player getPlayer() { + return Bukkit.getServer().getPlayerExact(getSendingAccount().getName()); + } + + public double getAmount() { + return amount; + } +} diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/transaction/TransactionBuilder.java b/Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/transaction/TransactionBuilder.java new file mode 100644 index 00000000000..fc66862cc1f --- /dev/null +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/transaction/TransactionBuilder.java @@ -0,0 +1,55 @@ +package com.palmergames.bukkit.towny.object.economy.transaction; + +import com.palmergames.bukkit.towny.event.economy.TownyTransactionEvent; +import com.palmergames.bukkit.towny.object.EconomyHandler; +import com.palmergames.bukkit.towny.object.economy.Account; + +public class TransactionBuilder { + TransactionType type; + Account receivingAccount; + Account sendingAccount; + double amount; + + public TransactionBuilder(double amount, TransactionType type) { + this.amount = amount; + this.type = type; + } + + public TransactionBuilder paidTo(Account account) { + this.receivingAccount = account; + return this; + } + + public TransactionBuilder paidTo(EconomyHandler handler) { + this.receivingAccount = handler.getAccount(); + return this; + } + + public TransactionBuilder paidToServer() { + this.receivingAccount = Account.SERVER_ACCOUNT; + return this; + } + + public TransactionBuilder paidBy(Account account) { + this.sendingAccount = account; + return this; + } + + public TransactionBuilder paidBy(EconomyHandler handler) { + this.sendingAccount = handler.getAccount(); + return this; + } + + public TransactionBuilder paidByServer() { + this.sendingAccount = Account.SERVER_ACCOUNT; + return this; + } + + public Transaction build() { + return new Transaction(this); + } + + public TownyTransactionEvent asTownyTransactionEvent() { + return new TownyTransactionEvent(new Transaction(this)); + } +} diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/transaction/TransactionType.java b/Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/transaction/TransactionType.java new file mode 100644 index 00000000000..7ec99af9c4d --- /dev/null +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/object/economy/transaction/TransactionType.java @@ -0,0 +1,15 @@ +package com.palmergames.bukkit.towny.object.economy.transaction; + +public enum TransactionType { + DEPOSIT("Deposit"), WITHDRAW("Withdraw"), ADD("Add"), SUBTRACT("Subtract"); + + private final String name; + + TransactionType(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/DailyTimerTask.java b/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/DailyTimerTask.java index 2c23ee9e88a..d749fb8e12d 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/DailyTimerTask.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/DailyTimerTask.java @@ -353,7 +353,7 @@ private String processTownPaysNationTax(Town town, Nation nation) { private void payNationTaxToTown(Nation nation, Town town, double tax) { if (!nation.getAccount().canPayFromHoldings(tax)) return; - nation.getAccount().payTo(tax, town.getAccount(), "Nation Tax Payment To Town"); + nation.getAccount().payTo(tax, town, "Nation Tax Payment To Town"); taxCollected += tax; } @@ -505,7 +505,7 @@ private boolean collectTownTaxFromResident(double tax, Resident resident, Town t private void payTownTaxToResidents(Town town, Resident resident, double tax) { if (!town.getAccount().canPayFromHoldings(tax)) return; - town.getAccount().payTo(tax, resident.getAccount(), "Town Tax Payment To Resident"); + town.getAccount().payTo(tax, resident, "Town Tax Payment To Resident"); taxCollected += tax; } @@ -591,7 +591,7 @@ private boolean collectPlotTaxFromResident(double tax, Resident resident, Town t private void payPlotTaxToResidents(double tax, Resident resident, Town town, String typeName) { if (!town.getAccount().canPayFromHoldings(tax)) return; - town.getAccount().payTo(tax, resident.getAccount(), String.format("Plot Tax Payment To Resident (%s)", typeName)); + town.getAccount().payTo(tax, resident, String.format("Plot Tax Payment To Resident (%s)", typeName)); taxCollected += tax; } diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/TeleportWarmupTimerTask.java b/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/TeleportWarmupTimerTask.java index fcf0c11c1e2..8fe916b992b 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/TeleportWarmupTimerTask.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/TeleportWarmupTimerTask.java @@ -132,7 +132,7 @@ public static boolean abortTeleportRequest(@Nullable Resident resident, Cancelle return false; if (request.teleportCost() != 0 && TownyEconomyHandler.isActive() && request.teleportAccount() != null) { - TownyEconomyHandler.economyExecutor().execute(() -> request.teleportAccount().payTo(request.teleportCost(), resident.getAccount(), Translation.of("msg_cost_spawn_refund"))); + TownyEconomyHandler.economyExecutor().execute(() -> request.teleportAccount().payTo(request.teleportCost(), resident, Translation.of("msg_cost_spawn_refund"))); TownyMessaging.sendMsg(resident, Translatable.of("msg_cost_spawn_refund")); } diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/MoneyUtil.java b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/MoneyUtil.java index ca17d9a8d8e..e4fc02f695f 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/MoneyUtil.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/MoneyUtil.java @@ -29,8 +29,7 @@ import com.palmergames.bukkit.towny.object.TownBlockType; import com.palmergames.bukkit.towny.object.TownBlockTypeCache.CacheType; import com.palmergames.bukkit.towny.object.statusscreens.StatusScreen; -import com.palmergames.bukkit.towny.object.Transaction; -import com.palmergames.bukkit.towny.object.TransactionType; +import com.palmergames.bukkit.towny.object.economy.transaction.Transaction; import com.palmergames.bukkit.util.BukkitTools; import net.kyori.adventure.text.Component; @@ -59,9 +58,9 @@ public static void townWithdraw(Player player, Resident resident, Town town, int try { commonTests(amount, resident, town, player.getLocation(), false, true); - - Transaction transaction = new Transaction(TransactionType.WITHDRAW, player, amount); - + + Transaction transaction = Transaction.withdraw(amount).paidBy(town).paidTo(resident).build(); + BukkitTools.ifCancelledThenThrow(new TownPreTransactionEvent(town, transaction)); // Withdraw from bank. @@ -81,8 +80,8 @@ public static void townDeposit(Player player, Resident resident, Town town, Nati try { commonTests(amount, resident, town, player.getLocation(), false, false); - Transaction transaction = new Transaction(TransactionType.DEPOSIT, player, amount); - + Transaction transaction = Transaction.deposit(amount).paidBy(resident).paidTo(town).build(); + BukkitTools.ifCancelledThenThrow(new TownPreTransactionEvent(town, transaction)); if (nation == null) { @@ -108,7 +107,7 @@ public static void nationWithdraw(Player player, Resident resident, Nation natio try { commonTests(amount, resident, nation.getCapital(), player.getLocation(), true, true); - Transaction transaction = new Transaction(TransactionType.WITHDRAW, player, amount); + Transaction transaction = Transaction.withdraw(amount).paidBy(nation).paidTo(resident).build(); BukkitTools.ifCancelledThenThrow(new NationPreTransactionEvent(nation, transaction)); @@ -128,7 +127,7 @@ public static void nationDeposit(Player player, Resident resident, Nation nation try { commonTests(amount, resident, nation.getCapital(), player.getLocation(), true, false); - Transaction transaction = new Transaction(TransactionType.DEPOSIT, player, amount); + Transaction transaction = Transaction.deposit(amount).paidBy(resident).paidTo(nation).build(); BukkitTools.ifCancelledThenThrow(new NationPreTransactionEvent(nation, transaction)); diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/SpawnUtil.java b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/SpawnUtil.java index 854965fc89a..a811d7cf3f8 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/SpawnUtil.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/SpawnUtil.java @@ -36,7 +36,6 @@ import com.palmergames.bukkit.towny.object.SpawnType; import com.palmergames.bukkit.towny.object.Town; import com.palmergames.bukkit.towny.object.TownBlock; -import com.palmergames.bukkit.towny.object.EconomyAccount; import com.palmergames.bukkit.towny.object.TownyObject; import com.palmergames.bukkit.towny.permissions.PermissionNodes; import com.palmergames.bukkit.towny.tasks.CooldownTimerTask; @@ -100,7 +99,7 @@ public static void sendToTownySpawn(Player player, String[] split, TownyObject t if (spawnInfo.travelCost > 0) { // Get paymentMsg for the money.csv and the Account being paid. final String paymentMsg = getPaymentMsg(spawnInfo.townSpawnLevel, spawnInfo.nationSpawnLevel, spawnType); - final Account payee = TownySettings.isTownSpawnPaidToTown() ? getPayee(town, nation, spawnType) : EconomyAccount.SERVER_ACCOUNT; + final Account payee = TownySettings.isTownSpawnPaidToTown() ? getPayee(town, nation, spawnType) : Account.SERVER_ACCOUNT; initiateCostedSpawn(player, resident, spawnLoc, spawnInfo.travelCost, payee, paymentMsg, ignoreWarn, spawnInfo.cooldown); // No Cost so skip confirmation system. } else @@ -614,7 +613,7 @@ private static String getPaymentMsg(TownSpawnLevel townSpawnLevel, NationSpawnLe */ private static Account getPayee(Town town, Nation nation, SpawnType spawnType) { return switch(spawnType) { - case RESIDENT -> town == null ? EconomyAccount.SERVER_ACCOUNT : town.getAccount(); + case RESIDENT -> town == null ? Account.SERVER_ACCOUNT : town.getAccount(); case TOWN -> town.getAccount(); case NATION -> nation.getAccount(); }; diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/TownRuinUtil.java b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/TownRuinUtil.java index a1511bf7d30..645928d2f93 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/TownRuinUtil.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/TownRuinUtil.java @@ -81,7 +81,7 @@ public static void putTownIntoRuinedState(Town town) { if (nation != null) { double bankBalance = town.getAccount().getHoldingBalance(); if (TownySettings.areRuinedTownsBanksPaidToNation() && bankBalance > 0) - town.getAccount().payTo(bankBalance, nation.getAccount(), String.format("Ruined Town (%s) Paid Remaining Bank To Nation", town.getName())); + town.getAccount().payTo(bankBalance, nation, String.format("Ruined Town (%s) Paid Remaining Bank To Nation", town.getName())); town.removeNation(); }