diff --git a/api/src/main/java/dev/xhyrom/lighteco/api/model/user/User.java b/api/src/main/java/dev/xhyrom/lighteco/api/model/user/User.java index c56bd68..0ff76c9 100644 --- a/api/src/main/java/dev/xhyrom/lighteco/api/model/user/User.java +++ b/api/src/main/java/dev/xhyrom/lighteco/api/model/user/User.java @@ -36,4 +36,22 @@ public interface User { * @param balance the balance */ void setBalance(@NonNull Currency currency, @NonNull BigDecimal balance); + + /** + * Add the specified amount to the balance of this user for the specified currency. + * + * @param currency the currency + * @param amount the amount + * @throws IllegalArgumentException if the amount is negative + */ + void deposit(@NonNull Currency currency, @NonNull BigDecimal amount) throws IllegalArgumentException; + + /** + * Subtract the specified amount from the balance of this user for the specified currency. + * + * @param currency the currency + * @param amount the amount + * @throws IllegalArgumentException if the amount is negative + */ + void withdraw(@NonNull Currency currency, @NonNull BigDecimal amount) throws IllegalArgumentException; } diff --git a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/hooks/PlaceholderAPIExpansion.java b/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/hooks/PlaceholderAPIExpansion.java index 6546038..7679f09 100644 --- a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/hooks/PlaceholderAPIExpansion.java +++ b/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/hooks/PlaceholderAPIExpansion.java @@ -1,9 +1,12 @@ package dev.xhyrom.lighteco.bukkit.hooks; import dev.xhyrom.lighteco.bukkit.BukkitLightEcoPlugin; +import dev.xhyrom.lighteco.common.model.currency.Currency; +import dev.xhyrom.lighteco.common.model.user.User; import lombok.RequiredArgsConstructor; import me.clip.placeholderapi.expansion.PlaceholderExpansion; import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -28,6 +31,21 @@ public class PlaceholderAPIExpansion extends PlaceholderExpansion { @Override public @Nullable String onRequest(OfflinePlayer player, @NotNull String params) { + String[] args = params.split("_"); + if (args.length < 2) return null; + + String currencyIdentifier = args[0]; + String type = args[1]; + + Currency currency = this.plugin.getCurrencyManager().getIfLoaded(currencyIdentifier); + if (currency == null) return null; + + if (type.equalsIgnoreCase("balance")) { + User user = this.plugin.getUserManager().loadUser(player.getUniqueId()).join(); + + return user.getBalance(currency).toPlainString(); + } + return "lighteco"; } } diff --git a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/manager/BukkitCommandManager.java b/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/manager/BukkitCommandManager.java index 2e68e7e..8d903f3 100644 --- a/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/manager/BukkitCommandManager.java +++ b/bukkit/src/main/java/dev/xhyrom/lighteco/bukkit/manager/BukkitCommandManager.java @@ -52,6 +52,7 @@ public class BukkitCommandManager extends AbstractCommandManager { // Dont expose set, give, take directly - only through main command new CommandAPICommand(currency.getIdentifier()) + .withPermission("lighteco.currency." + currency.getIdentifier() + ".command") .withSubcommand(new SetCommand(this, currency, permissionBase).build()) .withSubcommand(new GiveCommand(this, currency, permissionBase).build()) .withSubcommand(new TakeCommand(this, currency, permissionBase).build()) diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiUser.java b/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiUser.java index b65e905..afc0f5c 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiUser.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/api/impl/ApiUser.java @@ -42,4 +42,22 @@ public class ApiUser implements User { this.handler.setBalance(internal, balance); } + + @Override + public void deposit(@NonNull Currency currency, @NonNull BigDecimal amount) { + dev.xhyrom.lighteco.common.model.currency.Currency internal = this.handler.getPlugin() + .getCurrencyManager() + .getIfLoaded(currency.getIdentifier()); + + this.handler.deposit(internal, amount); + } + + @Override + public void withdraw(@NonNull Currency currency, @NonNull BigDecimal amount) { + dev.xhyrom.lighteco.common.model.currency.Currency internal = this.handler.getPlugin() + .getCurrencyManager() + .getIfLoaded(currency.getIdentifier()); + + this.handler.withdraw(internal, amount); + } } diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/manager/command/AbstractCommandManager.java b/common/src/main/java/dev/xhyrom/lighteco/common/manager/command/AbstractCommandManager.java index 574b33e..f1d1a0d 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/manager/command/AbstractCommandManager.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/manager/command/AbstractCommandManager.java @@ -100,7 +100,16 @@ public abstract class AbstractCommandManager implements CommandManager { addToMustWait(sender.getUniqueId(), target.getUniqueId()); amount = amount.setScale(currency.getProxy().fractionalDigits(), RoundingMode.DOWN); - target.setBalance(currency, amount); + try { + target.setBalance(currency, amount); + } catch (IllegalArgumentException e) { + sender.sendMessage( + miniMessage.deserialize("Cannot set negative money!") + ); + + removeFromMustWait(target.getUniqueId(), sender.getUniqueId()); + return; + } sender.sendMessage( miniMessage.deserialize("Set " + target.getUsername() + "'s balance to " + amount.toPlainString() + " " + currency.getIdentifier()) @@ -115,7 +124,16 @@ public abstract class AbstractCommandManager implements CommandManager { addToMustWait(sender.getUniqueId(), target.getUniqueId()); amount = amount.setScale(currency.getProxy().fractionalDigits(), RoundingMode.DOWN); - target.setBalance(currency, target.getBalance(currency).add(amount)); + try { + target.deposit(currency, amount); + } catch (IllegalArgumentException e) { + sender.sendMessage( + miniMessage.deserialize("Cannot give negative money!") + ); + + removeFromMustWait(target.getUniqueId(), sender.getUniqueId()); + return; + } sender.sendMessage( miniMessage.deserialize("Gave " + target.getUsername() + " " + amount.toPlainString() + " " + currency.getIdentifier()) @@ -130,7 +148,16 @@ public abstract class AbstractCommandManager implements CommandManager { addToMustWait(sender.getUniqueId(), target.getUniqueId()); amount = amount.setScale(currency.getProxy().fractionalDigits(), RoundingMode.DOWN); - target.setBalance(currency, target.getBalance(currency).subtract(amount)); + try { + target.withdraw(currency, amount); + } catch (IllegalArgumentException e) { + sender.sendMessage( + miniMessage.deserialize("Cannot take negative money!") + ); + + removeFromMustWait(target.getUniqueId(), sender.getUniqueId()); + return; + } sender.sendMessage( miniMessage.deserialize("Took " + amount.toPlainString() + " " + currency.getIdentifier() + " from " + target.getUsername()) @@ -170,8 +197,8 @@ public abstract class AbstractCommandManager implements CommandManager { // subtract tax from amount BigDecimal taxedAmount = amount.subtract(tax); - target.setBalance(currency, target.getBalance(currency).add(taxedAmount)); - user.setBalance(currency, user.getBalance(currency).subtract(amount)); + target.deposit(currency, taxedAmount); + user.withdraw(currency, amount); // send message that will include original amount, taxed amount, tax rate - percentage amount and tax amount sender.sendMessage( diff --git a/common/src/main/java/dev/xhyrom/lighteco/common/model/user/User.java b/common/src/main/java/dev/xhyrom/lighteco/common/model/user/User.java index a3a6665..a819fad 100644 --- a/common/src/main/java/dev/xhyrom/lighteco/common/model/user/User.java +++ b/common/src/main/java/dev/xhyrom/lighteco/common/model/user/User.java @@ -39,9 +39,34 @@ public class User { } public void setBalance(@NonNull Currency currency, @NonNull BigDecimal balance) { + if (balance.compareTo(BigDecimal.ZERO) < 0) { + throw new IllegalArgumentException("Balance cannot be negative"); + } + balances.put(currency, balance); } + public void deposit(@NonNull Currency currency, @NonNull BigDecimal amount) throws IllegalArgumentException { + if (amount.compareTo(BigDecimal.ZERO) < 0) { + throw new IllegalArgumentException("Amount cannot be negative"); + } + + setBalance(currency, getBalance(currency).add(amount)); + } + + public void withdraw(@NonNull Currency currency, @NonNull BigDecimal amount) throws IllegalArgumentException { + if (amount.compareTo(BigDecimal.ZERO) < 0) { + throw new IllegalArgumentException("Amount cannot be negative"); + } + + if (getBalance(currency).compareTo(amount) < 0) { + // Withdraw all + amount = getBalance(currency); + } + + setBalance(currency, getBalance(currency).subtract(amount)); + } + public void invalidateCaches() { balances.clear(); } diff --git a/currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/bukkit/hooks/vault/Vault.java b/currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/bukkit/hooks/vault/Vault.java index 4eaafb7..6a9537f 100644 --- a/currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/bukkit/hooks/vault/Vault.java +++ b/currency-money/src/main/java/dev/xhyrom/lighteco/currency/money/bukkit/hooks/vault/Vault.java @@ -7,10 +7,12 @@ import dev.xhyrom.lighteco.api.model.user.User; import net.milkbowl.vault.economy.AbstractEconomy; import net.milkbowl.vault.economy.EconomyResponse; import org.bukkit.Bukkit; +import org.jetbrains.annotations.NotNull; import java.math.BigDecimal; import java.util.List; import java.util.UUID; +import java.util.concurrent.ExecutionException; public class Vault extends AbstractEconomy { private final LightEco provider; @@ -105,14 +107,39 @@ public class Vault extends AbstractEconomy { UUID uniqueId = Bukkit.getPlayerUniqueId(playerName); User user = provider.getUserManager().loadUser(uniqueId).join(); - BigDecimal balance = user.getBalance(currency); - BigDecimal newBalance = balance.subtract(BigDecimal.valueOf(amount)); + try { + user.withdraw(currency, BigDecimal.valueOf(amount)); + } catch (IllegalArgumentException e) { + return new EconomyResponse( + amount, + bigDecimalToDouble(user.getBalance(currency)), + EconomyResponse.ResponseType.FAILURE, + "Cannot withdraw negative funds" + ); + } - user.setBalance(currency, newBalance); + return saveUser(amount, user); + } - provider.getUserManager().saveUser(user); + @NotNull + private EconomyResponse saveUser(double amount, User user) { + try { + provider.getUserManager().saveUser(user).get(); + } catch (InterruptedException | ExecutionException e) { + return new EconomyResponse( + amount, + bigDecimalToDouble(user.getBalance(currency)), + EconomyResponse.ResponseType.FAILURE, + "Cannot save user" + ); + } - return new EconomyResponse(amount, bigDecimalToDouble(newBalance), EconomyResponse.ResponseType.SUCCESS, ""); + return new EconomyResponse( + amount, + bigDecimalToDouble(user.getBalance(currency)), + EconomyResponse.ResponseType.SUCCESS, + "" + ); } @Override @@ -125,14 +152,18 @@ public class Vault extends AbstractEconomy { UUID uniqueId = Bukkit.getPlayerUniqueId(playerName); User user = provider.getUserManager().loadUser(uniqueId).join(); - BigDecimal balance = user.getBalance(currency); - BigDecimal newBalance = balance.add(BigDecimal.valueOf(amount)); + try { + user.deposit(currency, BigDecimal.valueOf(amount)); + } catch (IllegalArgumentException e) { + return new EconomyResponse( + amount, + bigDecimalToDouble(user.getBalance(currency)), + EconomyResponse.ResponseType.FAILURE, + "Cannot deposit negative funds" + ); + } - user.setBalance(currency, newBalance); - - provider.getUserManager().saveUser(user); - - return new EconomyResponse(amount, bigDecimalToDouble(newBalance), EconomyResponse.ResponseType.SUCCESS, ""); + return saveUser(amount, user); } @Override