From 5e6308ec21d7a899184d5310f090f68b1c099562 Mon Sep 17 00:00:00 2001 From: WinTone01 <103455948+WinTone01@users.noreply.github.com> Date: Mon, 2 Oct 2023 19:25:28 +0300 Subject: [PATCH 01/25] Create tr-TR.yml --- src/main/resources/tr-TR.yml | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/main/resources/tr-TR.yml diff --git a/src/main/resources/tr-TR.yml b/src/main/resources/tr-TR.yml new file mode 100644 index 0000000..17177ef --- /dev/null +++ b/src/main/resources/tr-TR.yml @@ -0,0 +1,34 @@ +#Turkish language file by WinTone01 +noConsole: Bu komutu kullanabilmek için oyunda olmalısınız! +noPermission: Bu komutu kullanma izniniz yok! +missingArguments: Komut için bazı parametreler eksik! +playerNotFound: Oyuncu bulunamadı! +invalidAmount: Girilen değer geçersiz! +invalidCurrency: Geçersiz para birimi! +insufficientFunds: Yeterli paranız yok! +balance: Bakiyeniz: %balance%! +balanceSet: %player% hesabının bakiyesi %balance% olarak ayarlandı! +balanceOther: %player% adlı oyuncunun bakiyesi: %balance%! +balanceTop: En zengin oyuncular:
%prevpage% %page% %nextpage% +balanceTopFormat: %pos% - %player% %balance% +paySelf: Kendinize ödeme yapamazsınız! +paySuccess: %player% adlı oyuncuya %amount% ödediniz, %tax_percentage% vergi (%tax_applied% uygulandı)! +payFail: Ödeme başarısız oldu! +payReceived: %player% adlı oyuncudan %amount% aldınız! +purgeUserSuccess: %player% adlı kullanıcı temizlendi! +switchCurrencySuccess: %currency% para biriminden %switch-currency% para birimine geçildi.
Lütfen çakışmaları önlemek için her RedisEconomy örneğini yeniden başlatın!
+noTransactionFound: %player% için hiçbir işlem bulunamadı! +transactionsStart: %player% adlı oyuncunun işlemleri %after% - %before% arası! +transactionsEnd: %player% adlı oyuncunun işlemlerinin sonu, %time% ms içinde tamamlandı +editMessageError: Bu yapılandırma alanı mevcut değil veya bir dize değil! +editMessageClickHere: %field%'yi düzenlemek için buraya tıklayın! +editMessageSuccess: %field% başarıyla kaydedildi! +transactionItem: + outgoingFunds: '#%id% Kopyalamak için tıklayın:
%timestamp%">[Zaman Damgası⌛] [←Geri Al]
%account-owner% > %amount%%symbol% > %other-account%
Sebep: %reason%' + incomingFunds: '#%id% Kopyalamak için tıklayın:
%timestamp%">[Zaman Damgası⌛] [←Geri Al]
%other-account% > %amount%%symbol% > %account-owner%
Sebep: %reason%' +unitSymbols: + thousand: k + million: m + billion: M + trillion: T + quadrillion: Q From 7e9f1e53ee586f59742b7ec7de7311630b774eef Mon Sep 17 00:00:00 2001 From: WinTone01 <103455948+WinTone01@users.noreply.github.com> Date: Fri, 19 Jan 2024 16:27:36 +0300 Subject: [PATCH 02/25] Update tr-TR.yml --- src/main/resources/tr-TR.yml | 43 ++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/src/main/resources/tr-TR.yml b/src/main/resources/tr-TR.yml index 17177ef..9153add 100644 --- a/src/main/resources/tr-TR.yml +++ b/src/main/resources/tr-TR.yml @@ -1,31 +1,40 @@ #Turkish language file by WinTone01 -noConsole: Bu komutu kullanabilmek için oyunda olmalısınız! +noConsole: Oyuncu olmalısınız, bu komutu kullanmak için! noPermission: Bu komutu kullanma izniniz yok! -missingArguments: Komut için bazı parametreler eksik! +missingArguments: Komut için eksik parametreler! playerNotFound: Oyuncu bulunamadı! invalidAmount: Girilen değer geçersiz! invalidCurrency: Geçersiz para birimi! -insufficientFunds: Yeterli paranız yok! -balance: Bakiyeniz: %balance%! -balanceSet: %player% hesabının bakiyesi %balance% olarak ayarlandı! -balanceOther: %player% adlı oyuncunun bakiyesi: %balance%! +insufficientFunds: Yeterli bakiyeniz yok! +balance: Bakiyeniz %balance%! +balanceSet: %player% adlı oyuncunun hesabına %balance% eklediniz! +balanceOther: %player%'in bakiyesi %balance%! balanceTop: En zengin oyuncular:
%prevpage% %page% %nextpage% balanceTopFormat: %pos% - %player% %balance% paySelf: Kendinize ödeme yapamazsınız! -paySuccess: %player% adlı oyuncuya %amount% ödediniz, %tax_percentage% vergi (%tax_applied% uygulandı)! +paySuccess: %amount% tutarındaki ödemeyi %player% adlı oyuncuya yaptınız. Komisyon oranı %tax_percentage% (%tax_applied%)! payFail: Ödeme başarısız oldu! -payReceived: %player% adlı oyuncudan %amount% aldınız! -purgeUserSuccess: %player% adlı kullanıcı temizlendi! -switchCurrencySuccess: %currency% para biriminden %switch-currency% para birimine geçildi.
Lütfen çakışmaları önlemek için her RedisEconomy örneğini yeniden başlatın!
-noTransactionFound: %player% için hiçbir işlem bulunamadı! -transactionsStart: %player% adlı oyuncunun işlemleri %after% - %before% arası! -transactionsEnd: %player% adlı oyuncunun işlemlerinin sonu, %time% ms içinde tamamlandı +payReceived: %player% adlı oyuncudan %amount% tutarında ödeme aldınız! +purgeUserSuccess: %player%'e eşleşen kullanıcı temizlendi! +switchCurrencySuccess: %currency% başarıyla %switch-currency% ile değiştirildi. Lütfen çakışmaları önlemek için RedisEconomy'nin her örneğini yeniden başlatın! +noTransactionFound: %player% adlı oyuncu için herhangi bir işlem bulunamadı! +transactionsStart: %player%'in işlemleri %after% - %before% arasında! +transactionsEnd: %player%'in işlemleri %time% ms içinde sona erdi editMessageError: Bu yapılandırma alanı mevcut değil veya bir dize değil! -editMessageClickHere: %field%'yi düzenlemek için buraya tıklayın! -editMessageSuccess: %field% başarıyla kaydedildi! +editMessageClickHere: %field% düzenlemek için buraya tıklayın! +editMessageSuccess: %field% başarıyla kaydedildi! transactionItem: - outgoingFunds: '#%id% Kopyalamak için tıklayın:
%timestamp%">[Zaman Damgası⌛] [←Geri Al]
%account-owner% > %amount%%symbol% > %other-account%
Sebep: %reason%' - incomingFunds: '#%id% Kopyalamak için tıklayın:
%timestamp%">[Zaman Damgası⌛] [←Geri Al]
%other-account% > %amount%%symbol% > %account-owner%
Sebep: %reason%' + outgoingFunds: '#%id% Kopyalamak için tıkla:
%timestamp%">[Zaman Damgası⌛] + [←Geri Al]
%account-owner% + > %amount%%symbol% > %other-account%
Neden: + %reason%' + incomingFunds: '#%id% Kopyalamak için tıkla:
%timestamp%">[Zaman Damgası⌛] + [←Geri Al]
%other-account% > %amount%%symbol% + > %account-owner%
Neden: + %reason%' unitSymbols: thousand: k million: m From 8b7a0091beee0ea14c5138e478798c0c0c0b05c3 Mon Sep 17 00:00:00 2001 From: Emibergo02 <36164338+Emibergo02@users.noreply.github.com> Date: Sat, 16 Mar 2024 13:01:56 +0100 Subject: [PATCH 03/25] 4.3.9 Fixed desynchronization issue Fixed migration: moved to enable instead of load Updated all dependencies Java 17 Dropped support for 1.16 --- jitpack.yml | 6 +- pom.xml | 30 ++-- .../rediseconomy/RedisEconomyPlugin.java | 38 ++--- .../rediseconomy/command/MainCommand.java | 16 ++ .../rediseconomy/config/ConfigManager.java | 45 +++--- .../currency/CurrenciesManager.java | 84 +++++----- .../rediseconomy/currency/Currency.java | 72 ++++----- .../currency/CurrencyWithBanks.java | 38 +++-- .../rediseconomy/redis/RedisManager.java | 15 ++ .../transaction/EconomyExchange.java | 143 +++++++++--------- src/main/resources/plugin.yml | 4 +- 11 files changed, 265 insertions(+), 226 deletions(-) diff --git a/jitpack.yml b/jitpack.yml index f0cebce..f29a667 100644 --- a/jitpack.yml +++ b/jitpack.yml @@ -1,5 +1,5 @@ jdk: - - openjdk16 + - openjdk17 before_install: - - sdk install java 16.0.1-open - - sdk use java 16.0.1-open \ No newline at end of file + - sdk install java 17.0.1-open + - sdk use java 17.0.1-open \ No newline at end of file diff --git a/pom.xml b/pom.xml index b5eb37d..be2f964 100644 --- a/pom.xml +++ b/pom.xml @@ -6,13 +6,13 @@ dev.unnm3d RedisEconomy - 4.3.8-SNAPSHOT + 4.3.9-SNAPSHOT jar RedisEconomy - 16 + 17 UTF-8 @@ -23,8 +23,8 @@ maven-compiler-plugin 3.8.1 - 16 - 16 + 17 + 17 @@ -113,17 +113,13 @@ placeholderapi https://repo.extendedclip.com/content/repositories/placeholderapi/ - - devmart-other - https://nexuslite.gcnt.net/repos/other/ - org.spigotmc spigot-api - 1.16.5-R0.1-SNAPSHOT + 1.17.1-R0.1-SNAPSHOT provided @@ -135,35 +131,35 @@ org.projectlombok lombok - 1.18.26 + 1.18.30 provided net.kyori adventure-text-minimessage - 4.14.0 + 4.16.0 net.kyori adventure-platform-bukkit - 4.3.0 + 4.3.2 me.clip placeholderapi - 2.11.3 + 2.11.5 provided io.lettuce lettuce-core - 6.2.4.RELEASE + 6.3.2.RELEASE provided - com.github.Emibergo02 - ConfigLib - master-SNAPSHOT + de.exlll + configlib-yaml + 4.5.0 com.github.Anon8281 diff --git a/src/main/java/dev/unnm3d/rediseconomy/RedisEconomyPlugin.java b/src/main/java/dev/unnm3d/rediseconomy/RedisEconomyPlugin.java index 740ce43..b3d4766 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/RedisEconomyPlugin.java +++ b/src/main/java/dev/unnm3d/rediseconomy/RedisEconomyPlugin.java @@ -34,6 +34,7 @@ public final class RedisEconomyPlugin extends JavaPlugin { + @Getter private static RedisEconomyPlugin instance; //private EzRedisMessenger ezRedisMessenger; @Getter @@ -43,6 +44,8 @@ public final class RedisEconomyPlugin extends JavaPlugin { private RedisManager redisManager; @Getter private TaskScheduler scheduler; + @Getter + private Plugin vaultPlugin; public Settings settings() { @@ -53,10 +56,6 @@ public Langs langs() { return configManager.getLangs(); } - public static RedisEconomyPlugin getInstance() { - return instance; - } - @Override public void onLoad() { instance = this; @@ -67,27 +66,30 @@ public void onLoad() { this.getLogger().severe("Disabling: redis server unreachable!"); this.getLogger().severe("Please setup a redis server before running this plugin!"); this.getServer().getPluginManager().disablePlugin(this); - return; } else { this.getLogger().info("Redis server connected!"); } - - if (!setupVault()) { //creates currenciesManager and exchange - this.getLogger().severe("Disabled due to no Vault dependency found!"); - this.getServer().getPluginManager().disablePlugin(this); - } else { - this.getLogger().info("Hooked into Vault!"); - } } @Override public void onEnable() { this.scheduler = UniversalScheduler.getScheduler(this); this.configManager.postStartupLoad(); + this.vaultPlugin = getServer().getPluginManager().getPlugin("Vault"); + if (this.vaultPlugin == null) { //creates currenciesManager and exchange + this.getLogger().severe("Disabled due to no Vault dependency found!"); + this.getServer().getPluginManager().disablePlugin(this); + return; + } + + this.currenciesManager = new CurrenciesManager(redisManager, this, configManager); + this.getLogger().info("Hooked into Vault!"); + if (settings().migrationEnabled) { scheduler.runTaskLater(() -> - currenciesManager.getCompleteMigration().complete(null), - 100L);//load: STARTUP doesn't consider dependencies on load so i have to wait a bit (bukkit bug?) + currenciesManager.migrateFromOfflinePlayers(getServer().getOfflinePlayers()), 100L); + } else { + currenciesManager.loadDefaultCurrency(this.vaultPlugin); } getServer().getPluginManager().registerEvents(currenciesManager, this); @@ -164,14 +166,6 @@ private boolean setupRedis() { } } - private boolean setupVault() { - Plugin vault = getServer().getPluginManager().getPlugin("Vault"); - if (vault == null) - return false; - this.currenciesManager = new CurrenciesManager(redisManager, this, configManager); - currenciesManager.loadDefaultCurrency(vault); - return true; - } private void loadCommand(String cmdName, CommandExecutor executor, TabCompleter tabCompleter) { PluginCommand cmd = getServer().getPluginCommand(cmdName); diff --git a/src/main/java/dev/unnm3d/rediseconomy/command/MainCommand.java b/src/main/java/dev/unnm3d/rediseconomy/command/MainCommand.java index 2e143ba..2c2f34b 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/command/MainCommand.java +++ b/src/main/java/dev/unnm3d/rediseconomy/command/MainCommand.java @@ -7,6 +7,7 @@ import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.command.TabCompleter; +import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import java.lang.reflect.Field; @@ -25,6 +26,9 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command plugin.getConfigManager().getLangs().send(sender, plugin.langs().missingArguments); return true; } else if (args.length == 1) { + if(args[0].equalsIgnoreCase("stress")){ + stress(); + } if (!args[0].equalsIgnoreCase("reload")) return true; if (!sender.hasPermission("rediseconomy.admin")) return true; String serverId = plugin.getConfigManager().getSettings().serverId; //Keep serverId @@ -79,6 +83,18 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command return true; } + private void stress() { + Player p=plugin.getServer().getPlayer("Unnm3d"); + for(int i=0;i<1000;i++){ + if(i==400)plugin.getServer().dispatchCommand(plugin.getServer().getConsoleSender(), "balance Unnm3d vault set 0"); + plugin.getServer().dispatchCommand(plugin.getServer().getConsoleSender(), "balance Unnm3d vault give 1"); + plugin.getServer().getScheduler().runTaskAsynchronously(plugin, () -> { + plugin.getCurrenciesManager().getDefaultCurrency().depositPlayer(p, 1); + }); + } + + } + @Override public @NotNull List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) { diff --git a/src/main/java/dev/unnm3d/rediseconomy/config/ConfigManager.java b/src/main/java/dev/unnm3d/rediseconomy/config/ConfigManager.java index c10ab23..e5dadd0 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/config/ConfigManager.java +++ b/src/main/java/dev/unnm3d/rediseconomy/config/ConfigManager.java @@ -11,8 +11,10 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; +import org.bukkit.plugin.messaging.ChannelNotRegisteredException; import java.io.File; +import java.nio.charset.StandardCharsets; import java.util.concurrent.CompletableFuture; public class ConfigManager { @@ -22,6 +24,19 @@ public class ConfigManager { @Getter private Langs langs; + private static final YamlConfigurationProperties PROPERTIES = YamlConfigurationProperties.newBuilder() + .header( + """ + ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ + ┃ RedisEconomy Config ┃ + ┃ Developed by Unnm3d ┃ + ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + """ + ) + .footer("Authors: Unnm3d") + .charset(StandardCharsets.UTF_8) + .build(); + public ConfigManager(RedisEconomyPlugin plugin) { this.plugin = plugin; loadSettingsConfig(); @@ -36,28 +51,18 @@ public void postStartupLoad() { } public void loadSettingsConfig() { - YamlConfigurationProperties properties = YamlConfigurationProperties.newBuilder() - .header( - """ - ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ - ┃ RedisEconomy Config ┃ - ┃ Developed by Unnm3d ┃ - ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - """ - ) - .footer("Authors: Unnm3d") - .build(); + File settingsFile = new File(plugin.getDataFolder(), "config.yml"); settings = YamlConfigurations.update( settingsFile.toPath(), Settings.class, - properties + PROPERTIES ); } public void saveConfigs() { - YamlConfigurations.save(new File(plugin.getDataFolder(), "config.yml").toPath(), Settings.class, settings); - YamlConfigurations.save(new File(plugin.getDataFolder(), settings.lang + ".yml").toPath(), Langs.class, langs); + YamlConfigurations.save(new File(plugin.getDataFolder(), "config.yml").toPath(), Settings.class, settings, PROPERTIES); + YamlConfigurations.save(new File(plugin.getDataFolder(), settings.lang + ".yml").toPath(), Langs.class, langs, PROPERTIES); } public void loadLangs() { @@ -67,7 +72,8 @@ public void loadLangs() { } langs = YamlConfigurations.update( settingsFile.toPath(), - Langs.class + Langs.class, + PROPERTIES ); } @@ -92,8 +98,11 @@ public void onJoin(org.bukkit.event.player.PlayerJoinEvent event) { plugin.getScheduler().runTaskLaterAsynchronously(() -> sendServerIdRequest(event.getPlayer()), 20L); } }; - if (plugin.getServer().getOnlinePlayers().size() > 0) { - sendServerIdRequest(plugin.getServer().getOnlinePlayers().iterator().next()); + if (!plugin.getServer().getOnlinePlayers().isEmpty()) { + try { + sendServerIdRequest(plugin.getServer().getOnlinePlayers().iterator().next()); + } catch (ChannelNotRegisteredException ignored) { + } } else { plugin.getServer().getPluginManager().registerEvents(listener, plugin); } @@ -107,7 +116,7 @@ public void onJoin(org.bukkit.event.player.PlayerJoinEvent event) { } @SuppressWarnings("UnstableApiUsage") - private void sendServerIdRequest(Player p) { + private void sendServerIdRequest(Player p) throws ChannelNotRegisteredException { ByteArrayDataOutput out = ByteStreams.newDataOutput(); out.writeUTF("GetServer"); p.sendPluginMessage(plugin, "BungeeCord", out.toByteArray());//Request server name diff --git a/src/main/java/dev/unnm3d/rediseconomy/currency/CurrenciesManager.java b/src/main/java/dev/unnm3d/rediseconomy/currency/CurrenciesManager.java index e786bc3..18640a0 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/currency/CurrenciesManager.java +++ b/src/main/java/dev/unnm3d/rediseconomy/currency/CurrenciesManager.java @@ -17,6 +17,7 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.server.PluginEnableEvent; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.RegisteredServiceProvider; import org.bukkit.plugin.ServicePriority; @@ -76,54 +77,56 @@ public CurrenciesManager(RedisManager redisManager, RedisEconomyPlugin plugin, C } - + /** + * Loads the default currency into the vault economy provider + * Unregisters the existent economy provider + * + * @param vaultPlugin the vault plugin + */ public void loadDefaultCurrency(Plugin vaultPlugin) { - Currency defaultCurrency = getDefaultCurrency(); - for (RegisteredServiceProvider registration : plugin.getServer().getServicesManager().getRegistrations(Economy.class)) { plugin.getServer().getServicesManager().unregister(Economy.class, registration.getProvider()); } + plugin.getServer().getServicesManager().register(Economy.class, getDefaultCurrency(), vaultPlugin, ServicePriority.High); + } - if (!configManager.getSettings().migrationEnabled) { - plugin.getServer().getServicesManager().register(Economy.class, defaultCurrency, vaultPlugin, ServicePriority.High); - return; - } - + /** + * Migrates the balances from the existent economy provider to the new one + * using the offline players + * + * @param offlinePlayers the offline players to migrate + */ + public void migrateFromOfflinePlayers(OfflinePlayer[] offlinePlayers) { + final Currency defaultCurrency = getDefaultCurrency(); RegisteredServiceProvider existentProvider = plugin.getServer().getServicesManager().getRegistration(Economy.class); if (existentProvider == null) { plugin.getLogger().severe("Vault economy provider not found!"); return; } - completeMigration.thenApply(voids -> { - plugin.getLogger().info("§aMigrating from " + existentProvider.getProvider().getName() + "..."); - if (existentProvider.getProvider() == defaultCurrency) { - plugin.getLogger().info("There's no other provider apart RedisEconomy!"); - return defaultCurrency; + plugin.getLogger().info("§aMigrating from " + existentProvider.getProvider().getName() + "..."); + + final List> balances = new ArrayList<>(); + final Map nameUniqueIds = new HashMap<>(); + for (int i = 0; i < offlinePlayers.length; i++) { + final OfflinePlayer offlinePlayer = offlinePlayers[i]; + try { + double bal = existentProvider.getProvider().getBalance(offlinePlayer); + balances.add(ScoredValue.just(bal, offlinePlayer.getUniqueId().toString())); + if (offlinePlayer.getName() != null) + nameUniqueIds.put(offlinePlayer.getName(), offlinePlayer.getUniqueId().toString()); + defaultCurrency.updateAccountLocal(offlinePlayer.getUniqueId(), offlinePlayer.getName() == null ? offlinePlayer.getUniqueId().toString() : offlinePlayer.getName(), bal); + } catch (Exception e) { + e.printStackTrace(); } - - List> balances = new ArrayList<>(); - Map nameUniqueIds = new HashMap<>(); - for (OfflinePlayer offlinePlayer : Bukkit.getOfflinePlayers()) { - try { - double bal = existentProvider.getProvider().getBalance(offlinePlayer); - balances.add(ScoredValue.just(bal, offlinePlayer.getUniqueId().toString())); - if (offlinePlayer.getName() != null) - nameUniqueIds.put(offlinePlayer.getName(), offlinePlayer.getUniqueId().toString()); - defaultCurrency.updateAccountLocal(offlinePlayer.getUniqueId(), offlinePlayer.getName() == null ? offlinePlayer.getUniqueId().toString() : offlinePlayer.getName(), bal); - } catch (Exception e) { - e.printStackTrace(); - } + if (i % 100 == 0) { + plugin.getLogger().info("Progress: " + i + "/" + offlinePlayers.length); } - - defaultCurrency.updateBulkAccountsCloudCache(balances, nameUniqueIds); - return defaultCurrency; - }).thenAccept((vaultCurrency) -> { - plugin.getServer().getServicesManager().register(Economy.class, vaultCurrency, vaultPlugin, ServicePriority.High); - plugin.getLogger().info("§aMigration completed!"); - configManager.getSettings().migrationEnabled = false; - configManager.saveConfigs(); - }); - + } + defaultCurrency.updateBulkAccountsCloudCache(balances, nameUniqueIds); + plugin.getLogger().info("§aMigration completed!"); + plugin.getLogger().info("§aRestart the server to apply the changes."); + configManager.getSettings().migrationEnabled = false; + configManager.saveConfigs(); } @Override @@ -258,6 +261,15 @@ private void onJoin(PlayerJoinEvent e) { })); } + @EventHandler + private void onPluginEnable(PluginEnableEvent pluginEnableEvent) { + if (plugin.settings().migrationEnabled) return; + if (!plugin.getServer().getServicesManager().getRegistrations(net.milkbowl.vault.economy.Economy.class) + .stream().allMatch(registration -> registration.getPlugin().equals(plugin))) { + loadDefaultCurrency(plugin.getVaultPlugin()); + } + } + private CompletionStage> loadRedisNameUniqueIds() { return redisManager.getConnectionAsync(connection -> connection.hgetall(NAME_UUID.toString()) diff --git a/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java b/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java index 6f57fcf..1170a00 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java +++ b/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java @@ -4,7 +4,6 @@ import dev.unnm3d.rediseconomy.config.Settings; import dev.unnm3d.rediseconomy.transaction.AccountID; import dev.unnm3d.rediseconomy.transaction.Transaction; -import io.lettuce.core.RedisFuture; import io.lettuce.core.ScoredValue; import io.lettuce.core.pubsub.StatefulRedisPubSubConnection; import lombok.AllArgsConstructor; @@ -19,7 +18,10 @@ import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.*; -import java.util.concurrent.*; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import static dev.unnm3d.rediseconomy.redis.RedisKeys.*; @@ -43,6 +45,7 @@ public class Currency implements Economy { private double transactionTax; @Getter private final boolean taxOnlyPay; + protected final ExecutorService updateExecutor; /** @@ -55,6 +58,7 @@ public class Currency implements Economy { public Currency(CurrenciesManager currenciesManager, Settings.CurrencySettings currencySettings) { this.currenciesManager = currenciesManager; this.enabled = true; + this.updateExecutor = Executors.newSingleThreadExecutor(); this.currencyName = currencySettings.currencyName(); this.currencySingular = currencySettings.currencySingle(); this.currencyPlural = currencySettings.currencyPlural(); @@ -440,8 +444,8 @@ public EconomyResponse setPlayerBalance(@NotNull OfflinePlayer player, double am public EconomyResponse setPlayerBalance(@NotNull UUID playerUUID, @Nullable String playerName, double amount) { if (amount == Double.POSITIVE_INFINITY || amount == Double.NEGATIVE_INFINITY || Double.isNaN(amount)) return new EconomyResponse(0, 0, EconomyResponse.ResponseType.FAILURE, "Invalid decimal amount format"); - currenciesManager.getExchange().saveTransaction(new AccountID(playerUUID), new AccountID(), -getBalance(playerUUID), currencyName, "Reset balance"); updateAccount(playerUUID, playerName, amount); + currenciesManager.getExchange().saveTransaction(new AccountID(playerUUID), new AccountID(), -getBalance(playerUUID), currencyName, "Reset balance"); currenciesManager.getExchange().saveTransaction(new AccountID(playerUUID), new AccountID(), amount, currencyName, "Set balance"); return new EconomyResponse(amount, getBalance(playerUUID), EconomyResponse.ResponseType.SUCCESS, null); } @@ -508,33 +512,32 @@ void updateAccountLocal(@NotNull UUID uuid, @Nullable String playerName, double protected void updateAccount(@NotNull UUID uuid, @Nullable String playerName, double balance) { updateAccountCloudCache(uuid, playerName, balance, 0); updateAccountLocal(uuid, playerName, balance); + } - private void updateAccountCloudCache(@NotNull UUID uuid, @Nullable String playerName, double balance, int tries) { - try { - currenciesManager.getRedisManager().getConnectionPipeline(commands -> { - commands.zadd(BALANCE_PREFIX + currencyName, balance, uuid.toString()); + private synchronized void updateAccountCloudCache(@NotNull UUID uuid, @Nullable String playerName, double balance, int tries) { + updateExecutor.submit(() -> { + currenciesManager.getRedisManager().executeTransaction(reactiveCommands -> { + reactiveCommands.zadd(BALANCE_PREFIX + currencyName, balance, uuid.toString()); if (playerName != null) - commands.hset(NAME_UUID.toString(), playerName, uuid.toString()); - commands.publish(UPDATE_PLAYER_CHANNEL_PREFIX + currencyName, RedisEconomyPlugin.getInstance().settings().serverId + ";;" + uuid + ";;" + playerName + ";;" + balance).thenAccept((result) -> { - if (RedisEconomyPlugin.getInstance().settings().debug) { - Bukkit.getLogger().info("01 Sent update account " + playerName + " to " + balance); - } - }); - return null; - }); - - } catch (Exception e) { - if (tries < 3) { - e.printStackTrace(); - Bukkit.getLogger().severe("Failed to update account " + playerName + " after 3 tries"); - Bukkit.getLogger().severe("Player accounts are desynchronized"); - updateAccountCloudCache(uuid, playerName, balance, tries + 1); - } else { - e.printStackTrace(); - } - } + reactiveCommands.hset(NAME_UUID.toString(), playerName, uuid.toString()); + reactiveCommands.publish(UPDATE_PLAYER_CHANNEL_PREFIX + currencyName, + RedisEconomyPlugin.getInstance().settings().serverId + ";;" + uuid + ";;" + playerName + ";;" + balance); + }).ifPresentOrElse(result -> { + if (RedisEconomyPlugin.getInstance().settings().debug) { + Bukkit.getLogger().info("01 Sent update account " + playerName + " to " + balance + " currency " + currencyName); + } + }, () -> { + if (tries < 3) { + Bukkit.getLogger().severe("Player accounts are desynchronized"); + updateAccountCloudCache(uuid, playerName, balance, tries + 1); + } else { + Bukkit.getLogger().severe("Failed to update account " + playerName + " after 3 tries"); + throw new RuntimeException("Player accounts are desynchronized"); + } + }); + }); } /** @@ -546,19 +549,16 @@ private void updateAccountCloudCache(@NotNull UUID uuid, @Nullable String player */ @SuppressWarnings("unchecked") public void updateBulkAccountsCloudCache(@NotNull List> balances, @NotNull Map nameUUIDs) { - currenciesManager.getRedisManager().getConnectionPipeline(commands -> { + currenciesManager.getRedisManager().executeTransaction(commands -> { ScoredValue[] balancesArray = new ScoredValue[balances.size()]; balances.toArray(balancesArray); - RedisFuture sortedAddFuture = commands.zadd(BALANCE_PREFIX + currencyName, balancesArray); - RedisFuture hstFuture = commands.hset(NAME_UUID.toString(), nameUUIDs); - try { - Bukkit.getLogger().info("migration01 updated balances into " + BALANCE_PREFIX + currencyName + " accounts. result " + sortedAddFuture.get(20, TimeUnit.SECONDS)); - Bukkit.getLogger().info("migration02 updated nameuuids into " + NAME_UUID + " accounts. result " + hstFuture.get(20, TimeUnit.SECONDS)); - } catch (ExecutionException | InterruptedException | TimeoutException e) { - e.printStackTrace(); - } - return null; + commands.zadd(BALANCE_PREFIX + currencyName, balancesArray); + commands.hset(NAME_UUID.toString(), nameUUIDs); + }).ifPresent(result -> { + Bukkit.getLogger().info("migration01 updated balances into " + BALANCE_PREFIX + currencyName + " accounts. result " + result.get(0)); + Bukkit.getLogger().info("migration02 updated nameuuids into " + NAME_UUID + " accounts. result " + result.get(1)); + }); } diff --git a/src/main/java/dev/unnm3d/rediseconomy/currency/CurrencyWithBanks.java b/src/main/java/dev/unnm3d/rediseconomy/currency/CurrencyWithBanks.java index 029f544..3dfaf99 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/currency/CurrencyWithBanks.java +++ b/src/main/java/dev/unnm3d/rediseconomy/currency/CurrencyWithBanks.java @@ -287,27 +287,25 @@ private void updateBankAccount(@NotNull String accountId, double balance) { updateBankAccountLocal(accountId, balance); } - private void updateBankAccountCloudCache(@NotNull String accountId, double balance, int tries) { - try { - currenciesManager.getRedisManager().getConnectionPipeline(commands -> { - commands.zadd(BALANCE_BANK_PREFIX + currencyName, balance, accountId); - return commands.publish(UPDATE_BANK_CHANNEL_PREFIX + currencyName, RedisEconomyPlugin.getInstance().settings().serverId + ";;" + accountId + ";;" + balance).thenAccept((result) -> { - if (RedisEconomyPlugin.getInstance().settings().debug) { - Bukkit.getLogger().info("01 Sent bank update account " + accountId + " to " + balance); - } - }); + private synchronized void updateBankAccountCloudCache(@NotNull String accountId, double balance, int tries) { + updateExecutor.submit(() -> { + currenciesManager.getRedisManager().executeTransaction(reactiveCommands -> { + reactiveCommands.zadd(BALANCE_BANK_PREFIX + currencyName, balance, accountId); + reactiveCommands.publish(UPDATE_BANK_CHANNEL_PREFIX + currencyName, RedisEconomyPlugin.getInstance().settings().serverId + ";;" + accountId + ";;" + balance); + }).ifPresentOrElse(result -> { + if (RedisEconomyPlugin.getInstance().settings().debug) { + Bukkit.getLogger().info("01 Sent bank update accoun " + accountId + " to " + balance); + } + }, () -> { + if (tries < 3) { + Bukkit.getLogger().severe("Player accounts are desynchronized"); + updateBankAccountCloudCache(accountId, balance, tries + 1); + } else { + Bukkit.getLogger().severe("Failed to update account " + accountId + " after 3 tries"); + throw new RuntimeException("Bank accounts are desynchronized"); + } }); - - } catch (Exception e) { - if (tries < 3) { - e.printStackTrace(); - Bukkit.getLogger().severe("Failed to update bank account " + accountId + " after 3 tries"); - Bukkit.getLogger().severe("Bank accounts are desynchronized"); - updateBankAccountCloudCache(accountId, balance, tries + 1); - } else { - e.printStackTrace(); - } - } + }); } /** diff --git a/src/main/java/dev/unnm3d/rediseconomy/redis/RedisManager.java b/src/main/java/dev/unnm3d/rediseconomy/redis/RedisManager.java index 2965065..6939cb9 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/redis/RedisManager.java +++ b/src/main/java/dev/unnm3d/rediseconomy/redis/RedisManager.java @@ -2,16 +2,20 @@ import io.lettuce.core.RedisClient; import io.lettuce.core.RedisFuture; +import io.lettuce.core.TransactionResult; import io.lettuce.core.api.StatefulRedisConnection; import io.lettuce.core.api.async.RedisAsyncCommands; +import io.lettuce.core.api.sync.RedisCommands; import io.lettuce.core.pubsub.StatefulRedisPubSubConnection; import java.time.Duration; import java.util.List; +import java.util.Optional; import java.util.concurrent.CompletionStage; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; +import java.util.function.Consumer; import java.util.function.Function; public class RedisManager { @@ -30,6 +34,9 @@ public RedisManager(RedisClient lettuceRedisClient) { public CompletionStage getConnectionAsync(Function, CompletionStage> redisCallBack) { return redisCallBack.apply(roundRobinConnectionPool.get().async()); } + public T getConnectionSync(Function, T> redisCallBack) { + return redisCallBack.apply(roundRobinConnectionPool.get().sync()); + } public CompletionStage getConnectionPipeline(Function, CompletionStage> redisCallBack) { StatefulRedisConnection connection = roundRobinConnectionPool.get(); @@ -40,6 +47,14 @@ public CompletionStage getConnectionPipeline(Function> executeTransaction(Consumer> redisCommandsConsumer) { + final RedisCommands syncCommands = roundRobinConnectionPool.get().sync(); + syncCommands.multi(); + redisCommandsConsumer.accept(syncCommands); + final TransactionResult transactionResult = syncCommands.exec(); + return Optional.ofNullable(transactionResult.wasDiscarded() ? null : transactionResult.stream().toList()); + } + public StatefulRedisPubSubConnection getPubSubConnection() { StatefulRedisPubSubConnection pubSubConnection = lettuceRedisClient.connectPubSub(); pubSubConnections.add(pubSubConnection); diff --git a/src/main/java/dev/unnm3d/rediseconomy/transaction/EconomyExchange.java b/src/main/java/dev/unnm3d/rediseconomy/transaction/EconomyExchange.java index 1b1e830..1d16be1 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/transaction/EconomyExchange.java +++ b/src/main/java/dev/unnm3d/rediseconomy/transaction/EconomyExchange.java @@ -13,9 +13,7 @@ import java.util.List; import java.util.Map; import java.util.UUID; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.ExecutionException; +import java.util.concurrent.*; import static dev.unnm3d.rediseconomy.redis.RedisKeys.NEW_TRANSACTIONS; @@ -23,6 +21,7 @@ public class EconomyExchange { private final RedisEconomyPlugin plugin; + private final ExecutorService executorService = Executors.newSingleThreadExecutor(); /** * Get transactions from an account id @@ -50,7 +49,7 @@ public CompletionStage removeAllTransactions() { return plugin.getCurrenciesManager().getRedisManager().getConnectionAsync(connection -> { try { List keys = connection.keys(NEW_TRANSACTIONS + "*").get(); - if (keys.size() == 0) { + if (keys.isEmpty()) { return CompletableFuture.completedFuture(0L); } return connection.del(keys.toArray(new String[0])); @@ -89,54 +88,54 @@ public CompletionStage getTransaction(AccountID accountId, int id) * @return List of ids: the first one is the id of the transaction on the sender side, the second one is the id of the transaction on the target side */ public CompletionStage> savePaymentTransaction(@NotNull UUID sender, @NotNull UUID target, double amount, @NotNull Currency currency, @NotNull String reason) { + final CompletableFuture> future = new CompletableFuture<>(); long init = System.currentTimeMillis(); - reason += getCallerPluginString(); - TransactionEvent transactionSenderEvent = new TransactionEvent(new Transaction( - new AccountID(sender), - System.currentTimeMillis(), - new AccountID(target), - -amount, - currency.getCurrencyName(), - reason, - null)); - TransactionEvent transactionReceiverEvent = new TransactionEvent(new Transaction( - new AccountID(target), - System.currentTimeMillis(), - new AccountID(sender), - amount, - currency.getCurrencyName(), - reason, - null)); + executorService.submit(() -> { + final String finalReason = reason + getCallerPluginString(); + TransactionEvent transactionSenderEvent = new TransactionEvent(new Transaction( + new AccountID(sender), + System.currentTimeMillis(), + new AccountID(target), + -amount, + currency.getCurrencyName(), + finalReason, + null)); + TransactionEvent transactionReceiverEvent = new TransactionEvent(new Transaction( + new AccountID(target), + System.currentTimeMillis(), + new AccountID(sender), + amount, + currency.getCurrencyName(), + finalReason, + null)); - plugin.getScheduler().runTask(() -> { - plugin.getServer().getPluginManager().callEvent(transactionSenderEvent); - plugin.getServer().getPluginManager().callEvent(transactionReceiverEvent); - }); + plugin.getScheduler().runTask(() -> { + plugin.getServer().getPluginManager().callEvent(transactionSenderEvent); + plugin.getServer().getPluginManager().callEvent(transactionReceiverEvent); + }); + future.complete(plugin.getCurrenciesManager().getRedisManager().getConnectionSync(connection -> + connection.eval( + "local senderCurrentId=redis.call('hlen', KEYS[1]);" + + "local receiverCurrentId=redis.call('hlen', KEYS[2]);" + + "redis.call('hset', KEYS[1], senderCurrentId, ARGV[1]);" + + "redis.call('hset', KEYS[2], receiverCurrentId, ARGV[2]);" + + "return {senderCurrentId,receiverCurrentId};", //Return the id of the new transaction + ScriptOutputType.MULTI, + new String[]{ + NEW_TRANSACTIONS + sender.toString(), + NEW_TRANSACTIONS + target.toString()}, //Key rediseco:transactions:playerUUID + transactionSenderEvent.getTransaction().toString(), + transactionReceiverEvent.getTransaction().toString()))); - return plugin.getCurrenciesManager().getRedisManager().getConnectionAsync(connection -> - connection.>eval( - "local senderCurrentId=redis.call('hlen', KEYS[1]);" + - "local receiverCurrentId=redis.call('hlen', KEYS[2]);" + - "redis.call('hset', KEYS[1], senderCurrentId, ARGV[1]);" + - "redis.call('hset', KEYS[2], receiverCurrentId, ARGV[2]);" + - "return {senderCurrentId,receiverCurrentId};", //Return the id of the new transaction - ScriptOutputType.MULTI, - new String[]{ - NEW_TRANSACTIONS + sender.toString(), - NEW_TRANSACTIONS + target.toString()}, //Key rediseco:transactions:playerUUID - transactionSenderEvent.getTransaction().toString(), - transactionReceiverEvent.getTransaction().toString())) - .thenApply(response -> { - if (RedisEconomyPlugin.getInstance().settings().debug) { - Bukkit.getLogger().info("03payment Transaction for " + sender + " saved in " + (System.currentTimeMillis() - init) + " ms with id " + response.get(0) + " !"); - Bukkit.getLogger().info("03payment Transaction for " + target + " saved in " + (System.currentTimeMillis() - init) + " ms with id " + response.get(1) + " !"); - } - return response; - }).exceptionally(throwable -> { - throwable.printStackTrace(); - return null; - }); + }); + return future.thenApply(response -> { + if (RedisEconomyPlugin.getInstance().settings().debug) { + Bukkit.getLogger().info("03payment Transaction for " + sender + " saved in " + (System.currentTimeMillis() - init) + " ms with id " + response.get(0) + " !"); + Bukkit.getLogger().info("03payment Transaction for " + target + " saved in " + (System.currentTimeMillis() - init) + " ms with id " + response.get(1) + " !"); + } + return response; + }); } @@ -151,33 +150,31 @@ public CompletionStage> savePaymentTransaction(@NotNull UUID sende * @return The transaction id */ public CompletionStage saveTransaction(@NotNull AccountID accountOwner, @NotNull AccountID target, double amount, @NotNull String currencyName, @NotNull String reason) { + final CompletableFuture future = new CompletableFuture<>(); long init = System.currentTimeMillis(); - return plugin.getCurrenciesManager().getRedisManager().getConnectionAsync(commands -> { - - TransactionEvent transactionEvent = new TransactionEvent(new Transaction( - accountOwner, - System.currentTimeMillis(), - target, //If target is null, it has been sent from the server - amount, currencyName, reason + getCallerPluginString(), null)); - plugin.getScheduler().runTask(() -> plugin.getServer().getPluginManager().callEvent(transactionEvent)); - return commands.eval( - "local currentId=redis.call('hlen', KEYS[1]);" + //Get the current size of the hash - "redis.call('hset', KEYS[1], currentId, ARGV[1]);" + //Add the new transaction - "return currentId;", //Return the id of the new transaction - ScriptOutputType.INTEGER, - new String[]{NEW_TRANSACTIONS + accountOwner.toString()}, //Key rediseco:transactions:playerUUID - transactionEvent.getTransaction().toString()).thenApply(response -> { - if (RedisEconomyPlugin.getInstance().settings().debug) { - Bukkit.getLogger().info("03 Transaction for " + accountOwner + " saved in " + (System.currentTimeMillis() - init) + " ms with id " + response + " !"); - } - return ((Long) response).intValue(); - }).exceptionally(throwable -> { - throwable.printStackTrace(); - return null; - }); - } - ); + executorService.submit(() -> { + TransactionEvent transactionEvent = new TransactionEvent(new Transaction( + accountOwner, + System.currentTimeMillis(), + target, //If target is null, it has been sent from the server + amount, currencyName, reason + getCallerPluginString(), null)); + plugin.getScheduler().runTask(() -> plugin.getServer().getPluginManager().callEvent(transactionEvent)); + Long longResult=plugin.getCurrenciesManager().getRedisManager().getConnectionSync(commands -> commands.eval( + "local currentId=redis.call('hlen', KEYS[1]);" + //Get the current size of the hash + "redis.call('hset', KEYS[1], currentId, ARGV[1]);" + //Add the new transaction + "return currentId;", //Return the id of the new transaction + ScriptOutputType.INTEGER, + new String[]{NEW_TRANSACTIONS + accountOwner.toString()}, //Key rediseco:transactions:playerUUID + transactionEvent.getTransaction().toString())); + future.complete(longResult.intValue()); + }); + return future.thenApply(response -> { + if (RedisEconomyPlugin.getInstance().settings().debug) { + Bukkit.getLogger().info("03 Transaction for " + accountOwner + " saved in " + (System.currentTimeMillis() - init) + " ms with id " + response + " !"); + } + return response; + }); } /** diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 397b99f..a31a8c1 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -6,7 +6,8 @@ load: STARTUP depend: - Vault libraries: - - io.lettuce:lettuce-core:6.2.4.RELEASE + - io.lettuce:lettuce-core:6.3.2.RELEASE + - de.exlll:configlib-yaml:4.5.0 softdepend: - PlaceholderAPI - Essentials @@ -17,6 +18,7 @@ softdepend: - BetterEconomy - ArcaneEconomy - EasyConomy + - Towny folia-supported: true commands: pay: From c8eb73cc6beb45ac8d727a7cdce85cc0a1c3e3ec Mon Sep 17 00:00:00 2001 From: Emibergo02 <36164338+Emibergo02@users.noreply.github.com> Date: Sat, 16 Mar 2024 15:44:40 +0100 Subject: [PATCH 04/25] Removed stress command --- .../unnm3d/rediseconomy/command/MainCommand.java | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/main/java/dev/unnm3d/rediseconomy/command/MainCommand.java b/src/main/java/dev/unnm3d/rediseconomy/command/MainCommand.java index 2c2f34b..2e143ba 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/command/MainCommand.java +++ b/src/main/java/dev/unnm3d/rediseconomy/command/MainCommand.java @@ -7,7 +7,6 @@ import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.command.TabCompleter; -import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import java.lang.reflect.Field; @@ -26,9 +25,6 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command plugin.getConfigManager().getLangs().send(sender, plugin.langs().missingArguments); return true; } else if (args.length == 1) { - if(args[0].equalsIgnoreCase("stress")){ - stress(); - } if (!args[0].equalsIgnoreCase("reload")) return true; if (!sender.hasPermission("rediseconomy.admin")) return true; String serverId = plugin.getConfigManager().getSettings().serverId; //Keep serverId @@ -83,18 +79,6 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command return true; } - private void stress() { - Player p=plugin.getServer().getPlayer("Unnm3d"); - for(int i=0;i<1000;i++){ - if(i==400)plugin.getServer().dispatchCommand(plugin.getServer().getConsoleSender(), "balance Unnm3d vault set 0"); - plugin.getServer().dispatchCommand(plugin.getServer().getConsoleSender(), "balance Unnm3d vault give 1"); - plugin.getServer().getScheduler().runTaskAsynchronously(plugin, () -> { - plugin.getCurrenciesManager().getDefaultCurrency().depositPlayer(p, 1); - }); - } - - } - @Override public @NotNull List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) { From 9f0709f96be84c3cfe71d82124f5b83854bf4d53 Mon Sep 17 00:00:00 2001 From: Emibergo02 <36164338+Emibergo02@users.noreply.github.com> Date: Sun, 17 Mar 2024 14:07:41 +0100 Subject: [PATCH 05/25] Reduced verbose --- .../dev/unnm3d/rediseconomy/RedisEconomyPlugin.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/java/dev/unnm3d/rediseconomy/RedisEconomyPlugin.java b/src/main/java/dev/unnm3d/rediseconomy/RedisEconomyPlugin.java index b3d4766..69a2225 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/RedisEconomyPlugin.java +++ b/src/main/java/dev/unnm3d/rediseconomy/RedisEconomyPlugin.java @@ -36,7 +36,6 @@ public final class RedisEconomyPlugin extends JavaPlugin { @Getter private static RedisEconomyPlugin instance; - //private EzRedisMessenger ezRedisMessenger; @Getter private ConfigManager configManager; @Getter @@ -73,6 +72,8 @@ public void onLoad() { @Override public void onEnable() { + if (redisManager == null) return; + this.scheduler = UniversalScheduler.getScheduler(this); this.configManager.postStartupLoad(); this.vaultPlugin = getServer().getPluginManager().getPlugin("Vault"); @@ -126,7 +127,8 @@ public void onEnable() { @Override public void onDisable() { - redisManager.close(); + if (redisManager != null) + redisManager.close(); if (currenciesManager != null) this.getServer().getServicesManager().unregister(Economy.class, currenciesManager.getDefaultCurrency()); this.getServer().getMessenger().unregisterOutgoingPluginChannel(this); @@ -145,16 +147,16 @@ private boolean setupRedis() { if (configManager.getSettings().redis.user().equals("changecredentials")) getLogger().warning("You are using default redis credentials. Please change them in the config.yml file!"); //Authentication params - redisURIBuilder = configManager.getSettings().redis.password().equals("") ? + redisURIBuilder = configManager.getSettings().redis.password().isEmpty() ? redisURIBuilder : - configManager.getSettings().redis.user().equals("") ? + configManager.getSettings().redis.user().isEmpty() ? redisURIBuilder.withPassword(configManager.getSettings().redis.password().toCharArray()) : redisURIBuilder.withAuthentication(configManager.getSettings().redis.user(), configManager.getSettings().redis.password()); getLogger().info("Connecting to redis server " + redisURIBuilder.build().toString() + "..."); this.redisManager = new RedisManager(RedisClient.create(redisURIBuilder.build())); redisManager.isConnected().get(1, java.util.concurrent.TimeUnit.SECONDS); - if (!configManager.getSettings().clusterId.equals("")) + if (!configManager.getSettings().clusterId.isEmpty()) RedisKeys.setClusterId(configManager.getSettings().clusterId); return true; } catch (Exception e) { From cbe46bdc2c394a98308b31e3b8862f52ab59215f Mon Sep 17 00:00:00 2001 From: Emibergo02 <36164338+Emibergo02@users.noreply.github.com> Date: Thu, 28 Mar 2024 20:21:36 +0100 Subject: [PATCH 06/25] max balance and save transactions --- pom.xml | 2 +- .../unnm3d/rediseconomy/config/Settings.java | 5 +- .../currency/CurrenciesManager.java | 2 +- .../rediseconomy/currency/Currency.java | 48 ++++++++++++++----- .../currency/CurrencyWithBanks.java | 10 ++-- .../transaction/EconomyExchange.java | 11 +++-- 6 files changed, 53 insertions(+), 25 deletions(-) diff --git a/pom.xml b/pom.xml index be2f964..b80d6ef 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ dev.unnm3d RedisEconomy - 4.3.9-SNAPSHOT + 4.3.10-SNAPSHOT jar RedisEconomy diff --git a/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java b/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java index 2856051..7a091f9 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java +++ b/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java @@ -39,11 +39,12 @@ public class Settings { @Comment("Minimum amount of money that can be paid") public double minPayAmount = 0.01; @Comment({"Currencies", "payTax is the tax on payments, 0.1 = 10% tax"}) - public List currencies = List.of(new CurrencySettings("vault", "euro", "euros", "#.##", "en-US", 0, 0, true, false), new CurrencySettings("dollar", "$", "$", "#.##", "en-US", 0, 0, false, false)); + public List currencies = List.of(new CurrencySettings("vault", "euro", "euros", "#.##", "en-US", 0, Double.POSITIVE_INFINITY, 0, true, true, false), new CurrencySettings("dollar", "$", "$", "#.##", "en-US", 0, Double.POSITIVE_INFINITY, 0, false, false, false)); public record CurrencySettings(String currencyName, String currencySingle, String currencyPlural, String decimalFormat, String languageTag, - double startingBalance, double payTax, boolean bankEnabled, boolean taxOnlyPay) { + double startingBalance, double maxBalance, double payTax, + boolean saveTransactions, boolean bankEnabled, boolean taxOnlyPay) { } public record RedisSettings(String host, int port, String user, String password, int database, int timeout, diff --git a/src/main/java/dev/unnm3d/rediseconomy/currency/CurrenciesManager.java b/src/main/java/dev/unnm3d/rediseconomy/currency/CurrenciesManager.java index 18640a0..3e78fc1 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/currency/CurrenciesManager.java +++ b/src/main/java/dev/unnm3d/rediseconomy/currency/CurrenciesManager.java @@ -70,7 +70,7 @@ public CurrenciesManager(RedisManager redisManager, RedisEconomyPlugin plugin, C currencies.put(currencySettings.currencyName(), currency); }); if (currencies.get(configManager.getSettings().defaultCurrencyName) == null) { - currencies.put(configManager.getSettings().defaultCurrencyName, new Currency(this, new Settings.CurrencySettings(configManager.getSettings().defaultCurrencyName, "€", "€", "#.##", "en-US", 0.0, 0.0, true, false))); + currencies.put(configManager.getSettings().defaultCurrencyName, new Currency(this, new Settings.CurrencySettings(configManager.getSettings().defaultCurrencyName, "€", "€", "#.##", "en-US", 0.0, Double.POSITIVE_INFINITY,0.0, true,true, false))); } registerPayMsgChannel(); registerBlockAccountChannel(); diff --git a/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java b/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java index 1170a00..ca7b3a9 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java +++ b/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java @@ -32,6 +32,7 @@ public class Currency implements Economy { @Getter protected final String currencyName; private final ConcurrentHashMap accounts; + private boolean enabled; @Getter private String currencySingular; @@ -40,7 +41,10 @@ public class Currency implements Economy { @Getter private final DecimalFormat decimalFormat; @Getter - private double startingBalance; + private final double startingBalance; + @Getter + private final double maxBalance; + private boolean saveTransactions; @Getter private double transactionTax; @Getter @@ -63,6 +67,8 @@ public Currency(CurrenciesManager currenciesManager, Settings.CurrencySettings c this.currencySingular = currencySettings.currencySingle(); this.currencyPlural = currencySettings.currencyPlural(); this.startingBalance = currencySettings.startingBalance(); + this.maxBalance = currencySettings.maxBalance() == 0.0d ? Double.POSITIVE_INFINITY : currencySettings.maxBalance(); + this.saveTransactions = currencySettings.saveTransactions(); this.transactionTax = currencySettings.payTax(); this.taxOnlyPay = currencySettings.taxOnlyPay(); this.accounts = new ConcurrentHashMap<>(); @@ -73,7 +79,7 @@ public Currency(CurrenciesManager currenciesManager, Settings.CurrencySettings c getOrderedAccounts(-1).thenApply(result -> { result.forEach(t -> accounts.put(UUID.fromString(t.getValue()), t.getScore())); - if (RedisEconomyPlugin.getInstance().settings().debug && accounts.size() > 0) { + if (RedisEconomyPlugin.getInstance().settings().debug && !accounts.isEmpty()) { Bukkit.getLogger().info("start1 Loaded " + accounts.size() + " accounts for currency " + currencyName); } return result; @@ -114,6 +120,14 @@ public boolean isEnabled() { return enabled; } + public boolean shouldSaveTransactions() { + return saveTransactions; + } + + public void setShouldSaveTransactions(boolean saveTransactions) { + this.saveTransactions = saveTransactions; + } + @Override public String getName() { return "RedisEconomy"; @@ -337,7 +351,7 @@ public boolean createPlayerAccount(@NotNull UUID playerUUID, @Nullable String pl if (hasAccount(playerUUID)) return false; updateAccount(playerUUID, playerName, startingBalance); - currenciesManager.getExchange().saveTransaction(new AccountID(playerUUID), new AccountID(), startingBalance, currencyName, "Account creation"); + currenciesManager.getExchange().saveTransaction(new AccountID(playerUUID), new AccountID(), startingBalance, this, "Account creation"); return true; } @@ -370,7 +384,7 @@ public EconomyResponse withdrawPlayer(@NotNull UUID playerUUID, @Nullable String return new EconomyResponse(amountToWithdraw, getBalance(playerUUID), EconomyResponse.ResponseType.FAILURE, "Insufficient funds"); updateAccount(playerUUID, playerName, getBalance(playerUUID) - amountToWithdraw); - currenciesManager.getExchange().saveTransaction(new AccountID(playerUUID), new AccountID(), -amountToWithdraw, currencyName, reason == null ? "Withdraw" : reason); + currenciesManager.getExchange().saveTransaction(new AccountID(playerUUID), new AccountID(), -amountToWithdraw, this, reason == null ? "Withdraw" : reason); return new EconomyResponse(amount, getBalance(playerUUID), EconomyResponse.ResponseType.SUCCESS, null); } @@ -391,10 +405,13 @@ public EconomyResponse payPlayer(@NotNull UUID sender, @NotNull UUID receiver, d if (!has(sender, amountToWithdraw)) return new EconomyResponse(0, getBalance(sender), EconomyResponse.ResponseType.FAILURE, "Insufficient funds"); + if (getBalance(receiver) + amount > maxBalance) + return new EconomyResponse(0, getBalance(receiver), EconomyResponse.ResponseType.FAILURE, "The receiver has reached the maximum balance"); + updateAccount(sender, senderName, getBalance(sender) - amountToWithdraw); - currenciesManager.getExchange().saveTransaction(new AccountID(sender), new AccountID(receiver), -amountToWithdraw, currencyName, reason == null ? "Payment" : reason); + currenciesManager.getExchange().saveTransaction(new AccountID(sender), new AccountID(receiver), -amountToWithdraw, this, reason == null ? "Payment" : reason); updateAccount(sender, receiverName, getBalance(receiver) + amount); - currenciesManager.getExchange().saveTransaction(new AccountID(receiver), new AccountID(sender), amount, currencyName, reason == null ? "Payment" : reason); + currenciesManager.getExchange().saveTransaction(new AccountID(receiver), new AccountID(sender), amount, this, reason == null ? "Payment" : reason); return new EconomyResponse(amount, getBalance(sender), EconomyResponse.ResponseType.SUCCESS, null); } @@ -414,7 +431,10 @@ public EconomyResponse payPlayer(@NotNull String senderName, @NotNull String rec return new EconomyResponse(0, 0, EconomyResponse.ResponseType.FAILURE, "Invalid decimal amount format"); if (!has(senderName, amountToWithdraw)) - return new EconomyResponse(0, getBalance(senderName), EconomyResponse.ResponseType.FAILURE, "Insufficient funds"); + return new EconomyResponse(0, getBalance(sender), EconomyResponse.ResponseType.FAILURE, "Insufficient funds"); + + if (getBalance(receiver) + amount > maxBalance) + return new EconomyResponse(0, getBalance(receiver), EconomyResponse.ResponseType.FAILURE, "The receiver has reached the maximum balance"); updateAccount(sender, senderName, getBalance(sender) - amountToWithdraw); updateAccount(receiver, receiverName, getBalance(receiver) + amount); @@ -445,8 +465,8 @@ public EconomyResponse setPlayerBalance(@NotNull UUID playerUUID, @Nullable Stri if (amount == Double.POSITIVE_INFINITY || amount == Double.NEGATIVE_INFINITY || Double.isNaN(amount)) return new EconomyResponse(0, 0, EconomyResponse.ResponseType.FAILURE, "Invalid decimal amount format"); updateAccount(playerUUID, playerName, amount); - currenciesManager.getExchange().saveTransaction(new AccountID(playerUUID), new AccountID(), -getBalance(playerUUID), currencyName, "Reset balance"); - currenciesManager.getExchange().saveTransaction(new AccountID(playerUUID), new AccountID(), amount, currencyName, "Set balance"); + currenciesManager.getExchange().saveTransaction(new AccountID(playerUUID), new AccountID(), -getBalance(playerUUID), this, "Reset balance"); + currenciesManager.getExchange().saveTransaction(new AccountID(playerUUID), new AccountID(), amount, this, "Set balance"); return new EconomyResponse(amount, getBalance(playerUUID), EconomyResponse.ResponseType.SUCCESS, null); } @@ -467,7 +487,7 @@ public CompletionStage revertTransaction(int transactionId, @NotNull Tr if (RedisEconomyPlugin.getInstance().settings().debug) { Bukkit.getLogger().info("revert01a reverted on account " + transaction.getAccountIdentifier() + " amount " + transaction.getAmount()); } - return currenciesManager.getExchange().saveTransaction(transaction.getAccountIdentifier(), transaction.getActor(), -transaction.getAmount(), currencyName, "Revert #" + transactionId + ": " + transaction.getReason()); + return currenciesManager.getExchange().saveTransaction(transaction.getAccountIdentifier(), transaction.getActor(), -transaction.getAmount(), this, "Revert #" + transactionId + ": " + transaction.getReason()); } /** @@ -498,8 +518,11 @@ public EconomyResponse depositPlayer(@NotNull UUID playerUUID, @Nullable String if (amount == Double.POSITIVE_INFINITY || amount == Double.NEGATIVE_INFINITY || Double.isNaN(amount)) return new EconomyResponse(0, 0, EconomyResponse.ResponseType.FAILURE, "Invalid decimal amount format"); + if (getBalance(playerUUID) + amount > maxBalance) + return new EconomyResponse(0, getBalance(playerUUID), EconomyResponse.ResponseType.FAILURE, "The player has reached the maximum balance"); + updateAccount(playerUUID, playerName, getBalance(playerUUID) + amount); - currenciesManager.getExchange().saveTransaction(new AccountID(playerUUID), new AccountID(), amount, currencyName, reason == null ? "Deposit" : reason); + currenciesManager.getExchange().saveTransaction(new AccountID(playerUUID), new AccountID(), amount, this, reason == null ? "Deposit" : reason); return new EconomyResponse(amount, getBalance(playerUUID), EconomyResponse.ResponseType.SUCCESS, null); } @@ -512,7 +535,6 @@ void updateAccountLocal(@NotNull UUID uuid, @Nullable String playerName, double protected void updateAccount(@NotNull UUID uuid, @Nullable String playerName, double balance) { updateAccountCloudCache(uuid, playerName, balance, 0); updateAccountLocal(uuid, playerName, balance); - } private synchronized void updateAccountCloudCache(@NotNull UUID uuid, @Nullable String playerName, double balance, int tries) { @@ -595,4 +617,6 @@ public CompletionStage getAccountRedis(UUID uuid) { public final Map getAccounts() { return Collections.unmodifiableMap(accounts); } + + } diff --git a/src/main/java/dev/unnm3d/rediseconomy/currency/CurrencyWithBanks.java b/src/main/java/dev/unnm3d/rediseconomy/currency/CurrencyWithBanks.java index 3dfaf99..214643f 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/currency/CurrencyWithBanks.java +++ b/src/main/java/dev/unnm3d/rediseconomy/currency/CurrencyWithBanks.java @@ -123,7 +123,7 @@ public EconomyResponse createBank(@NotNull String accountId, UUID playerOwner, S return new EconomyResponse(0, 0, EconomyResponse.ResponseType.FAILURE, "Bank account already exists"); setOwner(accountId, playerOwner); updateBankAccount(accountId, 0); - currenciesManager.getExchange().saveTransaction(new AccountID(accountId), new AccountID(playerOwner), 0, currencyName, reason); + currenciesManager.getExchange().saveTransaction(new AccountID(accountId), new AccountID(playerOwner), 0, this, reason); return new EconomyResponse(0, 0, EconomyResponse.ResponseType.SUCCESS, null); } @@ -146,7 +146,7 @@ public EconomyResponse deleteBank(@NotNull String accountId) { if (RedisEconomyPlugin.getInstance().settings().debug) { Bukkit.getLogger().info("Deleted bank account " + accountId + " with result " + result); } - currenciesManager.getExchange().saveTransaction(new AccountID(accountId), new AccountID(), 0, currencyName, "Bank account deletion"); + currenciesManager.getExchange().saveTransaction(new AccountID(accountId), new AccountID(), 0, this, "Bank account deletion"); }); return new EconomyResponse(0, 0, EconomyResponse.ResponseType.SUCCESS, null); } @@ -184,7 +184,7 @@ public EconomyResponse bankWithdraw(@NotNull String accountId, double amount, St return hasAmountResponse; } updateBankAccount(accountId, hasAmountResponse.balance);//Balance is the new balance with subtracted amount - currenciesManager.getExchange().saveTransaction(new AccountID(accountId), new AccountID(), -amount, currencyName, reason); + currenciesManager.getExchange().saveTransaction(new AccountID(accountId), new AccountID(), -amount, this, reason); return new EconomyResponse(amount, hasAmountResponse.balance, EconomyResponse.ResponseType.SUCCESS, null); } @@ -208,7 +208,7 @@ public EconomyResponse bankDeposit(@NotNull String accountId, double amount, Str } EconomyResponse balanceResponse = bankBalance(accountId); updateBankAccount(accountId, balanceResponse.balance + amount);//Balance is the new balance with subtracted amount - currenciesManager.getExchange().saveTransaction(new AccountID(accountId), new AccountID(), amount, currencyName, reason); + currenciesManager.getExchange().saveTransaction(new AccountID(accountId), new AccountID(), amount, this, reason); return new EconomyResponse(amount, balanceResponse.balance + amount, EconomyResponse.ResponseType.SUCCESS, null); } @@ -263,7 +263,7 @@ public CompletionStage revertTransaction(int transactionId, @NotNull Tr if (RedisEconomyPlugin.getInstance().settings().debug) { Bukkit.getLogger().info("revert01a reverted on account " + transaction.getAccountIdentifier() + " amount " + transaction.getAmount()); } - return currenciesManager.getExchange().saveTransaction(transaction.getAccountIdentifier(), transaction.getActor(), -transaction.getAmount(), currencyName, "Revert #" + transactionId + ": " + transaction.getReason()); + return currenciesManager.getExchange().saveTransaction(transaction.getAccountIdentifier(), transaction.getActor(), -transaction.getAmount(), this, "Revert #" + transactionId + ": " + transaction.getReason()); } private void setOwner(@NotNull String accountId, UUID ownerUUID) { diff --git a/src/main/java/dev/unnm3d/rediseconomy/transaction/EconomyExchange.java b/src/main/java/dev/unnm3d/rediseconomy/transaction/EconomyExchange.java index 1d16be1..e249caf 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/transaction/EconomyExchange.java +++ b/src/main/java/dev/unnm3d/rediseconomy/transaction/EconomyExchange.java @@ -88,6 +88,8 @@ public CompletionStage getTransaction(AccountID accountId, int id) * @return List of ids: the first one is the id of the transaction on the sender side, the second one is the id of the transaction on the target side */ public CompletionStage> savePaymentTransaction(@NotNull UUID sender, @NotNull UUID target, double amount, @NotNull Currency currency, @NotNull String reason) { + if (!currency.shouldSaveTransactions()) return CompletableFuture.completedStage(List.of(-1, -1)); + final CompletableFuture> future = new CompletableFuture<>(); long init = System.currentTimeMillis(); @@ -145,11 +147,12 @@ public CompletionStage> savePaymentTransaction(@NotNull UUID sende * @param accountOwner The id of the account, could be a UUID or a bank id (string) * @param target The id of the target account, could be a UUID or a bank id (string) * @param amount The amount of money transferred - * @param currencyName The name of the currency + * @param currency The currency of the transaction * @param reason The reason of the transaction * @return The transaction id */ - public CompletionStage saveTransaction(@NotNull AccountID accountOwner, @NotNull AccountID target, double amount, @NotNull String currencyName, @NotNull String reason) { + public CompletionStage saveTransaction(@NotNull AccountID accountOwner, @NotNull AccountID target, double amount, @NotNull Currency currency, @NotNull String reason) { + if (!currency.shouldSaveTransactions()) return CompletableFuture.completedStage(-1); final CompletableFuture future = new CompletableFuture<>(); long init = System.currentTimeMillis(); @@ -158,9 +161,9 @@ public CompletionStage saveTransaction(@NotNull AccountID accountOwner, accountOwner, System.currentTimeMillis(), target, //If target is null, it has been sent from the server - amount, currencyName, reason + getCallerPluginString(), null)); + amount, currency.getCurrencyName(), reason + getCallerPluginString(), null)); plugin.getScheduler().runTask(() -> plugin.getServer().getPluginManager().callEvent(transactionEvent)); - Long longResult=plugin.getCurrenciesManager().getRedisManager().getConnectionSync(commands -> commands.eval( + Long longResult = plugin.getCurrenciesManager().getRedisManager().getConnectionSync(commands -> commands.eval( "local currentId=redis.call('hlen', KEYS[1]);" + //Get the current size of the hash "redis.call('hset', KEYS[1], currentId, ARGV[1]);" + //Add the new transaction "return currentId;", //Return the id of the new transaction From 7130be9c950e030cbba1832542c386647d0a75dd Mon Sep 17 00:00:00 2001 From: Emibergo02 <36164338+Emibergo02@users.noreply.github.com> Date: Wed, 3 Apr 2024 11:37:56 +0200 Subject: [PATCH 07/25] 4.3.11 serverId retrieval from Bungeecord Placeholder renovated --- pom.xml | 2 +- .../rediseconomy/config/ConfigManager.java | 61 +------------- .../unnm3d/rediseconomy/config/Settings.java | 2 +- .../utils/PlaceholderAPIHook.java | 82 +++++++++++-------- 4 files changed, 54 insertions(+), 93 deletions(-) diff --git a/pom.xml b/pom.xml index b80d6ef..69f5c72 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ dev.unnm3d RedisEconomy - 4.3.10-SNAPSHOT + 4.3.11-SNAPSHOT jar RedisEconomy diff --git a/src/main/java/dev/unnm3d/rediseconomy/config/ConfigManager.java b/src/main/java/dev/unnm3d/rediseconomy/config/ConfigManager.java index e5dadd0..2e20c41 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/config/ConfigManager.java +++ b/src/main/java/dev/unnm3d/rediseconomy/config/ConfigManager.java @@ -1,21 +1,13 @@ package dev.unnm3d.rediseconomy.config; -import com.google.common.io.ByteArrayDataInput; -import com.google.common.io.ByteArrayDataOutput; -import com.google.common.io.ByteStreams; import de.exlll.configlib.YamlConfigurationProperties; import de.exlll.configlib.YamlConfigurations; import dev.unnm3d.rediseconomy.RedisEconomyPlugin; import lombok.Getter; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.HandlerList; -import org.bukkit.event.Listener; -import org.bukkit.plugin.messaging.ChannelNotRegisteredException; import java.io.File; import java.nio.charset.StandardCharsets; -import java.util.concurrent.CompletableFuture; +import java.util.UUID; public class ConfigManager { private final RedisEconomyPlugin plugin; @@ -44,10 +36,10 @@ public ConfigManager(RedisEconomyPlugin plugin) { public void postStartupLoad() { loadLangs(); - getServerId().thenAccept(s -> { - settings.serverId = s; + if (settings.serverId == null || settings.serverId.isEmpty()) { + settings.serverId = String.valueOf(UUID.randomUUID()); saveConfigs(); - }); + } } public void loadSettingsConfig() { @@ -77,49 +69,4 @@ public void loadLangs() { ); } - @SuppressWarnings("UnstableApiUsage") - public CompletableFuture getServerId() { - CompletableFuture future = new CompletableFuture<>(); - plugin.getServer().getMessenger().registerOutgoingPluginChannel(plugin, "BungeeCord"); - plugin.getServer().getMessenger().registerIncomingPluginChannel(plugin, "BungeeCord", (channel, player, message) -> { - if (future.isDone()) return; - ByteArrayDataInput in = ByteStreams.newDataInput(message); - String subchannel = in.readUTF(); - if (subchannel.equals("GetServer")) { - future.complete(in.readUTF());//Receive server name - } - }); - Listener listener = new Listener() { - @EventHandler - public void onJoin(org.bukkit.event.player.PlayerJoinEvent event) { - if (future.isDone()) { - return; - } - plugin.getScheduler().runTaskLaterAsynchronously(() -> sendServerIdRequest(event.getPlayer()), 20L); - } - }; - if (!plugin.getServer().getOnlinePlayers().isEmpty()) { - try { - sendServerIdRequest(plugin.getServer().getOnlinePlayers().iterator().next()); - } catch (ChannelNotRegisteredException ignored) { - } - } else { - plugin.getServer().getPluginManager().registerEvents(listener, plugin); - } - return future.thenApply(s -> { - //Remove listener and channel listeners - HandlerList.unregisterAll(listener); - plugin.getServer().getMessenger().unregisterIncomingPluginChannel(plugin, "BungeeCord"); - plugin.getServer().getMessenger().unregisterOutgoingPluginChannel(plugin, "BungeeCord"); - return s; - }); - } - - @SuppressWarnings("UnstableApiUsage") - private void sendServerIdRequest(Player p) throws ChannelNotRegisteredException { - ByteArrayDataOutput out = ByteStreams.newDataOutput(); - out.writeUTF("GetServer"); - p.sendPluginMessage(plugin, "BungeeCord", out.toByteArray());//Request server name - } - } diff --git a/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java b/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java index 7a091f9..bef8cbc 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java +++ b/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java @@ -10,7 +10,7 @@ @Configuration public class Settings { @Comment({"This is automatically generated on server startup", - "Change it only if you have disabled plugin messages on the proxy"}) + "You need to have a different serverId for each server!!!"}) public String serverId = String.valueOf(UUID.randomUUID()); @Comment("Language file") public String lang = "en-US"; diff --git a/src/main/java/dev/unnm3d/rediseconomy/utils/PlaceholderAPIHook.java b/src/main/java/dev/unnm3d/rediseconomy/utils/PlaceholderAPIHook.java index e12ce45..01744d2 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/utils/PlaceholderAPIHook.java +++ b/src/main/java/dev/unnm3d/rediseconomy/utils/PlaceholderAPIHook.java @@ -10,6 +10,7 @@ import org.bukkit.plugin.RegisteredServiceProvider; import org.jetbrains.annotations.NotNull; +import java.text.DecimalFormat; import java.util.*; @@ -109,43 +110,47 @@ public String onRequest(OfflinePlayer player, String params) { updatePlaceholdersCache(); - if (splitted.get(0).equals("totsupply")) { - - return parseParams(totalSupplyCache.get(currency), splitted, currency); - } else if (splitted.get(0).equals("top")) { - + switch (splitted.get(0)) { + case "totsupply" -> { + return parseParams(totalSupplyCache.get(currency), splitted, currency); + } + case "maxbal" -> { + return String.valueOf(currency.getMaxBalance()); + } + case "top" -> { - if (splitted.size() < 3) return null; //Insufficient parameters + if (splitted.size() < 3) return null; //Insufficient parameters - List user_balance_strings = baltopCache.get(currency); - if (user_balance_strings == null) return null; + List user_balance_strings = baltopCache.get(currency); + if (user_balance_strings == null) return null; - if (splitted.get(1).equals("position")) {//rediseco_top_position_ - for (int i = 0; i < user_balance_strings.size(); i++) { - if (user_balance_strings.get(i)[2].equals(player.getName())) { - return String.valueOf(i + 1); + if (splitted.get(1).equals("position")) {//rediseco_top_position_ + for (int i = 0; i < user_balance_strings.size(); i++) { + if (user_balance_strings.get(i)[2].equals(player.getName())) { + return String.valueOf(i + 1); + } } + return "10+"; } - return "10+"; - } - int position = Integer.parseInt(splitted.get(1)); - if (position < 1 || position > 10) return "N/A"; //Invalid positions - if (user_balance_strings.size() < position) return "N/A"; + int position = Integer.parseInt(splitted.get(1)); + if (position < 1 || position > 10) return "N/A"; //Invalid positions + if (user_balance_strings.size() < position) return "N/A"; - switch (splitted.get(2)) { - case "playerprefix" -> { - return user_balance_strings.get(position - 1)[0]; - } - case "playersuffix" -> { - return user_balance_strings.get(position - 1)[1]; - } - case "name" -> { - return user_balance_strings.get(position - 1)[2]; - } - case "bal" -> { - double balance = Double.parseDouble(user_balance_strings.get(position - 1)[3]); - return parseParams(balance, splitted, currency); + switch (splitted.get(2)) { + case "playerprefix" -> { + return user_balance_strings.get(position - 1)[0]; + } + case "playersuffix" -> { + return user_balance_strings.get(position - 1)[1]; + } + case "name" -> { + return user_balance_strings.get(position - 1)[2]; + } + case "bal" -> { + double balance = Double.parseDouble(user_balance_strings.get(position - 1)[3]); + return parseParams(balance, splitted, currency); + } } } } @@ -158,15 +163,24 @@ private String parseParams(double amount, List splitted, Currency curren if (splitted.contains("short")) { if (amount >= 1000000000000.0) { - formattedNumber = currency.format(amount / 1000000000000.0) + langs.unitSymbols.trillion(); + formattedNumber = currency.getDecimalFormat().format(amount / 1000000000000.0) + langs.unitSymbols.trillion(); } else if (amount >= 1000000000.0) { - formattedNumber = currency.format(amount / 1000000000.0) + langs.unitSymbols.billion(); + formattedNumber = currency.getDecimalFormat().format(amount / 1000000000.0) + langs.unitSymbols.billion(); } else if (amount >= 1000000.0) { - formattedNumber = currency.format(amount / 1000000.0) + langs.unitSymbols.million(); + formattedNumber = currency.getDecimalFormat().format(amount / 1000000.0) + langs.unitSymbols.million(); } else if (amount >= 1000.0) { - formattedNumber = currency.format(amount / 1000.0) + langs.unitSymbols.thousand(); + formattedNumber = currency.getDecimalFormat().format(amount / 1000.0) + langs.unitSymbols.thousand(); } } + + formattedNumber = splitted.stream() + .filter(s -> s.startsWith("decformat")) + .findFirst() + .map(s -> s.split("decformat")) + .filter(splittedFormat -> splittedFormat.length > 1) + .map(splittedFormat -> new DecimalFormat(splittedFormat[1]).format(amount)) + .orElse(formattedNumber); + if (splitted.contains("formatted")) { if (amount == 1) formattedNumber += currency.getCurrencySingular(); From 3ac6bb904971b4fcf755e82b9fe64801dcc45329 Mon Sep 17 00:00:00 2001 From: Emibergo02 <36164338+Emibergo02@users.noreply.github.com> Date: Sun, 5 May 2024 12:42:51 +0200 Subject: [PATCH 08/25] 4.3.12 New german language file New command /pay * to send money to all players on your server (you need rediseconomy.payall) --- pom.xml | 4 +- .../rediseconomy/command/PayCommand.java | 60 +++++++++++++++-- .../BrowseTransactionsCommand.java | 2 - .../rediseconomy/config/ConfigManager.java | 3 +- .../rediseconomy/currency/Currency.java | 7 +- src/main/resources/de-DE.yml | 66 +++++++++++++++++++ src/main/resources/plugin.yml | 9 ++- 7 files changed, 137 insertions(+), 14 deletions(-) create mode 100644 src/main/resources/de-DE.yml diff --git a/pom.xml b/pom.xml index 69f5c72..0278103 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ dev.unnm3d RedisEconomy - 4.3.11-SNAPSHOT + 4.3.12 jar RedisEconomy @@ -131,7 +131,7 @@ org.projectlombok lombok - 1.18.30 + 1.18.32 provided diff --git a/src/main/java/dev/unnm3d/rediseconomy/command/PayCommand.java b/src/main/java/dev/unnm3d/rediseconomy/command/PayCommand.java index 5bbbe48..e8094d0 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/command/PayCommand.java +++ b/src/main/java/dev/unnm3d/rediseconomy/command/PayCommand.java @@ -78,6 +78,13 @@ private void payCurrency(Player sender, Currency currency, String[] args) { if (target.equalsIgnoreCase(sender.getName())) { plugin.langs().send(sender, plugin.langs().paySelf); return; + } else if (target.equals("*")) { + if (sender.hasPermission("rediseconomy.payall")) { + payCurrencyAll(sender, currency, amount); + } else { + plugin.langs().send(sender, plugin.langs().noPermission); + } + return; } if (!currency.hasAccount(target)) { plugin.langs().send(sender, plugin.langs().playerNotFound); @@ -121,7 +128,48 @@ private void payCurrency(Player sender, Currency currency, String[] args) { } return currenciesManager.getExchange().savePaymentTransaction(sender.getUniqueId(), targetUUID, amount, currency, reason); }); + } + /** + * Pay to all online players + * + * @param sender Player who sends the payment + * @param currency Currency to pay + * @param amount Amount to pay + */ + private void payCurrencyAll(Player sender, Currency currency, double amount) { + for (Player onlinePlayer : plugin.getServer().getOnlinePlayers()) { + if (onlinePlayer.getName().equals(sender.getName())) continue; + + if (currenciesManager.isAccountLocked(onlinePlayer.getUniqueId(), sender.getUniqueId())) { + plugin.langs().send(sender, plugin.langs().blockedPayment.replace("%player%", onlinePlayer.getName())); + continue; + } + + final EconomyResponse response = currency.payPlayer(sender.getName(), onlinePlayer.getName(), amount); + if (!response.transactionSuccess()) { + if (response.errorMessage.equals("Insufficient funds")) { + plugin.langs().send(sender, plugin.langs().insufficientFunds); + } else { + plugin.langs().send(sender, plugin.langs().payFail); + } + return; + } + //Send msg to sender + plugin.langs().send(sender, + plugin.langs().paySuccess + .replace("%amount%", currency.format(amount)) + .replace("%player%", onlinePlayer.getName()) + .replace("%tax_percentage%", (currency.getTransactionTax() * 100) + "%") + .replace("%tax_applied%", currency.format(currency.getTransactionTax() * amount)) + ); + //Send msg to target + currenciesManager.getRedisManager().getConnectionAsync(commands -> { + commands.publish(MSG_CHANNEL.toString(), sender.getName() + ";;" + onlinePlayer.getName() + ";;" + currency.format(amount)); + //Register transaction + return currenciesManager.getExchange().savePaymentTransaction(sender.getUniqueId(), onlinePlayer.getUniqueId(), amount, currency, "Payment to all online players"); + }); + } } @Override @@ -129,12 +177,14 @@ private void payCurrency(Player sender, Currency currency, String[] args) { if (args.length == 1) { if (args[0].length() < plugin.settings().tab_complete_chars) return List.of(); - return currenciesManager.getNameUniqueIds().keySet().stream().filter(name -> name.toUpperCase().startsWith(args[0].toUpperCase())).toList(); - } else if (args.length == 2) - return List.of("69"); - else if (args.length == 3) + return currenciesManager.getNameUniqueIds().keySet().stream() + .filter(name -> name.toUpperCase().startsWith(args[0].toUpperCase())) + .toList(); + } else if (args.length == 2) { + return List.of("1"); + } else if (args.length == 3) { return currenciesManager.getCurrencies().stream().map(Currency::getCurrencyName).filter(name -> name.startsWith(args[2]) && sender.hasPermission("rediseconomy.pay." + args[2])).toList(); - + } return List.of(); } diff --git a/src/main/java/dev/unnm3d/rediseconomy/command/transaction/BrowseTransactionsCommand.java b/src/main/java/dev/unnm3d/rediseconomy/command/transaction/BrowseTransactionsCommand.java index f4ed64d..6dd22f5 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/command/transaction/BrowseTransactionsCommand.java +++ b/src/main/java/dev/unnm3d/rediseconomy/command/transaction/BrowseTransactionsCommand.java @@ -63,8 +63,6 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command sendTransaction(sender, i, transactions.get(i), afterDateString + " " + beforeDateString); - if (plugin.settings().debug) - sender.sendMessage("Time: " + (System.currentTimeMillis() - init)); } plugin.langs().send(sender, plugin.langs().transactionsEnd diff --git a/src/main/java/dev/unnm3d/rediseconomy/config/ConfigManager.java b/src/main/java/dev/unnm3d/rediseconomy/config/ConfigManager.java index 2e20c41..6877b3e 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/config/ConfigManager.java +++ b/src/main/java/dev/unnm3d/rediseconomy/config/ConfigManager.java @@ -60,7 +60,8 @@ public void saveConfigs() { public void loadLangs() { File settingsFile = new File(plugin.getDataFolder(), settings.lang + ".yml"); if (!settingsFile.exists()) { - plugin.saveResource("it-IT.yml", false);//save default lang + plugin.saveResource("it-IT.yml", false); + plugin.saveResource("de-DE.yml", false); } langs = YamlConfigurations.update( settingsFile.toPath(), diff --git a/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java b/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java index ca7b3a9..a7b9310 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java +++ b/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java @@ -421,8 +421,11 @@ public EconomyResponse payPlayer(@NotNull String senderName, @NotNull String rec return new EconomyResponse(amount, getBalance(senderName), EconomyResponse.ResponseType.FAILURE, "Account not found"); if (!hasAccount(receiverName)) return new EconomyResponse(amount, getBalance(receiverName), EconomyResponse.ResponseType.FAILURE, "Account not found"); - UUID sender = currenciesManager.getUUIDFromUsernameCache(senderName); - UUID receiver = currenciesManager.getUUIDFromUsernameCache(receiverName); + + final UUID sender = currenciesManager.getUUIDFromUsernameCache(senderName); + final UUID receiver = currenciesManager.getUUIDFromUsernameCache(receiverName); + + //Calculate the amount to withdraw with the transaction tax double amountToWithdraw = amount + (amount * transactionTax); if (sender == null || receiver == null) return new EconomyResponse(amount, getBalance(senderName), EconomyResponse.ResponseType.FAILURE, "Account not found"); diff --git a/src/main/resources/de-DE.yml b/src/main/resources/de-DE.yml new file mode 100644 index 0000000..3173812 --- /dev/null +++ b/src/main/resources/de-DE.yml @@ -0,0 +1,66 @@ +noConsole: Der Befehl muss inGame eingegeben werden! +noPermission: Du hast keine berechtigung, den Befehl zu nutzen! +missingArguments: Zu wenig! Argumente +playerNotFound: Spieler nicht gefunden! +invalidAmount: Ungültiger Betrag! +tooSmallAmount: Der Betrag ist zu klein! +payCooldown: Deine vorherige Zahlung ist noch in Bearbeitung! Bitte warten +invalidCurrency: Ungültige Währung! +insufficientFunds: Du hast nicht genügend Geld! +balance: Du hast %balance%! +balanceSet: Du hast das Geld von %player% auf %balance% gesetzt! +balanceOther: %player% hat %balance% ! +balanceTop: Die reichsten Spieler:
%prevpage% %page% %nextpage% +blockedAccounts: Gesperrte Accounts:
%list% +blockedAccountSuccess: Account %player% ist gesperrt! +unblockedAccountSuccess: Account %player% wurde entsperrt! +blockedPayment: Deine Zahlung an %player% wurde gesperrt! +balanceTopFormat: %pos% - %player% %balance% +paySelf: Du kannst nichts an dich selbst zahlen! +# Use %tax_percentage% for tax percentage and %tax_applied% for tax applied to the transaction. +paySuccess: Du hast %player% %amount% gezahlt +payFail: Zahlung fehlgeschlagen! +payReceived: Du hast %amount% from %player%! +purgeUserSuccess: %player% wurde gelöscht! +purgeBalanceSuccess: Die Währung von %player% wurde auf %currency% zurückgesetzt! +switchCurrencySuccess: %currency% zu %switch-currency%. gewechselt
Bitte + starten Sie jeden Server mit
installiertem RedisEconomy neu, um ein Überschreiben + zu vermeiden!
+noTransactionFound: Keine Transaktion von %player% gefunden! +incorrectDate: Falsches Datumsformat ! +transactionsStart: Transactionen von Spieler %player% von %after% bis %before%! +transactionsEnd: Die Prüfung von %player%'s Transactionen dauerte %time% + ms +transactionsArchiveCompleted: Archiviere %size% Transactiosdaten nach %file% +transactionsArchiveProgress: 'Archivierungsstatus: %progress%% ' +editMessageError: Dieser Config-Eintrag ist keine Zeichenfolge oder existiert + nicht! +editMessageClickHere: Klicke hier um die Nachricht zu bearbeiten + %field%! +editMessageSuccess: Erfolgreich gespeichert %field%! +transactionItem: + outgoingFunds: '#%id% Click + to copy:
%timestamp%">[Timestamp⌛] + [←Revert]
%account-owner% + > %amount%%symbol% > %other-account%
Reason: + %reason%' + incomingFunds: '#%id% Click + to copy:
%timestamp%">[Timestamp⌛] + [←Revert]
%other-account% > %amount%%symbol% + > %account-owner%
Reason: + %reason%' +unitSymbols: + thousand: k + million: m + billion: b + trillion: t + quadrillion: q +backupRestoreFinished: Backup/restore der Datei %file% beendet! +invalidPath: Ungültiger Pfad! + +# Authors: Unnm3d diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index a31a8c1..89d0239 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -73,6 +73,9 @@ permissions: rediseconomy.pay: description: Allows to use /pay default: true + rediseconomy.payall: + description: Allows to use /pay * + default: false rediseconomy.toggle-payments: description: Allows to use /toggle-payments default: true @@ -107,8 +110,10 @@ permissions: description: Allows to use /transaction default: false rediseconomy.pay.*: - description: Allows to use /pay all currencies - default: op + description: Allows to use /pay all currencies + default: op + children: + rediseconomy.payall: true rediseconomy.balance.*: description: Allows to use /balance with other currencies default: op From 86dc411c98009259890bc40bafdb6bfc0cd2b4cb Mon Sep 17 00:00:00 2001 From: Emibergo02 <36164338+Emibergo02@users.noreply.github.com> Date: Wed, 8 May 2024 00:30:16 +0200 Subject: [PATCH 09/25] 4.3.13 Percentage payments are now possible everywhere! with /pay username 10% you will pay 'username' 10% of your balance. (This feature is optional, check config.yml) --- pom.xml | 2 +- .../rediseconomy/command/PayCommand.java | 2 +- .../command/balance/BalanceCommand.java | 4 +-- .../dev/unnm3d/rediseconomy/config/Langs.java | 32 ++++++++----------- .../unnm3d/rediseconomy/config/Settings.java | 2 ++ .../currency/CurrenciesManager.java | 31 +++++++++++++++++- 6 files changed, 49 insertions(+), 24 deletions(-) diff --git a/pom.xml b/pom.xml index 0278103..10b8a50 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ dev.unnm3d RedisEconomy - 4.3.12 + 4.3.13 jar RedisEconomy diff --git a/src/main/java/dev/unnm3d/rediseconomy/command/PayCommand.java b/src/main/java/dev/unnm3d/rediseconomy/command/PayCommand.java index e8094d0..e8ac73a 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/command/PayCommand.java +++ b/src/main/java/dev/unnm3d/rediseconomy/command/PayCommand.java @@ -66,7 +66,7 @@ private void payCurrency(Player sender, Currency currency, String[] args) { } long init = System.currentTimeMillis(); final String target = args[0]; - final double amount = plugin.langs().formatAmountString(args[1]); + final double amount = currenciesManager.formatAmountString(sender.getName(), currency, args[1]); if (amount <= 0) { plugin.langs().send(sender, plugin.langs().invalidAmount); return; diff --git a/src/main/java/dev/unnm3d/rediseconomy/command/balance/BalanceCommand.java b/src/main/java/dev/unnm3d/rediseconomy/command/balance/BalanceCommand.java index 796438b..9ff8773 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/command/balance/BalanceCommand.java +++ b/src/main/java/dev/unnm3d/rediseconomy/command/balance/BalanceCommand.java @@ -36,7 +36,7 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command selfBalancePlayer(sender, defaultCurrency); return true; } - String target = economy.getCaseSensitiveName(args[0]); + final String target = economy.getCaseSensitiveName(args[0]); if (args.length == 1) { balancePlayer(sender, defaultCurrency, target); } else if (args.length == 2) { @@ -62,7 +62,7 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command plugin.langs().send(sender, plugin.langs().invalidCurrency); return true; } - double amount = plugin.langs().formatAmountString(args[3]); + double amount = plugin.getCurrenciesManager().formatAmountString(target, currency, args[3]); if (amount < 0) { plugin.langs().send(sender, plugin.langs().invalidAmount); return true; diff --git a/src/main/java/dev/unnm3d/rediseconomy/config/Langs.java b/src/main/java/dev/unnm3d/rediseconomy/config/Langs.java index c314284..e054bdc 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/config/Langs.java +++ b/src/main/java/dev/unnm3d/rediseconomy/config/Langs.java @@ -9,6 +9,8 @@ import org.jetbrains.annotations.Nullable; import java.lang.reflect.Field; +import java.util.NavigableMap; +import java.util.TreeMap; @Configuration public final class Langs { @@ -75,27 +77,19 @@ public record UnitSymbols( ) { } - public void send(CommandSender sender, String text) { - audiences.sender(sender).sendMessage(MiniMessage.miniMessage().deserialize(text)); + public NavigableMap getSuffixes() { + return new TreeMap<>() {{ + put(unitSymbols.thousand(), 1_000L); + put(unitSymbols.million(), 1_000_000L); + put(unitSymbols.billion(), 1_000_000_000L); + put(unitSymbols.trillion(), 1_000_000_000_000L); + put(unitSymbols.quadrillion(), 1_000_000_000_000_000L); + }}; + } - public double formatAmountString(String amount) { - try { - if (amount.endsWith(unitSymbols.quadrillion())) { - return Double.parseDouble(amount.substring(0, amount.length() - unitSymbols.quadrillion().length())) * 1_000_000_000_000_000D; - } else if (amount.endsWith(unitSymbols.trillion())) { - return Double.parseDouble(amount.substring(0, amount.length() - unitSymbols.trillion().length())) * 1_000_000_000_000D; - } else if (amount.endsWith(unitSymbols.billion())) { - return Double.parseDouble(amount.substring(0, amount.length() - unitSymbols.billion().length())) * 1_000_000_000D; - } else if (amount.endsWith(unitSymbols.million())) { - return Double.parseDouble(amount.substring(0, amount.length() - unitSymbols.million().length())) * 1_000_000D; - } else if (amount.endsWith(unitSymbols.thousand())) { - return Double.parseDouble(amount.substring(0, amount.length() - unitSymbols.thousand().length())) * 1_000D; - } - return Double.parseDouble(amount); - } catch (NumberFormatException e) { - return -1; - } + public void send(CommandSender sender, String text) { + audiences.sender(sender).sendMessage(MiniMessage.miniMessage().deserialize(text)); } public @Nullable Field getStringField(String name) throws NoSuchFieldException { diff --git a/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java b/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java index bef8cbc..f94c7c1 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java +++ b/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java @@ -23,6 +23,8 @@ public class Settings { @Comment({"if true, migrates the bukkit offline uuids accounts to the default RedisEconomy currency", "During the migration, the plugin will be disabled. Restart all RedisEconomy instances after the migration."}) public boolean migrationEnabled = false; + @Comment("Allow paying with percentage (ex: /pay player 10% sends 'player' 10% of the sender balance)") + public boolean allowPercentagePayments = true; @Comment({"Leave password or user empty if you don't have a password or user", "Don't use the default credentials in production!! Generate new credentials on RedisLabs -> https://github.com/Emibergo02/RedisEconomy/wiki/Install-redis", "Default credentials lead to a non-persistent redis server, only for testing!!", diff --git a/src/main/java/dev/unnm3d/rediseconomy/currency/CurrenciesManager.java b/src/main/java/dev/unnm3d/rediseconomy/currency/CurrenciesManager.java index 3e78fc1..1354d8a 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/currency/CurrenciesManager.java +++ b/src/main/java/dev/unnm3d/rediseconomy/currency/CurrenciesManager.java @@ -70,7 +70,7 @@ public CurrenciesManager(RedisManager redisManager, RedisEconomyPlugin plugin, C currencies.put(currencySettings.currencyName(), currency); }); if (currencies.get(configManager.getSettings().defaultCurrencyName) == null) { - currencies.put(configManager.getSettings().defaultCurrencyName, new Currency(this, new Settings.CurrencySettings(configManager.getSettings().defaultCurrencyName, "€", "€", "#.##", "en-US", 0.0, Double.POSITIVE_INFINITY,0.0, true,true, false))); + currencies.put(configManager.getSettings().defaultCurrencyName, new Currency(this, new Settings.CurrencySettings(configManager.getSettings().defaultCurrencyName, "€", "€", "#.##", "en-US", 0.0, Double.POSITIVE_INFINITY, 0.0, true, true, false))); } registerPayMsgChannel(); registerBlockAccountChannel(); @@ -415,6 +415,35 @@ public boolean isAccountLocked(UUID uuid, UUID target) { getLockedAccounts(uuid).contains(RedisKeys.getAllAccountUUID()); } + /** + * Formats the amount string to a double + * Parses suffixes (10k, 10M for 10 thousand and 10 million) + * Parses percentages ("10%" for 10% of the accountOwner balance) + * + * @param targetName The account that has to be modified + * @param currency the currency to format the amount + * @param amount the amount to format + * @return the formatted amount + */ + public double formatAmountString(String targetName, Currency currency, String amount) { + try { + //Check if last char of amount is number + if (Character.isDigit(amount.charAt(amount.length() - 1))) { + return Double.parseDouble(amount); + } + double parsedAmount = Double.parseDouble(amount.substring(0, amount.length() - 1)); + return amount.endsWith("%") && plugin.settings().allowPercentagePayments ? + //Percentage 20% + parsedAmount / 100 * currency.getBalance(targetName) : + //Parse suffixes from map + parsedAmount * plugin.langs().getSuffixes() + .getOrDefault(amount.substring(amount.length() - 1), -1L); + } catch (NumberFormatException e) { + plugin.langs().send(Bukkit.getConsoleSender(), plugin.langs().invalidAmount); + } + return -1; + } + public List getLockedAccounts(UUID uuid) { return lockedAccounts.getOrDefault(uuid, new ArrayList<>()); } From f7ae0e03de06622135f7ab5618be2bd00b110133 Mon Sep 17 00:00:00 2001 From: Emibergo02 <36164338+Emibergo02@users.noreply.github.com> Date: Thu, 9 May 2024 18:43:05 +0200 Subject: [PATCH 10/25] 4.3.14 Got rid of the serverId UUID. Now it is randomly generated and NOT configurable. Placeholder update time changed to 5 seconds --- .../dev/unnm3d/rediseconomy/RedisEconomyPlugin.java | 7 ++++++- .../dev/unnm3d/rediseconomy/command/MainCommand.java | 6 ++---- .../unnm3d/rediseconomy/config/ConfigManager.java | 10 ---------- .../dev/unnm3d/rediseconomy/currency/Currency.java | 4 ++-- .../rediseconomy/currency/CurrencyWithBanks.java | 12 ++++++------ .../rediseconomy/utils/PlaceholderAPIHook.java | 2 +- 6 files changed, 17 insertions(+), 24 deletions(-) diff --git a/src/main/java/dev/unnm3d/rediseconomy/RedisEconomyPlugin.java b/src/main/java/dev/unnm3d/rediseconomy/RedisEconomyPlugin.java index 69a2225..f03a77e 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/RedisEconomyPlugin.java +++ b/src/main/java/dev/unnm3d/rediseconomy/RedisEconomyPlugin.java @@ -30,6 +30,7 @@ import org.bukkit.plugin.java.JavaPlugin; import java.time.Duration; +import java.util.UUID; import java.util.concurrent.TimeUnit; public final class RedisEconomyPlugin extends JavaPlugin { @@ -45,6 +46,8 @@ public final class RedisEconomyPlugin extends JavaPlugin { private TaskScheduler scheduler; @Getter private Plugin vaultPlugin; + @Getter + private static UUID instanceUUID; public Settings settings() { @@ -58,6 +61,8 @@ public Langs langs() { @Override public void onLoad() { instance = this; + //Generate a unique instance id to not send redis updates to itself + instanceUUID = UUID.randomUUID(); this.configManager = new ConfigManager(this); @@ -75,7 +80,7 @@ public void onEnable() { if (redisManager == null) return; this.scheduler = UniversalScheduler.getScheduler(this); - this.configManager.postStartupLoad(); + this.configManager.loadLangs(); this.vaultPlugin = getServer().getPluginManager().getPlugin("Vault"); if (this.vaultPlugin == null) { //creates currenciesManager and exchange this.getLogger().severe("Disabled due to no Vault dependency found!"); diff --git a/src/main/java/dev/unnm3d/rediseconomy/command/MainCommand.java b/src/main/java/dev/unnm3d/rediseconomy/command/MainCommand.java index 2e143ba..359c155 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/command/MainCommand.java +++ b/src/main/java/dev/unnm3d/rediseconomy/command/MainCommand.java @@ -27,13 +27,11 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command } else if (args.length == 1) { if (!args[0].equalsIgnoreCase("reload")) return true; if (!sender.hasPermission("rediseconomy.admin")) return true; - String serverId = plugin.getConfigManager().getSettings().serverId; //Keep serverId plugin.getConfigManager().loadSettingsConfig();//Reload configs - plugin.getConfigManager().loadLangs(); - plugin.getConfigManager().getSettings().serverId = serverId; //Restore serverId + plugin.getConfigManager().loadLangs(); //Reload langs plugin.getConfigManager().saveConfigs(); //Save configs this.adventureWebuiEditorAPI = new AdventureWebuiEditorAPI(plugin.getConfigManager().getSettings().webEditorUrl); - sender.sendMessage("§aReloaded successfully " + plugin.getConfigManager().getSettings().serverId + "!"); + sender.sendMessage("§aReloaded successfully!"); return true; } String langField = args[1]; diff --git a/src/main/java/dev/unnm3d/rediseconomy/config/ConfigManager.java b/src/main/java/dev/unnm3d/rediseconomy/config/ConfigManager.java index 6877b3e..4f0e256 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/config/ConfigManager.java +++ b/src/main/java/dev/unnm3d/rediseconomy/config/ConfigManager.java @@ -7,7 +7,6 @@ import java.io.File; import java.nio.charset.StandardCharsets; -import java.util.UUID; public class ConfigManager { private final RedisEconomyPlugin plugin; @@ -34,16 +33,7 @@ public ConfigManager(RedisEconomyPlugin plugin) { loadSettingsConfig(); } - public void postStartupLoad() { - loadLangs(); - if (settings.serverId == null || settings.serverId.isEmpty()) { - settings.serverId = String.valueOf(UUID.randomUUID()); - saveConfigs(); - } - } - public void loadSettingsConfig() { - File settingsFile = new File(plugin.getDataFolder(), "config.yml"); settings = YamlConfigurations.update( settingsFile.toPath(), diff --git a/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java b/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java index a7b9310..705b00e 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java +++ b/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java @@ -99,7 +99,7 @@ public void message(String channel, String message) { Bukkit.getLogger().severe("Invalid message received from RedisEco channel, consider updating RedisEconomy"); return; } - if (split[0].equals(RedisEconomyPlugin.getInstance().settings().serverId)) return; + if (split[0].equals(RedisEconomyPlugin.getInstanceUUID().toString())) return; UUID uuid = UUID.fromString(split[1]); String playerName = split[2]; double balance = Double.parseDouble(split[3]); @@ -547,7 +547,7 @@ private synchronized void updateAccountCloudCache(@NotNull UUID uuid, @Nullable if (playerName != null) reactiveCommands.hset(NAME_UUID.toString(), playerName, uuid.toString()); reactiveCommands.publish(UPDATE_PLAYER_CHANNEL_PREFIX + currencyName, - RedisEconomyPlugin.getInstance().settings().serverId + ";;" + uuid + ";;" + playerName + ";;" + balance); + RedisEconomyPlugin.getInstanceUUID().toString() + ";;" + uuid + ";;" + playerName + ";;" + balance); }).ifPresentOrElse(result -> { if (RedisEconomyPlugin.getInstance().settings().debug) { diff --git a/src/main/java/dev/unnm3d/rediseconomy/currency/CurrencyWithBanks.java b/src/main/java/dev/unnm3d/rediseconomy/currency/CurrencyWithBanks.java index 214643f..445e4ca 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/currency/CurrencyWithBanks.java +++ b/src/main/java/dev/unnm3d/rediseconomy/currency/CurrencyWithBanks.java @@ -34,14 +34,14 @@ public CurrencyWithBanks(CurrenciesManager currenciesManager, Settings.CurrencyS for (ScoredValue scoredValue : list) { bankAccounts.put(scoredValue.getValue(), scoredValue.getScore()); } - if (RedisEconomyPlugin.getInstance().settings().debug && bankAccounts.size() > 0) { + if (RedisEconomyPlugin.getInstance().settings().debug && !bankAccounts.isEmpty()) { Bukkit.getLogger().info("start1bank Loaded " + bankAccounts.size() + " accounts for currency " + currencyName); } return list; }).toCompletableFuture().join(); getRedisBankOwners().thenApply(map -> { map.forEach((k, v) -> bankOwners.put(k, UUID.fromString(v))); - if (RedisEconomyPlugin.getInstance().settings().debug && bankOwners.size() > 0) { + if (RedisEconomyPlugin.getInstance().settings().debug && !bankOwners.isEmpty()) { Bukkit.getLogger().info("start1bankb Loaded " + bankOwners.size() + " accounts owners for currency " + currencyName); } return map; @@ -60,7 +60,7 @@ public void message(String channel, String message) { Bukkit.getLogger().severe("Invalid message received from RedisEco channel, consider updating RedisEconomy"); return; } - if (split[0].equals(RedisEconomyPlugin.getInstance().settings().serverId)) return; + if (split[0].equals(RedisEconomyPlugin.getInstanceUUID().toString())) return; String accountId = split[1]; UUID owner = UUID.fromString(split[2]); bankOwners.put(accountId, owner); @@ -85,7 +85,7 @@ public void message(String channel, String message) { Bukkit.getLogger().severe("Invalid message received from RedisEco channel, consider updating RedisEconomy"); return; } - if (split[0].equals(RedisEconomyPlugin.getInstance().settings().serverId)) return; + if (split[0].equals(RedisEconomyPlugin.getInstanceUUID().toString())) return; String accountId = split[1]; double balance = Double.parseDouble(split[2]); updateBankAccountLocal(accountId, balance); @@ -269,7 +269,7 @@ public CompletionStage revertTransaction(int transactionId, @NotNull Tr private void setOwner(@NotNull String accountId, UUID ownerUUID) { currenciesManager.getRedisManager().getConnectionPipeline(connection -> { connection.hset(BANK_OWNERS.toString(), accountId, ownerUUID.toString()); - return connection.publish(UPDATE_BANK_OWNER_CHANNEL_PREFIX + currencyName, RedisEconomyPlugin.getInstance().settings().serverId + ";;" + accountId + ";;" + ownerUUID); + return connection.publish(UPDATE_BANK_OWNER_CHANNEL_PREFIX + currencyName, RedisEconomyPlugin.getInstanceUUID().toString() + ";;" + accountId + ";;" + ownerUUID); }).thenAccept((result) -> { if (RedisEconomyPlugin.getInstance().settings().debug) { Bukkit.getLogger().info("Set owner of bank " + accountId + " to " + ownerUUID + " with result " + result); @@ -291,7 +291,7 @@ private synchronized void updateBankAccountCloudCache(@NotNull String accountId, updateExecutor.submit(() -> { currenciesManager.getRedisManager().executeTransaction(reactiveCommands -> { reactiveCommands.zadd(BALANCE_BANK_PREFIX + currencyName, balance, accountId); - reactiveCommands.publish(UPDATE_BANK_CHANNEL_PREFIX + currencyName, RedisEconomyPlugin.getInstance().settings().serverId + ";;" + accountId + ";;" + balance); + reactiveCommands.publish(UPDATE_BANK_CHANNEL_PREFIX + currencyName, RedisEconomyPlugin.getInstanceUUID().toString() + ";;" + accountId + ";;" + balance); }).ifPresentOrElse(result -> { if (RedisEconomyPlugin.getInstance().settings().debug) { Bukkit.getLogger().info("01 Sent bank update accoun " + accountId + " to " + balance); diff --git a/src/main/java/dev/unnm3d/rediseconomy/utils/PlaceholderAPIHook.java b/src/main/java/dev/unnm3d/rediseconomy/utils/PlaceholderAPIHook.java index 01744d2..ae0eb44 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/utils/PlaceholderAPIHook.java +++ b/src/main/java/dev/unnm3d/rediseconomy/utils/PlaceholderAPIHook.java @@ -30,7 +30,7 @@ public PlaceholderAPIHook(RedisEconomyPlugin redisEconomyPlugin) { this.langs = redisEconomyPlugin.langs(); this.totalSupplyCache = new HashMap<>(); this.baltopCache = new HashMap<>(); - this.updateCachePeriod = 1000 * 20; // 1 minute + this.updateCachePeriod = 1000 * 5; // 5 secs this.lastUpdateTimestamp = 0; this.plugin = redisEconomyPlugin; this.prefixProvider = redisEconomyPlugin.getServer().getServicesManager().getRegistration(net.milkbowl.vault.chat.Chat.class); From 3338e61c6cf473a1e63d5525b0494580bf487c14 Mon Sep 17 00:00:00 2001 From: Emibergo02 <36164338+Emibergo02@users.noreply.github.com> Date: Sat, 18 May 2024 12:05:15 +0200 Subject: [PATCH 11/25] Bump version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 10b8a50..226588d 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ dev.unnm3d RedisEconomy - 4.3.13 + 4.3.14 jar RedisEconomy From 583d39bd7291c068ebf1f0f2994e3e0ef9f4095d Mon Sep 17 00:00:00 2001 From: Emibergo02 <36164338+Emibergo02@users.noreply.github.com> Date: Fri, 7 Jun 2024 12:48:58 +0200 Subject: [PATCH 12/25] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ffa50cd..4556ac0 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ dependencies { } ``` ## API usage - +YOU PROBABLY DON'T NEED TO USE REDISECONOMY API: USE VAULT API https://github.com/MilkBowl/VaultAPI ```java // Access Point RedisEconomyAPI api = RedisEconomyAPI.getAPI(); @@ -53,7 +53,7 @@ api.getCurrencyBySymbol("€");//Gets the currency by symbol //Currency is a Vault Economy https://github.com/MilkBowl/VaultAPI/blob/master/src/main/java/net/milkbowl/vault/economy/Economy.java, //same methods and everything currency.getBalance(offlinePlayer); -currency.withdrawPlayer(offlinePlayer, 100); +currency.withdrawPlayer(offlinePlayer, 100, "Reason of withdrawal"); //Modify a player balance (default currency) api.getDefaultCurrency().setPlayerBalance(player.getUniqueId(), 1000); From c692ee0f338848d5bd3baa93fbce22742b551761 Mon Sep 17 00:00:00 2001 From: Emibergo02 <36164338+Emibergo02@users.noreply.github.com> Date: Sun, 1 Sep 2024 22:19:19 +0200 Subject: [PATCH 13/25] Better timeout handling in updateAccountCloudCache Added configurable poolSize in config Added expandpool command to adjust the redis pool size at runtime --- pom.xml | 15 ++-- .../rediseconomy/RedisEconomyPlugin.java | 2 +- .../rediseconomy/command/MainCommand.java | 18 ++++- .../unnm3d/rediseconomy/config/Settings.java | 4 +- .../rediseconomy/currency/Currency.java | 69 ++++++++++++------- .../currency/CurrencyWithBanks.java | 55 ++++++++++----- .../rediseconomy/redis/RedisManager.java | 13 +++- .../redis/RoundRobinConnectionPool.java | 15 ++++ src/main/resources/plugin.yml | 6 +- 9 files changed, 143 insertions(+), 54 deletions(-) diff --git a/pom.xml b/pom.xml index 226588d..8e5ac5c 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ dev.unnm3d RedisEconomy - 4.3.14 + 4.3.15 jar RedisEconomy @@ -113,6 +113,11 @@ placeholderapi https://repo.extendedclip.com/content/repositories/placeholderapi/ + + maven_central + Maven Central + https://repo.maven.apache.org/maven2/ + @@ -131,18 +136,18 @@ org.projectlombok lombok - 1.18.32 + 1.18.34 provided net.kyori adventure-text-minimessage - 4.16.0 + 4.17.0 net.kyori adventure-platform-bukkit - 4.3.2 + 4.3.3 me.clip @@ -153,7 +158,7 @@ io.lettuce lettuce-core - 6.3.2.RELEASE + 6.4.0.RELEASE provided diff --git a/src/main/java/dev/unnm3d/rediseconomy/RedisEconomyPlugin.java b/src/main/java/dev/unnm3d/rediseconomy/RedisEconomyPlugin.java index f03a77e..897e028 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/RedisEconomyPlugin.java +++ b/src/main/java/dev/unnm3d/rediseconomy/RedisEconomyPlugin.java @@ -159,7 +159,7 @@ private boolean setupRedis() { redisURIBuilder.withAuthentication(configManager.getSettings().redis.user(), configManager.getSettings().redis.password()); getLogger().info("Connecting to redis server " + redisURIBuilder.build().toString() + "..."); - this.redisManager = new RedisManager(RedisClient.create(redisURIBuilder.build())); + this.redisManager = new RedisManager(RedisClient.create(redisURIBuilder.build()), configManager.getSettings().redis.poolSize()); redisManager.isConnected().get(1, java.util.concurrent.TimeUnit.SECONDS); if (!configManager.getSettings().clusterId.isEmpty()) RedisKeys.setClusterId(configManager.getSettings().clusterId); diff --git a/src/main/java/dev/unnm3d/rediseconomy/command/MainCommand.java b/src/main/java/dev/unnm3d/rediseconomy/command/MainCommand.java index 359c155..d54b7f1 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/command/MainCommand.java +++ b/src/main/java/dev/unnm3d/rediseconomy/command/MainCommand.java @@ -36,6 +36,20 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command } String langField = args[1]; + if (args[0].equalsIgnoreCase("expandpool")) { + if (!sender.hasPermission("rediseconomy.admin.expandpool")) { + plugin.getConfigManager().getLangs().send(sender, plugin.getConfigManager().getLangs().noPermission); + return true; + } + try { + plugin.getCurrenciesManager().getRedisManager().expandPool(Integer.parseInt(args[1])); + plugin.getConfigManager().getLangs().send(sender, "§aPool expanded successfully!"); + } catch (Exception e) { + plugin.getConfigManager().getLangs().send(sender, "§cError expanding pool: " + e.getMessage()); + } + return true; + } + if (!sender.hasPermission("rediseconomy.admin.editmessage")) { plugin.getConfigManager().getLangs().send(sender, plugin.getConfigManager().getLangs().noPermission); return true; @@ -81,7 +95,9 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command @Override public @NotNull List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) { if (args.length == 1) { - return List.of("reload", "editmessage"); + return List.of("reload", "editmessage", "expandpool"); + } else if (args.length == 2 && args[0].equalsIgnoreCase("expandpool")) { + return List.of("1", "2", "3", "4", "5"); } else if (args.length == 2 && sender.hasPermission("rediseconomy.admin.editmessage")) { return Arrays.stream(plugin.getConfigManager().getLangs().getClass().getFields()).filter(field -> field.getType().equals(String.class)).map(Field::getName).toList(); } diff --git a/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java b/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java index f94c7c1..f531f58 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java +++ b/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java @@ -29,7 +29,7 @@ public class Settings { "Don't use the default credentials in production!! Generate new credentials on RedisLabs -> https://github.com/Emibergo02/RedisEconomy/wiki/Install-redis", "Default credentials lead to a non-persistent redis server, only for testing!!", }) - public RedisSettings redis = new RedisSettings("localhost", 6379, "", "", 0, 2000, "RedisEconomy"); + public RedisSettings redis = new RedisSettings("localhost", 6379, "", "", 0, 300, "RedisEconomy", 5, 3); @Comment({"All RedisEconomy instances with the same cluster id will share the same data"}) public String clusterId = ""; @Comment({"How many chars are needed for a command autocompletion", "Increase if you have a lot of players to list"}) @@ -50,6 +50,6 @@ public record CurrencySettings(String currencyName, String currencySingle, Strin } public record RedisSettings(String host, int port, String user, String password, int database, int timeout, - String clientName) { + String clientName, int poolSize, int tryAgainCount) { } } diff --git a/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java b/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java index 705b00e..db10882 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java +++ b/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java @@ -18,10 +18,7 @@ import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.*; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; +import java.util.concurrent.*; import static dev.unnm3d.rediseconomy.redis.RedisKeys.*; @@ -541,30 +538,52 @@ protected void updateAccount(@NotNull UUID uuid, @Nullable String playerName, do } private synchronized void updateAccountCloudCache(@NotNull UUID uuid, @Nullable String playerName, double balance, int tries) { - updateExecutor.submit(() -> { - currenciesManager.getRedisManager().executeTransaction(reactiveCommands -> { - reactiveCommands.zadd(BALANCE_PREFIX + currencyName, balance, uuid.toString()); - if (playerName != null) - reactiveCommands.hset(NAME_UUID.toString(), playerName, uuid.toString()); - reactiveCommands.publish(UPDATE_PLAYER_CHANNEL_PREFIX + currencyName, - RedisEconomyPlugin.getInstanceUUID().toString() + ";;" + uuid + ";;" + playerName + ";;" + balance); - }).ifPresentOrElse(result -> { - - if (RedisEconomyPlugin.getInstance().settings().debug) { - Bukkit.getLogger().info("01 Sent update account " + playerName + " to " + balance + " currency " + currencyName); - } - }, () -> { - if (tries < 3) { - Bukkit.getLogger().severe("Player accounts are desynchronized"); - updateAccountCloudCache(uuid, playerName, balance, tries + 1); - } else { - Bukkit.getLogger().severe("Failed to update account " + playerName + " after 3 tries"); - throw new RuntimeException("Player accounts are desynchronized"); + final RedisEconomyPlugin plugin = RedisEconomyPlugin.getInstance(); + try { + updateExecutor.submit(() -> { + try { + if (plugin.settings().debug) { + Bukkit.getLogger().info("01a Starting update account " + playerName + " to " + balance + " currency " + currencyName); + } + currenciesManager.getRedisManager().executeTransaction(reactiveCommands -> { + reactiveCommands.zadd(BALANCE_PREFIX + currencyName, balance, uuid.toString()); + if (playerName != null) + reactiveCommands.hset(NAME_UUID.toString(), playerName, uuid.toString()); + reactiveCommands.publish(UPDATE_PLAYER_CHANNEL_PREFIX + currencyName, + RedisEconomyPlugin.getInstanceUUID().toString() + ";;" + uuid + ";;" + playerName + ";;" + balance); + if (plugin.settings().debug) { + plugin.getLogger().info("01b Publishing update account " + playerName + " to " + balance + " currency " + currencyName); + } + }).ifPresentOrElse(result -> { + if (RedisEconomyPlugin.getInstance().settings().debug) { + plugin.getLogger().info("01c Sent update account successfully " + playerName + " to " + balance + " currency " + currencyName); + } + }, () -> handleException(uuid, playerName, balance, tries, null)); + } catch (Exception e) { + handleException(uuid, playerName, balance, tries, e); } - }); - }); + }).get(plugin.settings().redis.timeout(), TimeUnit.MILLISECONDS); + } catch (InterruptedException | TimeoutException | ExecutionException e) { + handleException(uuid, playerName, balance, tries, e); + } } + private void handleException(@NotNull UUID uuid, @Nullable String playerName, double balance, int tries, @Nullable Exception e) { + final RedisEconomyPlugin plugin = RedisEconomyPlugin.getInstance(); + if (tries < plugin.settings().redis.tryAgainCount()) { + plugin.getLogger().warning("Player accounts are desynchronized. try: " + tries); + if (e != null) + plugin.getLogger().warning(e.getMessage()); + updateAccountCloudCache(uuid, playerName, balance, tries + 1); + } else { + plugin.getLogger().severe("Failed to update account " + playerName + " after " + tries + " tries"); + currenciesManager.getRedisManager().printPool(); + if (e != null) + throw new RuntimeException(e); + } + } + + /** * Update the balances of all players and their nameuuids * Do not use this method unless you know what you are doing diff --git a/src/main/java/dev/unnm3d/rediseconomy/currency/CurrencyWithBanks.java b/src/main/java/dev/unnm3d/rediseconomy/currency/CurrencyWithBanks.java index 445e4ca..14d33b1 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/currency/CurrencyWithBanks.java +++ b/src/main/java/dev/unnm3d/rediseconomy/currency/CurrencyWithBanks.java @@ -10,12 +10,12 @@ import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.List; import java.util.Map; import java.util.UUID; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.*; import static dev.unnm3d.rediseconomy.redis.RedisKeys.*; @@ -288,24 +288,45 @@ private void updateBankAccount(@NotNull String accountId, double balance) { } private synchronized void updateBankAccountCloudCache(@NotNull String accountId, double balance, int tries) { - updateExecutor.submit(() -> { - currenciesManager.getRedisManager().executeTransaction(reactiveCommands -> { - reactiveCommands.zadd(BALANCE_BANK_PREFIX + currencyName, balance, accountId); - reactiveCommands.publish(UPDATE_BANK_CHANNEL_PREFIX + currencyName, RedisEconomyPlugin.getInstanceUUID().toString() + ";;" + accountId + ";;" + balance); - }).ifPresentOrElse(result -> { + try { + updateExecutor.submit(() -> { if (RedisEconomyPlugin.getInstance().settings().debug) { - Bukkit.getLogger().info("01 Sent bank update accoun " + accountId + " to " + balance); + Bukkit.getLogger().info("01a Starting update bank account " + accountId + " to " + balance + " currency " + currencyName); } - }, () -> { - if (tries < 3) { - Bukkit.getLogger().severe("Player accounts are desynchronized"); - updateBankAccountCloudCache(accountId, balance, tries + 1); - } else { - Bukkit.getLogger().severe("Failed to update account " + accountId + " after 3 tries"); - throw new RuntimeException("Bank accounts are desynchronized"); + try { + currenciesManager.getRedisManager().executeTransaction(reactiveCommands -> { + reactiveCommands.zadd(BALANCE_BANK_PREFIX + currencyName, balance, accountId); + reactiveCommands.publish(UPDATE_BANK_CHANNEL_PREFIX + currencyName, RedisEconomyPlugin.getInstanceUUID().toString() + ";;" + accountId + ";;" + balance); + if (RedisEconomyPlugin.getInstance().settings().debug) { + RedisEconomyPlugin.getInstance().getLogger().info("01b Publishing update bank account " + accountId + " to " + balance + " currency " + currencyName); + } + }).ifPresentOrElse(result -> { + if (RedisEconomyPlugin.getInstance().settings().debug) { + Bukkit.getLogger().info("01c Sent bank update account " + accountId + " to " + balance); + } + }, () -> handleException(accountId, balance, tries, null)); + } catch (Exception e) { + handleException(accountId, balance, tries, e); } - }); - }); + }).get(RedisEconomyPlugin.getInstance().settings().redis.timeout(), TimeUnit.MILLISECONDS); + } catch (InterruptedException | TimeoutException | ExecutionException e) { + handleException(accountId, balance, tries, e); + } + } + + private void handleException(@NotNull String accountId, double balance, int tries, @Nullable Exception e) { + final RedisEconomyPlugin plugin = RedisEconomyPlugin.getInstance(); + if (tries < plugin.settings().redis.tryAgainCount()) { + plugin.getLogger().warning("Player accounts are desynchronized. try: " + tries); + if (e != null) + plugin.getLogger().warning(e.getMessage()); + updateBankAccountCloudCache(accountId, balance, tries + 1); + } else { + plugin.getLogger().severe("Failed to update bank account " + accountId + " after " + tries + " tries"); + currenciesManager.getRedisManager().printPool(); + if (e != null) + throw new RuntimeException(e); + } } /** diff --git a/src/main/java/dev/unnm3d/rediseconomy/redis/RedisManager.java b/src/main/java/dev/unnm3d/rediseconomy/redis/RedisManager.java index 6939cb9..1da0f61 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/redis/RedisManager.java +++ b/src/main/java/dev/unnm3d/rediseconomy/redis/RedisManager.java @@ -1,5 +1,6 @@ package dev.unnm3d.rediseconomy.redis; +import dev.unnm3d.rediseconomy.RedisEconomyPlugin; import io.lettuce.core.RedisClient; import io.lettuce.core.RedisFuture; import io.lettuce.core.TransactionResult; @@ -25,9 +26,9 @@ public class RedisManager { private final List> pubSubConnections; protected RedisClient lettuceRedisClient; - public RedisManager(RedisClient lettuceRedisClient) { + public RedisManager(RedisClient lettuceRedisClient, int poolSize) { this.lettuceRedisClient = lettuceRedisClient; - this.roundRobinConnectionPool = new RoundRobinConnectionPool<>(lettuceRedisClient::connect, 5); + this.roundRobinConnectionPool = new RoundRobinConnectionPool<>(lettuceRedisClient::connect, poolSize); pubSubConnections = new CopyOnWriteArrayList<>(); } @@ -61,6 +62,14 @@ public StatefulRedisPubSubConnection getPubSubConnection() { return pubSubConnection; } + public void expandPool(int expandBy) { + roundRobinConnectionPool.expandPool(expandBy); + } + + public void printPool() { + RedisEconomyPlugin.getInstance().getLogger().warning(roundRobinConnectionPool.printPool()); + } + public void close() { pubSubConnections.forEach(StatefulRedisPubSubConnection::close); lettuceRedisClient.shutdown(Duration.ofSeconds(1), Duration.ofSeconds(1)); diff --git a/src/main/java/dev/unnm3d/rediseconomy/redis/RoundRobinConnectionPool.java b/src/main/java/dev/unnm3d/rediseconomy/redis/RoundRobinConnectionPool.java index 6dd131e..ea81571 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/redis/RoundRobinConnectionPool.java +++ b/src/main/java/dev/unnm3d/rediseconomy/redis/RoundRobinConnectionPool.java @@ -41,6 +41,21 @@ public StatefulRedisConnection get() { return connection; } + public String printPool() { + StringBuilder sb = new StringBuilder(); + for (StatefulRedisConnection element : elements) { + sb.append("Open: ") + .append(element.isOpen()) + .append(", multi: ") + .append(element.isMulti()) + .append(", hash") + .append(element.hashCode()) + .append("\n"); + } + return sb.toString(); + } + + public void close() { for (StatefulRedisConnection element : elements) { element.closeAsync(); diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 89d0239..4e7f1fd 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -6,7 +6,7 @@ load: STARTUP depend: - Vault libraries: - - io.lettuce:lettuce-core:6.3.2.RELEASE + - io.lettuce:lettuce-core:6.4.0.RELEASE - de.exlll:configlib-yaml:4.5.0 softdepend: - PlaceholderAPI @@ -109,6 +109,9 @@ permissions: rediseconomy.admin.transaction: description: Allows to use /transaction default: false + rediseconomy.admin.expandpool: + description: Allows to expand the pool + default: false rediseconomy.pay.*: description: Allows to use /pay all currencies default: op @@ -128,3 +131,4 @@ permissions: rediseconomy.admin.editmessage: true rediseconomy.admin.backup-restore: true rediseconomy.admin.archive-transactions: true + rediseconomy.admin.expandpool: true From 392daf8c2e87c1178bda575db001c0b59e4c53bf Mon Sep 17 00:00:00 2001 From: Emibergo02 <36164338+Emibergo02@users.noreply.github.com> Date: Sun, 1 Sep 2024 22:19:19 +0200 Subject: [PATCH 14/25] Better timeout handling in updateAccountCloudCache Added configurable poolSize in config Added expandpool command to adjust the redis pool size at runtime --- .../java/dev/unnm3d/rediseconomy/config/ConfigManager.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/dev/unnm3d/rediseconomy/config/ConfigManager.java b/src/main/java/dev/unnm3d/rediseconomy/config/ConfigManager.java index 4f0e256..ba966dc 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/config/ConfigManager.java +++ b/src/main/java/dev/unnm3d/rediseconomy/config/ConfigManager.java @@ -22,7 +22,7 @@ public class ConfigManager { ┃ RedisEconomy Config ┃ ┃ Developed by Unnm3d ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - """ + """ ) .footer("Authors: Unnm3d") .charset(StandardCharsets.UTF_8) @@ -40,6 +40,8 @@ public void loadSettingsConfig() { Settings.class, PROPERTIES ); + if (settings.redis.tryAgainCount() < 2 || settings.redis.poolSize() < 2) + plugin.getLogger().severe("Please regenerate the redis configuration section. New settings have been added."); } public void saveConfigs() { From b24c8b23f6d9215cb47860b1b67d42259645e442 Mon Sep 17 00:00:00 2001 From: Emibergo02 <36164338+Emibergo02@users.noreply.github.com> Date: Mon, 16 Sep 2024 23:05:25 +0200 Subject: [PATCH 15/25] Better timeout handling in updateAccountCloudCache Added configurable poolSize in config Added expandpool command to adjust the redis pool size at runtime --- pom.xml | 2 +- .../unnm3d/rediseconomy/config/Settings.java | 2 + .../rediseconomy/currency/Currency.java | 65 ++++++++++--------- 3 files changed, 37 insertions(+), 32 deletions(-) diff --git a/pom.xml b/pom.xml index 8e5ac5c..972e9d3 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ dev.unnm3d RedisEconomy - 4.3.15 + 4.3.16 jar RedisEconomy diff --git a/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java b/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java index f531f58..d38960a 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java +++ b/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java @@ -18,6 +18,8 @@ public class Settings { public String webEditorUrl = "https://webui.advntr.dev/"; @Comment("Activate this before reporting an issue") public boolean debug = false; + @Comment("A specific debug for cache update") + public boolean debugUpdateCache = false; @Comment("If true, the plugin registers who's calling it's methods inside transactions") public boolean registerCalls = false; @Comment({"if true, migrates the bukkit offline uuids accounts to the default RedisEconomy currency", diff --git a/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java b/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java index db10882..6f2504c 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java +++ b/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java @@ -18,7 +18,10 @@ import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.*; -import java.util.concurrent.*; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import static dev.unnm3d.rediseconomy.redis.RedisKeys.*; @@ -539,43 +542,43 @@ protected void updateAccount(@NotNull UUID uuid, @Nullable String playerName, do private synchronized void updateAccountCloudCache(@NotNull UUID uuid, @Nullable String playerName, double balance, int tries) { final RedisEconomyPlugin plugin = RedisEconomyPlugin.getInstance(); - try { - updateExecutor.submit(() -> { - try { - if (plugin.settings().debug) { - Bukkit.getLogger().info("01a Starting update account " + playerName + " to " + balance + " currency " + currencyName); - } - currenciesManager.getRedisManager().executeTransaction(reactiveCommands -> { - reactiveCommands.zadd(BALANCE_PREFIX + currencyName, balance, uuid.toString()); - if (playerName != null) - reactiveCommands.hset(NAME_UUID.toString(), playerName, uuid.toString()); - reactiveCommands.publish(UPDATE_PLAYER_CHANNEL_PREFIX + currencyName, - RedisEconomyPlugin.getInstanceUUID().toString() + ";;" + uuid + ";;" + playerName + ";;" + balance); - if (plugin.settings().debug) { - plugin.getLogger().info("01b Publishing update account " + playerName + " to " + balance + " currency " + currencyName); - } - }).ifPresentOrElse(result -> { - if (RedisEconomyPlugin.getInstance().settings().debug) { - plugin.getLogger().info("01c Sent update account successfully " + playerName + " to " + balance + " currency " + currencyName); - } - }, () -> handleException(uuid, playerName, balance, tries, null)); - } catch (Exception e) { - handleException(uuid, playerName, balance, tries, e); + updateExecutor.submit(() -> { + try { + if (plugin.settings().debugUpdateCache) { + Bukkit.getLogger().info("01a Starting update account " + playerName + " to " + balance + " currency " + currencyName); } - }).get(plugin.settings().redis.timeout(), TimeUnit.MILLISECONDS); - } catch (InterruptedException | TimeoutException | ExecutionException e) { - handleException(uuid, playerName, balance, tries, e); - } + currenciesManager.getRedisManager().executeTransaction(reactiveCommands -> { + reactiveCommands.zadd(BALANCE_PREFIX + currencyName, balance, uuid.toString()); + if (playerName != null) + reactiveCommands.hset(NAME_UUID.toString(), playerName, uuid.toString()); + reactiveCommands.publish(UPDATE_PLAYER_CHANNEL_PREFIX + currencyName, + RedisEconomyPlugin.getInstanceUUID().toString() + ";;" + uuid + ";;" + playerName + ";;" + balance); + if (plugin.settings().debugUpdateCache) { + plugin.getLogger().info("01b Publishing update account " + playerName + " to " + balance + " currency " + currencyName); + } + }).ifPresentOrElse(result -> { + if (RedisEconomyPlugin.getInstance().settings().debugUpdateCache) { + plugin.getLogger().info("01c Sent update account successfully " + playerName + " to " + balance + " currency " + currencyName); + } + }, () -> handleException(uuid, playerName, balance, tries, null)); + } catch (Exception e) { + handleException(uuid, playerName, balance, tries, e); + } + }); } private void handleException(@NotNull UUID uuid, @Nullable String playerName, double balance, int tries, @Nullable Exception e) { final RedisEconomyPlugin plugin = RedisEconomyPlugin.getInstance(); if (tries < plugin.settings().redis.tryAgainCount()) { - plugin.getLogger().warning("Player accounts are desynchronized. try: " + tries); - if (e != null) - plugin.getLogger().warning(e.getMessage()); + if (plugin.settings().debugUpdateCache) { + plugin.getLogger().warning("Player accounts are desynchronized. try: " + tries); + if (e != null) + plugin.getLogger().warning(e.getMessage()); + } updateAccountCloudCache(uuid, playerName, balance, tries + 1); - } else { + return; + } + if (plugin.settings().debugUpdateCache) { plugin.getLogger().severe("Failed to update account " + playerName + " after " + tries + " tries"); currenciesManager.getRedisManager().printPool(); if (e != null) From b08fff5ed227ae523b23b1e21ffe2236cb3060a4 Mon Sep 17 00:00:00 2001 From: Emibergo02 <36164338+Emibergo02@users.noreply.github.com> Date: Sat, 21 Sep 2024 15:48:40 +0200 Subject: [PATCH 16/25] Added per-player max balance Configurable with /balance username currencyName set-max (It is a cross-server feature of course) Avoid error when upgrading RedisEconomy from ancient versions by checking 0 values --- pom.xml | 2 +- .../rediseconomy/RedisEconomyPlugin.java | 2 +- .../command/balance/BalanceCommand.java | 7 +- .../command/balance/BalanceSubCommands.java | 14 +++ .../dev/unnm3d/rediseconomy/config/Langs.java | 1 + .../unnm3d/rediseconomy/config/Settings.java | 8 ++ .../rediseconomy/currency/Currency.java | 95 +++++++++++++++---- .../currency/CurrencyWithBanks.java | 2 +- .../unnm3d/rediseconomy/redis/RedisKeys.java | 2 + .../utils/PlaceholderAPIHook.java | 2 +- 10 files changed, 111 insertions(+), 24 deletions(-) diff --git a/pom.xml b/pom.xml index 972e9d3..6764ecd 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ dev.unnm3d RedisEconomy - 4.3.16 + 4.3.17 jar RedisEconomy diff --git a/src/main/java/dev/unnm3d/rediseconomy/RedisEconomyPlugin.java b/src/main/java/dev/unnm3d/rediseconomy/RedisEconomyPlugin.java index 897e028..7beff76 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/RedisEconomyPlugin.java +++ b/src/main/java/dev/unnm3d/rediseconomy/RedisEconomyPlugin.java @@ -159,7 +159,7 @@ private boolean setupRedis() { redisURIBuilder.withAuthentication(configManager.getSettings().redis.user(), configManager.getSettings().redis.password()); getLogger().info("Connecting to redis server " + redisURIBuilder.build().toString() + "..."); - this.redisManager = new RedisManager(RedisClient.create(redisURIBuilder.build()), configManager.getSettings().redis.poolSize()); + this.redisManager = new RedisManager(RedisClient.create(redisURIBuilder.build()), configManager.getSettings().redis.getPoolSize()); redisManager.isConnected().get(1, java.util.concurrent.TimeUnit.SECONDS); if (!configManager.getSettings().clusterId.isEmpty()) RedisKeys.setClusterId(configManager.getSettings().clusterId); diff --git a/src/main/java/dev/unnm3d/rediseconomy/command/balance/BalanceCommand.java b/src/main/java/dev/unnm3d/rediseconomy/command/balance/BalanceCommand.java index 9ff8773..dc0207f 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/command/balance/BalanceCommand.java +++ b/src/main/java/dev/unnm3d/rediseconomy/command/balance/BalanceCommand.java @@ -84,6 +84,9 @@ else if (reasonOrCommand.startsWith("/")) { } else if (args[2].equalsIgnoreCase("set")) { setPlayer(sender, currency, amount, target); + + } else if (args[2].equalsIgnoreCase("set-max")) { + setPlayerMaxBalance(sender, currency, amount, target); } } if (plugin.settings().debug) @@ -105,6 +108,8 @@ else if (reasonOrCommand.startsWith("/")) { protected abstract void setPlayer(CommandSender sender, Currency currency, double amount, String target); + protected abstract void setPlayerMaxBalance(CommandSender sender, Currency currency, double amount, String target); + @Override public @NotNull List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { if (args.length == 1) { @@ -118,7 +123,7 @@ else if (reasonOrCommand.startsWith("/")) { } else if (args.length == 2) return economy.getCurrencies().stream().map(Currency::getCurrencyName).filter(name -> name.startsWith(args[1]) && sender.hasPermission("rediseconomy.balance." + args[1])).toList(); else if (args.length == 3) - return List.of("give", "take", "set"); + return List.of("give", "take", "set", "set-max"); else if (args.length == 4) return List.of("69"); return List.of(); diff --git a/src/main/java/dev/unnm3d/rediseconomy/command/balance/BalanceSubCommands.java b/src/main/java/dev/unnm3d/rediseconomy/command/balance/BalanceSubCommands.java index c09f54d..2625cb0 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/command/balance/BalanceSubCommands.java +++ b/src/main/java/dev/unnm3d/rediseconomy/command/balance/BalanceSubCommands.java @@ -7,6 +7,8 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import java.util.UUID; + public class BalanceSubCommands extends BalanceCommand { public BalanceSubCommands(CurrenciesManager economy, RedisEconomyPlugin plugin) { @@ -72,4 +74,16 @@ protected void setPlayer(CommandSender sender, Currency currency, double amount, plugin.langs().send(sender, plugin.langs().balanceSet.replace("%balance%", currency.format(er.balance)).replace("%player%", target)); else sender.sendMessage(er.errorMessage); } + + @Override + protected void setPlayerMaxBalance(CommandSender sender, Currency currency, double amount, String target) { + final UUID targetUUID = plugin.getCurrenciesManager().getUUIDFromUsernameCache(target); + if (targetUUID == null) { + plugin.langs().send(sender, plugin.langs().playerNotFound); + return; + } + currency.setPlayerMaxBalance(targetUUID, amount); + plugin.langs().send(sender, plugin.langs().maxBalanceSet.replace("%player%", target).replace("%amount%", currency.format(amount))); + } + } diff --git a/src/main/java/dev/unnm3d/rediseconomy/config/Langs.java b/src/main/java/dev/unnm3d/rediseconomy/config/Langs.java index e054bdc..b68e860 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/config/Langs.java +++ b/src/main/java/dev/unnm3d/rediseconomy/config/Langs.java @@ -26,6 +26,7 @@ public final class Langs { public String insufficientFunds = "You do not have enough money!"; public String balance = "You have %balance%!"; public String balanceSet = "You set %player% account to %balance% !"; + public String maxBalanceSet = "You set %player% max balance to %amount% !"; public String balanceOther = "%player% has %balance% !"; public String balanceTop = "Top richest players:
%prevpage% %page% %nextpage%"; public String blockedAccounts = "Blocked accounts:
%list%"; diff --git a/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java b/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java index d38960a..911c8ee 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java +++ b/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java @@ -53,5 +53,13 @@ public record CurrencySettings(String currencyName, String currencySingle, Strin public record RedisSettings(String host, int port, String user, String password, int database, int timeout, String clientName, int poolSize, int tryAgainCount) { + //Those checks are for new config files, if the user doesn't have the new settings + public int getPoolSize() { + return poolSize == 0 ? 5 : poolSize; + } + + public int getTryAgainCount() { + return tryAgainCount == 0 ? 3 : tryAgainCount; + } } } diff --git a/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java b/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java index 6f2504c..24c25b1 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java +++ b/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java @@ -32,6 +32,7 @@ public class Currency implements Economy { @Getter protected final String currencyName; private final ConcurrentHashMap accounts; + private final ConcurrentHashMap maxPlayerBalances; private boolean enabled; @Getter @@ -72,19 +73,29 @@ public Currency(CurrenciesManager currenciesManager, Settings.CurrencySettings c this.transactionTax = currencySettings.payTax(); this.taxOnlyPay = currencySettings.taxOnlyPay(); this.accounts = new ConcurrentHashMap<>(); + this.maxPlayerBalances = new ConcurrentHashMap<>(); this.decimalFormat = new DecimalFormat( currencySettings.decimalFormat() != null ? currencySettings.decimalFormat() : "#.##", new DecimalFormatSymbols(Locale.forLanguageTag(currencySettings.languageTag() != null ? currencySettings.languageTag() : "en-US")) ); + getOrderedAccounts(-1).thenApply(result -> { - result.forEach(t -> - accounts.put(UUID.fromString(t.getValue()), t.getScore())); - if (RedisEconomyPlugin.getInstance().settings().debug && !accounts.isEmpty()) { - Bukkit.getLogger().info("start1 Loaded " + accounts.size() + " accounts for currency " + currencyName); - } - return result; - } - ).toCompletableFuture().join(); //Wait to avoid API calls before accounts are loaded + result.forEach(t -> + accounts.put(UUID.fromString(t.getValue()), t.getScore())); + if (RedisEconomyPlugin.getInstance().settings().debug && !accounts.isEmpty()) { + Bukkit.getLogger().info("start1 Loaded " + accounts.size() + " accounts for currency " + currencyName); + } + return result; + }).toCompletableFuture().join(); //Wait to avoid API calls before accounts are loaded + + getPlayerMaxBalances().thenApply(result -> { + maxPlayerBalances.putAll(result); + if (RedisEconomyPlugin.getInstance().settings().debug && !maxPlayerBalances.isEmpty()) { + Bukkit.getLogger().info("start1 Loaded " + maxPlayerBalances.size() + " max balances for currency " + currencyName); + } + return result; + }); //Not as critical as accounts, so we don't wait + registerUpdateListener(); } @@ -95,21 +106,33 @@ private void registerUpdateListener() { @Override public void message(String channel, String message) { String[] split = message.split(";;"); - if (split.length != 4) { + if (split.length != 3) { Bukkit.getLogger().severe("Invalid message received from RedisEco channel, consider updating RedisEconomy"); return; } if (split[0].equals(RedisEconomyPlugin.getInstanceUUID().toString())) return; + UUID uuid = UUID.fromString(split[1]); - String playerName = split[2]; - double balance = Double.parseDouble(split[3]); - updateAccountLocal(uuid, playerName, balance); - if (RedisEconomyPlugin.getInstance().settings().debug) { - Bukkit.getLogger().info("01b Received balance update " + playerName + " to " + balance); + double balance = Double.parseDouble(split[2]); + if (channel.equals(UPDATE_PLAYER_CHANNEL_PREFIX + currencyName)) { + String playerName = currenciesManager.getUsernameFromUUIDCache(uuid); + if (playerName == null) { + Bukkit.getLogger().severe("Player name not found for UUID " + uuid); + return; + } + updateAccountLocal(uuid, playerName, balance); + if (RedisEconomyPlugin.getInstance().settings().debug) { + Bukkit.getLogger().info("01b Received balance update " + playerName + " to " + balance); + } + } else if (channel.equals(UPDATE_MAX_BAL_PREFIX + currencyName)) { + setPlayerMaxBalanceLocal(uuid, maxBalance); + if (RedisEconomyPlugin.getInstance().settings().debug) { + Bukkit.getLogger().info("01b Received max balance update " + uuid + " to " + maxBalance); + } } } }); - connection.async().subscribe(UPDATE_PLAYER_CHANNEL_PREFIX + currencyName); + connection.async().subscribe(UPDATE_PLAYER_CHANNEL_PREFIX + currencyName, UPDATE_MAX_BAL_PREFIX + currencyName); if (RedisEconomyPlugin.getInstance().settings().debug) { Bukkit.getLogger().info("start1b Listening to RedisEco channel " + UPDATE_PLAYER_CHANNEL_PREFIX + currencyName); } @@ -405,7 +428,7 @@ public EconomyResponse payPlayer(@NotNull UUID sender, @NotNull UUID receiver, d if (!has(sender, amountToWithdraw)) return new EconomyResponse(0, getBalance(sender), EconomyResponse.ResponseType.FAILURE, "Insufficient funds"); - if (getBalance(receiver) + amount > maxBalance) + if (getBalance(receiver) + amount > getPlayerMaxBalance(receiver)) return new EconomyResponse(0, getBalance(receiver), EconomyResponse.ResponseType.FAILURE, "The receiver has reached the maximum balance"); updateAccount(sender, senderName, getBalance(sender) - amountToWithdraw); @@ -436,7 +459,7 @@ public EconomyResponse payPlayer(@NotNull String senderName, @NotNull String rec if (!has(senderName, amountToWithdraw)) return new EconomyResponse(0, getBalance(sender), EconomyResponse.ResponseType.FAILURE, "Insufficient funds"); - if (getBalance(receiver) + amount > maxBalance) + if (getBalance(receiver) + amount > getPlayerMaxBalance(receiver)) return new EconomyResponse(0, getBalance(receiver), EconomyResponse.ResponseType.FAILURE, "The receiver has reached the maximum balance"); updateAccount(sender, senderName, getBalance(sender) - amountToWithdraw); @@ -521,7 +544,7 @@ public EconomyResponse depositPlayer(@NotNull UUID playerUUID, @Nullable String if (amount == Double.POSITIVE_INFINITY || amount == Double.NEGATIVE_INFINITY || Double.isNaN(amount)) return new EconomyResponse(0, 0, EconomyResponse.ResponseType.FAILURE, "Invalid decimal amount format"); - if (getBalance(playerUUID) + amount > maxBalance) + if (getBalance(playerUUID) + amount > getPlayerMaxBalance(playerUUID)) return new EconomyResponse(0, getBalance(playerUUID), EconomyResponse.ResponseType.FAILURE, "The player has reached the maximum balance"); updateAccount(playerUUID, playerName, getBalance(playerUUID) + amount); @@ -569,7 +592,7 @@ private synchronized void updateAccountCloudCache(@NotNull UUID uuid, @Nullable private void handleException(@NotNull UUID uuid, @Nullable String playerName, double balance, int tries, @Nullable Exception e) { final RedisEconomyPlugin plugin = RedisEconomyPlugin.getInstance(); - if (tries < plugin.settings().redis.tryAgainCount()) { + if (tries < plugin.settings().redis.getTryAgainCount()) { if (plugin.settings().debugUpdateCache) { plugin.getLogger().warning("Player accounts are desynchronized. try: " + tries); if (e != null) @@ -623,6 +646,40 @@ public CompletionStage>> getOrderedAccounts(int limit) } + public double getPlayerMaxBalance(UUID uuid) { + return maxPlayerBalances.getOrDefault(uuid, maxBalance); + } + + public void setPlayerMaxBalance(UUID uuid, double amount) { + setPlayerMaxBalanceCloud(uuid, amount); + setPlayerMaxBalanceLocal(uuid, amount); + } + + public void setPlayerMaxBalanceLocal(UUID uuid, double amount) { + maxPlayerBalances.put(uuid, amount); + } + + public void setPlayerMaxBalanceCloud(UUID uuid, double amount) { + currenciesManager.getRedisManager().getConnectionPipeline(asyncCommands -> { + if(amount == maxBalance) { + asyncCommands.hdel(MAX_PLAYER_BALANCES + currencyName, uuid.toString()); + } else { + asyncCommands.hset(MAX_PLAYER_BALANCES + currencyName, uuid.toString(), String.valueOf(amount)); + } + return asyncCommands.publish(UPDATE_MAX_BAL_PREFIX + currencyName, RedisEconomyPlugin.getInstanceUUID().toString() + ";;" + uuid + ";;" + amount); + }); + } + + public CompletionStage> getPlayerMaxBalances() { + return currenciesManager.getRedisManager().getConnectionAsync(accounts -> + accounts.hgetall(MAX_PLAYER_BALANCES + currencyName)) + .thenApply(result -> { + final Map maxBalances = new HashMap<>(); + result.forEach((key, value) -> maxBalances.put(UUID.fromString(key), Double.parseDouble(value))); + return maxBalances; + }); + } + /** * Get single ordered account from Redis * diff --git a/src/main/java/dev/unnm3d/rediseconomy/currency/CurrencyWithBanks.java b/src/main/java/dev/unnm3d/rediseconomy/currency/CurrencyWithBanks.java index 14d33b1..1d23c51 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/currency/CurrencyWithBanks.java +++ b/src/main/java/dev/unnm3d/rediseconomy/currency/CurrencyWithBanks.java @@ -316,7 +316,7 @@ private synchronized void updateBankAccountCloudCache(@NotNull String accountId, private void handleException(@NotNull String accountId, double balance, int tries, @Nullable Exception e) { final RedisEconomyPlugin plugin = RedisEconomyPlugin.getInstance(); - if (tries < plugin.settings().redis.tryAgainCount()) { + if (tries < plugin.settings().redis.getTryAgainCount()) { plugin.getLogger().warning("Player accounts are desynchronized. try: " + tries); if (e != null) plugin.getLogger().warning(e.getMessage()); diff --git a/src/main/java/dev/unnm3d/rediseconomy/redis/RedisKeys.java b/src/main/java/dev/unnm3d/rediseconomy/redis/RedisKeys.java index 6865262..e18d473 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/redis/RedisKeys.java +++ b/src/main/java/dev/unnm3d/rediseconomy/redis/RedisKeys.java @@ -5,10 +5,12 @@ public enum RedisKeys { NAME_UUID("rediseco:nameuuid"), + MAX_PLAYER_BALANCES("rediseco:max_bals"), BALANCE_PREFIX("rediseco:balances_"), BALANCE_BANK_PREFIX("rediseco:b_balances_"), BANK_OWNERS("rediseco:b_owners"), UPDATE_PLAYER_CHANNEL_PREFIX("rediseco:update_"), + UPDATE_MAX_BAL_PREFIX("rediseco:update_"), UPDATE_BANK_CHANNEL_PREFIX("rediseco:b_update_"), UPDATE_BANK_OWNER_CHANNEL_PREFIX("rediseco:b_owner_update_"), MSG_CHANNEL("rediseco:paymsg"), diff --git a/src/main/java/dev/unnm3d/rediseconomy/utils/PlaceholderAPIHook.java b/src/main/java/dev/unnm3d/rediseconomy/utils/PlaceholderAPIHook.java index ae0eb44..d4a9b25 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/utils/PlaceholderAPIHook.java +++ b/src/main/java/dev/unnm3d/rediseconomy/utils/PlaceholderAPIHook.java @@ -115,7 +115,7 @@ public String onRequest(OfflinePlayer player, String params) { return parseParams(totalSupplyCache.get(currency), splitted, currency); } case "maxbal" -> { - return String.valueOf(currency.getMaxBalance()); + return String.valueOf(currency.getPlayerMaxBalance(player.getUniqueId())); } case "top" -> { From fe378c56d28497cffa9ec8824aadcad2f34a1518 Mon Sep 17 00:00:00 2001 From: Emibergo02 <36164338+Emibergo02@users.noreply.github.com> Date: Mon, 30 Sep 2024 15:47:43 +0200 Subject: [PATCH 17/25] changed duplicated channel name --- src/main/java/dev/unnm3d/rediseconomy/redis/RedisKeys.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/dev/unnm3d/rediseconomy/redis/RedisKeys.java b/src/main/java/dev/unnm3d/rediseconomy/redis/RedisKeys.java index e18d473..996d05a 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/redis/RedisKeys.java +++ b/src/main/java/dev/unnm3d/rediseconomy/redis/RedisKeys.java @@ -10,7 +10,7 @@ public enum RedisKeys { BALANCE_BANK_PREFIX("rediseco:b_balances_"), BANK_OWNERS("rediseco:b_owners"), UPDATE_PLAYER_CHANNEL_PREFIX("rediseco:update_"), - UPDATE_MAX_BAL_PREFIX("rediseco:update_"), + UPDATE_MAX_BAL_PREFIX("rediseco:update_max_"), UPDATE_BANK_CHANNEL_PREFIX("rediseco:b_update_"), UPDATE_BANK_OWNER_CHANNEL_PREFIX("rediseco:b_owner_update_"), MSG_CHANNEL("rediseco:paymsg"), From 080a2ec40e4859d396aa29288beb93c33e5244d9 Mon Sep 17 00:00:00 2001 From: Emibergo02 <36164338+Emibergo02@users.noreply.github.com> Date: Wed, 2 Oct 2024 13:28:06 +0200 Subject: [PATCH 18/25] Fixed error and shading Cleaned up plugin message registering --- pom.xml | 4 ++++ src/main/java/dev/unnm3d/rediseconomy/RedisEconomyPlugin.java | 2 -- src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 6764ecd..197a46b 100644 --- a/pom.xml +++ b/pom.xml @@ -44,6 +44,10 @@ net.kyori dev.unnm3d.shaded.kyori + + de.exlll.configlib + dev.unnm3d.shaded.configlib + com.github.Anon8281.universalScheduler dev.unnm3d.shaded.universalScheduler diff --git a/src/main/java/dev/unnm3d/rediseconomy/RedisEconomyPlugin.java b/src/main/java/dev/unnm3d/rediseconomy/RedisEconomyPlugin.java index 7beff76..04a4a4b 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/RedisEconomyPlugin.java +++ b/src/main/java/dev/unnm3d/rediseconomy/RedisEconomyPlugin.java @@ -136,8 +136,6 @@ public void onDisable() { redisManager.close(); if (currenciesManager != null) this.getServer().getServicesManager().unregister(Economy.class, currenciesManager.getDefaultCurrency()); - this.getServer().getMessenger().unregisterOutgoingPluginChannel(this); - this.getServer().getMessenger().unregisterIncomingPluginChannel(this); getLogger().info("RedisEconomy disabled successfully!"); } diff --git a/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java b/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java index 24c25b1..3d0a522 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java +++ b/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java @@ -106,7 +106,7 @@ private void registerUpdateListener() { @Override public void message(String channel, String message) { String[] split = message.split(";;"); - if (split.length != 3) { + if (split.length < 3) { Bukkit.getLogger().severe("Invalid message received from RedisEco channel, consider updating RedisEconomy"); return; } From 6ff875a455eb0e2bfad774986e58b7c06b76205a Mon Sep 17 00:00:00 2001 From: Pierre-Olivier GOIN <60008676+Koora7334@users.noreply.github.com> Date: Tue, 1 Oct 2024 08:29:35 +0200 Subject: [PATCH 19/25] Fix Permissions Fix permissions for paying with currencies --- src/main/java/dev/unnm3d/rediseconomy/command/PayCommand.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/dev/unnm3d/rediseconomy/command/PayCommand.java b/src/main/java/dev/unnm3d/rediseconomy/command/PayCommand.java index e8ac73a..f88a91a 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/command/PayCommand.java +++ b/src/main/java/dev/unnm3d/rediseconomy/command/PayCommand.java @@ -45,8 +45,10 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command if (args.length == 2) { payCurrency(p, currenciesManager.getDefaultCurrency(), args); } else { - if (!sender.hasPermission("rediseconomy.pay." + args[2])) + if (!sender.hasPermission("rediseconomy.pay." + args[2])) { plugin.langs().send(sender, plugin.langs().noPermission); + return true; + } Currency currency = currenciesManager.getCurrencyByName(args[2]); if (currency == null) { plugin.langs().send(sender, plugin.langs().invalidCurrency); From 0d3dac9e76a2c67c1ff10fbc5c93553f50096c69 Mon Sep 17 00:00:00 2001 From: Emibergo02 <36164338+Emibergo02@users.noreply.github.com> Date: Wed, 2 Oct 2024 13:30:20 +0200 Subject: [PATCH 20/25] Fixed setting wrong max balance --- src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java b/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java index 3d0a522..08c78f0 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java +++ b/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java @@ -125,9 +125,9 @@ public void message(String channel, String message) { Bukkit.getLogger().info("01b Received balance update " + playerName + " to " + balance); } } else if (channel.equals(UPDATE_MAX_BAL_PREFIX + currencyName)) { - setPlayerMaxBalanceLocal(uuid, maxBalance); + setPlayerMaxBalanceLocal(uuid, balance); if (RedisEconomyPlugin.getInstance().settings().debug) { - Bukkit.getLogger().info("01b Received max balance update " + uuid + " to " + maxBalance); + Bukkit.getLogger().info("01b Received max balance update " + uuid + " to " + balance); } } } From 0a6215d19b9831b2392b2c0ff54e4bc8393a0f95 Mon Sep 17 00:00:00 2001 From: Emibergo02 <36164338+Emibergo02@users.noreply.github.com> Date: Wed, 2 Oct 2024 15:42:52 +0200 Subject: [PATCH 21/25] Fixed error when receiving max bal --- pom.xml | 2 +- .../dev/unnm3d/rediseconomy/currency/Currency.java | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index 197a46b..9e60d24 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ dev.unnm3d RedisEconomy - 4.3.17 + 4.3.18 jar RedisEconomy diff --git a/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java b/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java index 08c78f0..f64b2ea 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java +++ b/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java @@ -108,14 +108,14 @@ public void message(String channel, String message) { String[] split = message.split(";;"); if (split.length < 3) { Bukkit.getLogger().severe("Invalid message received from RedisEco channel, consider updating RedisEconomy"); - return; } + if (split[0].equals(RedisEconomyPlugin.getInstanceUUID().toString())) return; + final UUID uuid = UUID.fromString(split[1]); - UUID uuid = UUID.fromString(split[1]); - double balance = Double.parseDouble(split[2]); if (channel.equals(UPDATE_PLAYER_CHANNEL_PREFIX + currencyName)) { - String playerName = currenciesManager.getUsernameFromUUIDCache(uuid); + String playerName = split[2]; + double balance = Double.parseDouble(split[3]); if (playerName == null) { Bukkit.getLogger().severe("Player name not found for UUID " + uuid); return; @@ -125,9 +125,10 @@ public void message(String channel, String message) { Bukkit.getLogger().info("01b Received balance update " + playerName + " to " + balance); } } else if (channel.equals(UPDATE_MAX_BAL_PREFIX + currencyName)) { - setPlayerMaxBalanceLocal(uuid, balance); + double maxBal = Double.parseDouble(split[2]); + setPlayerMaxBalanceLocal(uuid, maxBal); if (RedisEconomyPlugin.getInstance().settings().debug) { - Bukkit.getLogger().info("01b Received max balance update " + uuid + " to " + balance); + Bukkit.getLogger().info("01b Received max balance update " + uuid + " to " + maxBal); } } } From cbc5643347befb3938f3da825d0d2e7fde40d18f Mon Sep 17 00:00:00 2001 From: Emibergo02 <36164338+Emibergo02@users.noreply.github.com> Date: Wed, 2 Oct 2024 15:46:35 +0200 Subject: [PATCH 22/25] Removed unused Settings parameter --- src/main/java/dev/unnm3d/rediseconomy/config/Settings.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java b/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java index 911c8ee..bc9e00e 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java +++ b/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java @@ -9,9 +9,6 @@ @SuppressWarnings("unused") @Configuration public class Settings { - @Comment({"This is automatically generated on server startup", - "You need to have a different serverId for each server!!!"}) - public String serverId = String.valueOf(UUID.randomUUID()); @Comment("Language file") public String lang = "en-US"; @Comment("Webeditor URL") From 8f2cf09714c3797e78e57928aaa023c67645024d Mon Sep 17 00:00:00 2001 From: Emibergo02 <36164338+Emibergo02@users.noreply.github.com> Date: Mon, 14 Oct 2024 22:34:20 +0200 Subject: [PATCH 23/25] 4.3.19 Remove unbinded uuids More verbose on cloud sync --- pom.xml | 2 +- .../unnm3d/rediseconomy/command/PurgeUserCommand.java | 4 +--- .../unnm3d/rediseconomy/currency/CurrenciesManager.java | 9 +++++++++ .../java/dev/unnm3d/rediseconomy/currency/Currency.java | 2 +- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 9e60d24..4d450b3 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ dev.unnm3d RedisEconomy - 4.3.18 + 4.3.19 jar RedisEconomy diff --git a/src/main/java/dev/unnm3d/rediseconomy/command/PurgeUserCommand.java b/src/main/java/dev/unnm3d/rediseconomy/command/PurgeUserCommand.java index 71304f7..7f984c6 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/command/PurgeUserCommand.java +++ b/src/main/java/dev/unnm3d/rediseconomy/command/PurgeUserCommand.java @@ -44,13 +44,11 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command nameUUIDs = currenciesManager.removeNamePattern(target, !onlyNameUUID); successMsg = plugin.langs().purgeUserSuccess.replace("%player%", target); } - if (nameUUIDs.size() == 0) { + if (nameUUIDs.isEmpty()) { plugin.langs().send(sender, plugin.langs().playerNotFound); return true; } plugin.langs().send(sender, successMsg); - - return true; } diff --git a/src/main/java/dev/unnm3d/rediseconomy/currency/CurrenciesManager.java b/src/main/java/dev/unnm3d/rediseconomy/currency/CurrenciesManager.java index 1354d8a..80dbda8 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/currency/CurrenciesManager.java +++ b/src/main/java/dev/unnm3d/rediseconomy/currency/CurrenciesManager.java @@ -193,6 +193,15 @@ public HashMap removeNamePattern(String namePattern, boolean reset */ public HashMap resetBalanceNamePattern(String namePattern, Currency currencyReset) { HashMap removed = new HashMap<>(); + currencyReset.getOrderedAccounts(Integer.MAX_VALUE).thenAccept(accounts -> { + for (ScoredValue account : accounts) { + UUID uuid = UUID.fromString(account.getValue()); + if (!nameUniqueIds.containsValue(uuid)) { + currencyReset.setPlayerBalance(uuid, null, 0.0); + } + } + }); + for (Map.Entry entry : nameUniqueIds.entrySet()) { if (entry.getKey().matches(namePattern)) { removed.put(entry.getKey(), entry.getValue()); diff --git a/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java b/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java index f64b2ea..579e8d3 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java +++ b/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java @@ -597,7 +597,7 @@ private void handleException(@NotNull UUID uuid, @Nullable String playerName, do if (plugin.settings().debugUpdateCache) { plugin.getLogger().warning("Player accounts are desynchronized. try: " + tries); if (e != null) - plugin.getLogger().warning(e.getMessage()); + e.printStackTrace(); } updateAccountCloudCache(uuid, playerName, balance, tries + 1); return; From 7176cda3f902579402071f6adec4b5fe67ad2f9f Mon Sep 17 00:00:00 2001 From: Emibergo02 <36164338+Emibergo02@users.noreply.github.com> Date: Thu, 19 Dec 2024 23:41:59 +0100 Subject: [PATCH 24/25] 4.3.20 Fractional digits Vault method was returning a wrong number Added %balance_short% for /balance and /baltop commands to display short version of the amount --- pom.xml | 2 +- .../rediseconomy/command/MainCommand.java | 8 ++++-- .../command/balance/BalanceSubCommands.java | 14 ++++++++-- .../command/balance/BalanceTopCommand.java | 4 +++ .../dev/unnm3d/rediseconomy/config/Langs.java | 6 ++--- .../unnm3d/rediseconomy/config/Settings.java | 3 +-- .../rediseconomy/currency/Currency.java | 2 +- .../rediseconomy/utils/DecimalUtils.java | 27 +++++++++++++++++++ 8 files changed, 55 insertions(+), 11 deletions(-) create mode 100644 src/main/java/dev/unnm3d/rediseconomy/utils/DecimalUtils.java diff --git a/pom.xml b/pom.xml index 4d450b3..e5b59ea 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ dev.unnm3d RedisEconomy - 4.3.19 + 4.3.20 jar RedisEconomy diff --git a/src/main/java/dev/unnm3d/rediseconomy/command/MainCommand.java b/src/main/java/dev/unnm3d/rediseconomy/command/MainCommand.java index d54b7f1..e315d62 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/command/MainCommand.java +++ b/src/main/java/dev/unnm3d/rediseconomy/command/MainCommand.java @@ -98,8 +98,12 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command return List.of("reload", "editmessage", "expandpool"); } else if (args.length == 2 && args[0].equalsIgnoreCase("expandpool")) { return List.of("1", "2", "3", "4", "5"); - } else if (args.length == 2 && sender.hasPermission("rediseconomy.admin.editmessage")) { - return Arrays.stream(plugin.getConfigManager().getLangs().getClass().getFields()).filter(field -> field.getType().equals(String.class)).map(Field::getName).toList(); + } else if (args.length == 2 && sender.hasPermission("rediseconomy.admin.editmessage") && args[0].equalsIgnoreCase("editmessage")) { + return Arrays.stream(plugin.getConfigManager().getLangs().getClass().getFields()) + .filter(field -> field.getType().equals(String.class)) + .map(Field::getName) + .filter(name -> name.startsWith(args[1])) + .toList(); } return List.of(); } diff --git a/src/main/java/dev/unnm3d/rediseconomy/command/balance/BalanceSubCommands.java b/src/main/java/dev/unnm3d/rediseconomy/command/balance/BalanceSubCommands.java index 2625cb0..b7e43c0 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/command/balance/BalanceSubCommands.java +++ b/src/main/java/dev/unnm3d/rediseconomy/command/balance/BalanceSubCommands.java @@ -3,6 +3,7 @@ import dev.unnm3d.rediseconomy.RedisEconomyPlugin; import dev.unnm3d.rediseconomy.currency.CurrenciesManager; import dev.unnm3d.rediseconomy.currency.Currency; +import dev.unnm3d.rediseconomy.utils.DecimalUtils; import net.milkbowl.vault.economy.EconomyResponse; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -21,7 +22,12 @@ protected void balancePlayer(CommandSender sender, Currency currency, String tar plugin.langs().send(sender, plugin.langs().playerNotFound); return; } - plugin.langs().send(sender, plugin.langs().balanceOther.replace("%balance%", String.valueOf(currency.format(currency.getBalance(target)))).replace("%player%", target)); + double currentBalance = currency.getBalance(target); + plugin.langs().send(sender, plugin.langs().balanceOther + .replace("%balance%", String.valueOf(currency.format(currentBalance))) + .replace("%balance_short%", DecimalUtils.shortAmount(currentBalance, currency.getDecimalFormat()) + + (currentBalance == 1 ? currency.getCurrencySingular() : currency.getCurrencyPlural())) + .replace("%player%", target)); } @Override @@ -30,7 +36,11 @@ protected void selfBalancePlayer(CommandSender sender, Currency currency) { plugin.langs().send(sender, plugin.langs().noConsole); return; } - plugin.langs().send(sender, plugin.langs().balance.replace("%balance%", String.valueOf(currency.format(currency.getBalance(p))))); + + plugin.langs().send(sender, plugin.langs().balance.replace("%balance_short%", + DecimalUtils.shortAmount(currency.getBalance(p), currency.getDecimalFormat()) + + (currency.getBalance(p) == 1 ? currency.getCurrencySingular() : currency.getCurrencyPlural())) + .replace("%balance%", String.valueOf(currency.format(currency.getBalance(p))))); } @Override diff --git a/src/main/java/dev/unnm3d/rediseconomy/command/balance/BalanceTopCommand.java b/src/main/java/dev/unnm3d/rediseconomy/command/balance/BalanceTopCommand.java index 11330fb..f35b6d2 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/command/balance/BalanceTopCommand.java +++ b/src/main/java/dev/unnm3d/rediseconomy/command/balance/BalanceTopCommand.java @@ -3,6 +3,7 @@ import dev.unnm3d.rediseconomy.RedisEconomyPlugin; import dev.unnm3d.rediseconomy.currency.CurrenciesManager; import dev.unnm3d.rediseconomy.currency.Currency; +import dev.unnm3d.rediseconomy.utils.DecimalUtils; import io.lettuce.core.ScoredValue; import lombok.AllArgsConstructor; import org.bukkit.command.Command; @@ -65,6 +66,9 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command plugin.langs().send(sender, plugin.langs().balanceTopFormat .replace("%pos%", String.valueOf((pageData.pageNumber - 1) * 10 + i)) .replace("%player%", username == null ? tuple.getValue() + "-Unknown" : username) + .replace("%balance_short%", + DecimalUtils.shortAmount(tuple.getScore(), baltopCurrency.getDecimalFormat()) + + (tuple.getScore() == 1 ? baltopCurrency.getCurrencySingular() : baltopCurrency.getCurrencyPlural())) .replace("%balance%", baltopCurrency.format(tuple.getScore()))); i++; } diff --git a/src/main/java/dev/unnm3d/rediseconomy/config/Langs.java b/src/main/java/dev/unnm3d/rediseconomy/config/Langs.java index b68e860..14698f8 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/config/Langs.java +++ b/src/main/java/dev/unnm3d/rediseconomy/config/Langs.java @@ -24,16 +24,16 @@ public final class Langs { public String payCooldown = "Your previous payment is still in progress! Wait please"; public String invalidCurrency = "Invalid currency!"; public String insufficientFunds = "You do not have enough money!"; - public String balance = "You have %balance%!"; + public String balance = "You have %balance_short%!"; public String balanceSet = "You set %player% account to %balance% !"; public String maxBalanceSet = "You set %player% max balance to %amount% !"; - public String balanceOther = "%player% has %balance% !"; + public String balanceOther = "%player% has %balance_short% !"; public String balanceTop = "Top richest players:
%prevpage% %page% %nextpage%"; public String blockedAccounts = "Blocked accounts:
%list%"; public String blockedAccountSuccess = "Account %player% has been blocked!"; public String unblockedAccountSuccess = "Account %player% has been unblocked!"; public String blockedPayment = "Your payments to %player% have been blocked!"; - public String balanceTopFormat = "%pos% - %player% %balance%"; + public String balanceTopFormat = "%pos% - %player% %balance_short%"; public String paySelf = "You cannot pay yourself!"; @Comment("Use %tax_percentage% for tax percentage and %tax_applied% for tax applied to the transaction.") public String paySuccess = "You paid %player% %amount%"; diff --git a/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java b/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java index bc9e00e..05bedf0 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java +++ b/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java @@ -4,7 +4,6 @@ import de.exlll.configlib.Configuration; import java.util.List; -import java.util.UUID; @SuppressWarnings("unused") @Configuration @@ -40,7 +39,7 @@ public class Settings { @Comment("Minimum amount of money that can be paid") public double minPayAmount = 0.01; @Comment({"Currencies", "payTax is the tax on payments, 0.1 = 10% tax"}) - public List currencies = List.of(new CurrencySettings("vault", "euro", "euros", "#.##", "en-US", 0, Double.POSITIVE_INFINITY, 0, true, true, false), new CurrencySettings("dollar", "$", "$", "#.##", "en-US", 0, Double.POSITIVE_INFINITY, 0, false, false, false)); + public List currencies = List.of(new CurrencySettings("vault", "euro", "euros", "#.##", "en-US", 0, 100000000000000d, 0, true, true, false), new CurrencySettings("dollar", "$", "$", "#.##", "en-US", 0, 100000000000000d, 0, false, false, false)); public record CurrencySettings(String currencyName, String currencySingle, String currencyPlural, String decimalFormat, String languageTag, diff --git a/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java b/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java index 579e8d3..629fb31 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java +++ b/src/main/java/dev/unnm3d/rediseconomy/currency/Currency.java @@ -164,7 +164,7 @@ public boolean hasBankSupport() { @Override public int fractionalDigits() { - return 0; + return decimalFormat.getMaximumFractionDigits(); } @Override diff --git a/src/main/java/dev/unnm3d/rediseconomy/utils/DecimalUtils.java b/src/main/java/dev/unnm3d/rediseconomy/utils/DecimalUtils.java new file mode 100644 index 0000000..ff55498 --- /dev/null +++ b/src/main/java/dev/unnm3d/rediseconomy/utils/DecimalUtils.java @@ -0,0 +1,27 @@ +package dev.unnm3d.rediseconomy.utils; + +import dev.unnm3d.rediseconomy.RedisEconomyPlugin; +import lombok.experimental.UtilityClass; + +import java.text.DecimalFormat; + +@UtilityClass +public class DecimalUtils { + + public static String shortAmount(double amount, DecimalFormat decimalFormat) { + if (amount >= 1000000000000.0) { + return decimalFormat.format(amount / 1000000000000.0) + + RedisEconomyPlugin.getInstance().getConfigManager().getLangs().unitSymbols.trillion(); + } else if (amount >= 1000000000.0) { + return decimalFormat.format(amount / 1000000000.0) + + RedisEconomyPlugin.getInstance().getConfigManager().getLangs().unitSymbols.billion(); + } else if (amount >= 1000000.0) { + return decimalFormat.format(amount / 1000000.0) + + RedisEconomyPlugin.getInstance().getConfigManager().getLangs().unitSymbols.million(); + } else if (amount >= 1000.0) { + return decimalFormat.format(amount / 1000.0) + + RedisEconomyPlugin.getInstance().getConfigManager().getLangs().unitSymbols.thousand(); + } + return decimalFormat.format(amount); + } +} From 02b3c72170af26119ad9119641ade31922fe317e Mon Sep 17 00:00:00 2001 From: Emibergo02 <36164338+Emibergo02@users.noreply.github.com> Date: Tue, 31 Dec 2024 16:53:08 +0100 Subject: [PATCH 25/25] 4.3.21 Enhanced registerCalls feature --- pom.xml | 2 +- .../unnm3d/rediseconomy/config/Settings.java | 2 ++ .../transaction/EconomyExchange.java | 30 ++++++++----------- 3 files changed, 15 insertions(+), 19 deletions(-) diff --git a/pom.xml b/pom.xml index e5b59ea..6f073d0 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ dev.unnm3d RedisEconomy - 4.3.20 + 4.3.21 jar RedisEconomy diff --git a/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java b/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java index 05bedf0..402b74a 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java +++ b/src/main/java/dev/unnm3d/rediseconomy/config/Settings.java @@ -18,6 +18,8 @@ public class Settings { public boolean debugUpdateCache = false; @Comment("If true, the plugin registers who's calling it's methods inside transactions") public boolean registerCalls = false; + @Comment("List of regex to be excluded from the registerCalls") + public List callBlacklistRegex = List.of("^org\\.bukkit.*", "^dev\\.unnm3d\\.rediseconomy.*","^com\\.mojang.*"); @Comment({"if true, migrates the bukkit offline uuids accounts to the default RedisEconomy currency", "During the migration, the plugin will be disabled. Restart all RedisEconomy instances after the migration."}) public boolean migrationEnabled = false; diff --git a/src/main/java/dev/unnm3d/rediseconomy/transaction/EconomyExchange.java b/src/main/java/dev/unnm3d/rediseconomy/transaction/EconomyExchange.java index e249caf..2ffbfeb 100644 --- a/src/main/java/dev/unnm3d/rediseconomy/transaction/EconomyExchange.java +++ b/src/main/java/dev/unnm3d/rediseconomy/transaction/EconomyExchange.java @@ -9,10 +9,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; +import java.util.*; import java.util.concurrent.*; import static dev.unnm3d.rediseconomy.redis.RedisKeys.NEW_TRANSACTIONS; @@ -92,16 +89,16 @@ public CompletionStage> savePaymentTransaction(@NotNull UUID sende final CompletableFuture> future = new CompletableFuture<>(); long init = System.currentTimeMillis(); + final String stackTrace = getCallerPluginString(); executorService.submit(() -> { - final String finalReason = reason + getCallerPluginString(); TransactionEvent transactionSenderEvent = new TransactionEvent(new Transaction( new AccountID(sender), System.currentTimeMillis(), new AccountID(target), -amount, currency.getCurrencyName(), - finalReason, + reason + stackTrace, null)); TransactionEvent transactionReceiverEvent = new TransactionEvent(new Transaction( new AccountID(target), @@ -109,7 +106,7 @@ public CompletionStage> savePaymentTransaction(@NotNull UUID sende new AccountID(sender), amount, currency.getCurrencyName(), - finalReason, + reason + stackTrace, null)); plugin.getScheduler().runTask(() -> { @@ -156,12 +153,13 @@ public CompletionStage saveTransaction(@NotNull AccountID accountOwner, final CompletableFuture future = new CompletableFuture<>(); long init = System.currentTimeMillis(); + final String stackTrace = getCallerPluginString(); executorService.submit(() -> { TransactionEvent transactionEvent = new TransactionEvent(new Transaction( accountOwner, System.currentTimeMillis(), target, //If target is null, it has been sent from the server - amount, currency.getCurrencyName(), reason + getCallerPluginString(), null)); + amount, currency.getCurrencyName(), reason + stackTrace, null)); plugin.getScheduler().runTask(() -> plugin.getServer().getPluginManager().callEvent(transactionEvent)); Long longResult = plugin.getCurrenciesManager().getRedisManager().getConnectionSync(commands -> commands.eval( "local currentId=redis.call('hlen', KEYS[1]);" + //Get the current size of the hash @@ -244,16 +242,12 @@ public CompletionStage revertTransaction(AccountID accountOwner, int tr public String getCallerPluginString() { if (!plugin.settings().registerCalls) return ""; - StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); - for (int i = 3; i < stackTraceElements.length; i++) { - if (!stackTraceElements[i].getClassName().startsWith("org.bukkit") && - !stackTraceElements[i].getClassName().startsWith("dev.unnm3d.rediseconomy") && - !stackTraceElements[i].getClassName().startsWith("com.mojang") - ) { - return "\nCall: " + stackTraceElements[i].getClassName() + ":" + stackTraceElements[i].getMethodName(); - } - } - return ""; + return Arrays.stream(Thread.currentThread().getStackTrace()) + .skip(3) + .filter(s -> plugin.settings().callBlacklistRegex.stream().noneMatch(blRegex -> s.getClassName().matches(blRegex))) + .findFirst() + .map(ste -> "\nCall: " + ste.getClassName() + ":" + ste.getMethodName()) + .orElse(""); } }