From f47d0a8642b86a2f6fb6ec270eee7d524327f64c Mon Sep 17 00:00:00 2001 From: AnonymousGCA Date: Mon, 23 Aug 2021 10:42:04 +0200 Subject: [PATCH 001/283] Changelogs: - Mayor changes to SellAll. - Improved performance of SellAll. - New internals for SellAll Commands. - Some GUI changes. - Some changes in the whole project (onEnable changes). - Minor visual changes to GUIs. - Some bug fixes. - Some unmentioned changes. --- docs/changelog_v3.2.x.md | 2 - docs/changelog_v3.3.x.md | 11 + .../autofeatures/AutoFeaturesFileConfig.java | 2 +- .../mcprison/prison/spigot/SpigotPrison.java | 22 +- .../prison/spigot/api/PrisonSpigotAPI.java | 6 +- .../commands/PrisonSpigotSellAllCommands.java | 370 ++- .../spigot/game/SpigotCommandSender.java | 5 +- .../spigot/gui/ListenersPrisonManager.java | 171 +- .../gui/guiutility/SpigotGUIComponents.java | 6 +- .../spigot/gui/sellall/SellAllAdminGUI.java | 2 +- .../prison/spigot/sellall/SellAllUtil.java | 2497 ++++++++--------- 11 files changed, 1551 insertions(+), 1543 deletions(-) diff --git a/docs/changelog_v3.2.x.md b/docs/changelog_v3.2.x.md index f2ec3d3a3..c55bc2e1e 100644 --- a/docs/changelog_v3.2.x.md +++ b/docs/changelog_v3.2.x.md @@ -30,10 +30,8 @@ that you need. # v3.2.6 2021-04-11 - * **v3.2.6 2021-04-11** - * **Start to add in a PrisonMinesBlockEventEvent class.** It has been disabled because it cannot be used yet; the BlockEvents need to under go some major changes to support its use. Currently the BlockEvents receive only references to the sources (block names and not the actual blocks), but in order to hook this up properly, all blocks and details need to be passed. The current system for controlling the BlockEvents is unable to support that kind of an environment right now. It will be changed in the very near future to get this working. diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index a76b3b826..53e5174e9 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -12,7 +12,18 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* +# 3.2.11 2021-08-23 +* **Much better performance for SellAll generally.** + + +* **SellAll Commands internal changes.** + + +* **Minor changes to GUIs:** Some fixes and visual changes. + + +* **SellAllUtil Rewrite:** New internals for SellAll and SellAll API. # v3.2.10 2021-08-22 diff --git a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java index d92b99567..d605b0091 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java +++ b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java @@ -724,7 +724,7 @@ public boolean saveConf() { * initial saving of the data since the original file will not be deleted first. *

* - * @param afConfig + * @param config * @return */ private boolean saveConf( Map config ) { diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPrison.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPrison.java index bf39354bc..f90091301 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPrison.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPrison.java @@ -86,6 +86,7 @@ import tech.mcprison.prison.spigot.permissions.VaultPermissions; import tech.mcprison.prison.spigot.placeholder.MVdWPlaceholderIntegration; import tech.mcprison.prison.spigot.placeholder.PlaceHolderAPIIntegration; +import tech.mcprison.prison.spigot.sellall.SellAllUtil; import tech.mcprison.prison.spigot.slime.SlimeBlockFunEventListener; import tech.mcprison.prison.spigot.spiget.BluesSpigetSemVerComparator; import tech.mcprison.prison.spigot.tasks.PrisonInitialStartupTask; @@ -122,6 +123,7 @@ public class SpigotPrison extends JavaPlugin { private PrisonBlockTypes prisonBlockTypes; private static boolean isBackPacksEnabled = false; + private static boolean isSellAllEnabled = false; private List registeredBlockListeners; @@ -243,6 +245,14 @@ public void onEnableStartup() { Bukkit.getPluginManager().registerEvents(new BackpacksListeners(), this); } + try { + isSellAllEnabled = getConfig().getBoolean("sellall"); + } catch (NullPointerException ignored){} + + if (isSellAllEnabled){ + SellAllUtil.get(); + } + initIntegrations(); @@ -330,7 +340,7 @@ public FileConfiguration getSellAllConfig(){ } public FileConfiguration updateSellAllConfig() { - // Let this like this or it wont update when you do /Sellall etc and will need a server restart. + // Let this like this or it won't update when you do /Sellall etc and will need a server restart. sellAllConfig = new SellAllConfig(); sellAllConfig.initialize(); return sellAllConfig.getFileSellAllConfig(); @@ -364,6 +374,14 @@ public AutoManagerFeatures getAutoFeatures() { return autoFeatures; } + public SellAllUtil getSellAllUtil(){ + return SellAllUtil.get(); + } + + public boolean isSellAllEnabled(){ + return isSellAllEnabled; + } + public void setAutoFeatures( AutoManagerFeatures autoFeatures ) { this.autoFeatures = autoFeatures; } @@ -644,7 +662,7 @@ private void initModulesAndCommands() { // } // Load sellAll if enabled - if (PrisonSpigotSellAllCommands.isEnabled()){ + if (isSellAllEnabled){ Prison.get().getCommandHandler().registerCommands(new PrisonSpigotSellAllCommands()); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonSpigotAPI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonSpigotAPI.java index 496800f69..2d2091b7a 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonSpigotAPI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonSpigotAPI.java @@ -378,7 +378,7 @@ public BackpacksUtil getPrisonBackpacks(){ public SellAllUtil getPrisonSellAll(){ if (sellAll == null){ - sellAll = SellAllUtil.get(); + sellAll = SpigotPrison.getInstance().getSellAllUtil(); } return sellAll; @@ -396,11 +396,11 @@ public SellAllUtil getPrisonSellAll(){ public Double getSellAllMoneyWithMultiplier(Player player){ if (sellAll == null){ - sellAll = SellAllUtil.get(); + sellAll = SpigotPrison.getInstance().getSellAllUtil(); } if (sellAll != null){ - return sellAll.getMoneyWithMultiplier(player, false); + return sellAll.getSellMoney(player); } return null; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotSellAllCommands.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotSellAllCommands.java index 8208feb18..c31952b65 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotSellAllCommands.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotSellAllCommands.java @@ -26,7 +26,6 @@ public class PrisonSpigotSellAllCommands extends PrisonSpigotBaseCommands { private static PrisonSpigotSellAllCommands instance; - private SellAllUtil sellAllUtil = SellAllUtil.get(); private final Configuration messages = SpigotPrison.getInstance().getMessagesConfig(); /** @@ -51,7 +50,7 @@ public static PrisonSpigotSellAllCommands get() { @Command(identifier = "sellall set currency", description = "SellAll set currency command", onlyPlayers = false, permissions = "prison.sellall.currency") private void sellAllCurrency(CommandSender sender, - @Arg(name = "currency", description = "Currency name.", def = "default") @Wildcard String currency){ + @Arg(name = "currency", description = "Currency name.", def = "default") @Wildcard String currency){ EconomyCurrencyIntegration currencyEcon = PrisonAPI.getIntegrationManager().getEconomyForCurrency(currency); if (currencyEcon == null && !currency.equalsIgnoreCase("default")) { @@ -59,9 +58,14 @@ private void sellAllCurrency(CommandSender sender, return; } - if (sellAllUtil.setCurrency(currency)) return; + SellAllUtil sellAllUtil = SellAllUtil.get(); + if (sellAllUtil == null){ + return; + } - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllCurrencyEditedSuccess") + " [" + sellAllUtil.getSellAllConfig().getString("Options.SellAll_Currency") + "]")); + if (sellAllUtil.setCurrency(currency)){ + Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllCurrencyEditedSuccess") + " [" + currency + "]")); + } } @Command(identifier = "sellall", description = "SellAll main command", onlyPlayers = false) @@ -70,10 +74,10 @@ private void sellAllCommands(CommandSender sender) { if (!isEnabled()) return; if (sender.hasPermission("prison.admin")) { - String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "sellall help" ); + String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "sellall help" ); sender.dispatchCommand(registeredCmd); } else { - String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "sellall sell" ); + String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "sellall sell" ); sender.dispatchCommand(registeredCmd); } } @@ -89,9 +93,14 @@ private void sellAllDelay(CommandSender sender, return; } + SellAllUtil sellAllUtil = SellAllUtil.get(); + + if (sellAllUtil == null){ + return; + } + boolean enableBoolean = getBoolean(enable); - boolean sellDelayEnabled = getBoolean(sellAllUtil.getSellAllConfig().getString("Options.Sell_Delay_Enabled")); - if (sellDelayEnabled == enableBoolean){ + if (sellAllUtil.isSellAllDelayEnabled == enableBoolean){ if (enableBoolean){ Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllDelayAlreadyEnabled"))); } else { @@ -100,21 +109,26 @@ private void sellAllDelay(CommandSender sender, return; } - if (sellAllUtil.enableDelay(enableBoolean)) return; - - if (enableBoolean){ - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllDelayEnabled"))); - } else { - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllDelayDisabled"))); + if (sellAllUtil.setDelayEnable(enableBoolean)){ + if (enableBoolean){ + Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllDelayEnabled"))); + } else { + Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllDelayDisabled"))); + } } } @Command(identifier = "sellall set delay", description = "Edit SellAll delay.", onlyPlayers = false, permissions = "prison.sellall.delay") private void sellAllDelaySet(CommandSender sender, - @Arg(name = "delay", description = "Set delay value in seconds.", def = "0") String delay){ + @Arg(name = "delay", description = "Set delay value in seconds.", def = "0") String delay){ if (!isEnabled()) return; + SellAllUtil sellAllUtil = SellAllUtil.get(); + if (sellAllUtil == null){ + return; + } + int delayValue; try { delayValue = Integer.parseInt(delay); @@ -123,9 +137,9 @@ private void sellAllDelaySet(CommandSender sender, return; } - if (sellAllUtil.setDelay(delayValue)) return; - - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllDelayEditedWithSuccess") + " [" + delayValue + "s]")); + if (sellAllUtil.setDelay(delayValue)){ + Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllDelayEditedWithSuccess") + " [" + delayValue + "s]")); + } } @Command(identifier = "sellall autosell", description = "Enable SellAll AutoSell.", onlyPlayers = false, permissions = "prison.autosell.edit") @@ -144,9 +158,13 @@ private void sellAllAutoSell(CommandSender sender, return; } + SellAllUtil sellAllUtil = SellAllUtil.get(); + if (sellAllUtil == null){ + return; + } + boolean enableBoolean = getBoolean(enable); - boolean fullInvAutoSellEnabled = getBoolean(sellAllUtil.getSellAllConfig().getString("Options.Full_Inv_AutoSell")); - if (fullInvAutoSellEnabled == enableBoolean){ + if (sellAllUtil.isAutoSellEnabled == enableBoolean){ if (enableBoolean){ Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllAutoSellAlreadyEnabled"))); } else { @@ -155,12 +173,12 @@ private void sellAllAutoSell(CommandSender sender, return; } - if (sellAllUtil.enableAutoSell(enableBoolean)) return; - - if (enableBoolean){ - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllAutoSellEnabled"))); - } else { - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllAutoSellDisabled"))); + if (sellAllUtil.setAutoSell(enableBoolean)){ + if (enableBoolean){ + Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllAutoSellEnabled"))); + } else { + Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllAutoSellDisabled"))); + } } } @@ -175,9 +193,13 @@ private void sellAllAutoSellPerUserToggleable(CommandSender sender, return; } + SellAllUtil sellAllUtil = SellAllUtil.get(); + if (sellAllUtil == null){ + return; + } + boolean enableBoolean = getBoolean(enable); - boolean perUserToggleableEnabled = getBoolean(sellAllUtil.getSellAllConfig().getString("Options.Full_Inv_AutoSell_perUserToggleable")); - if (perUserToggleableEnabled == enableBoolean){ + if (sellAllUtil.isAutoSellPerUserToggleable == enableBoolean){ if (enableBoolean){ Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllAutoPerUserToggleableAlreadyEnabled"))); } else { @@ -186,20 +208,20 @@ private void sellAllAutoSellPerUserToggleable(CommandSender sender, return; } - if (sellAllUtil.enableAutoSellPerUserToggleable(enableBoolean)) return; - - if (enableBoolean){ - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllAutoPerUserToggleableEnabled"))); - } else { - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllAutoPerUserToggleableDisabled"))); + if (sellAllUtil.setAutoSellPerUserToggleable(enableBoolean)){ + if (enableBoolean){ + Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllAutoPerUserToggleableEnabled"))); + } else { + Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllAutoPerUserToggleableDisabled"))); + } } } @Command(identifier = "sellall sell", description = "SellAll sell command", onlyPlayers = true) - public void sellAllSellCommand(CommandSender sender, - @Arg(name = "notification", def="", - description = "Notification about the sellall transaction. Defaults to normal. " + - "'silent' suppresses results. [silent]") String notification ){ + public void sellAllSellCommand(CommandSender sender, + @Arg(name = "notification", def="", + description = "Notification about the sellall transaction. Defaults to normal. " + + "'silent' suppresses results. [silent]") String notification ){ if (!isEnabled()) return; @@ -210,21 +232,50 @@ public void sellAllSellCommand(CommandSender sender, return; } - if (sellAllUtil.isDisabledWorld(p)) return; + SellAllUtil sellAllUtil = SellAllUtil.get(); + if (sellAllUtil == null){ + return; + } + + if (sellAllUtil.isPlayerInDisabledWorld(p)) return; - boolean sellPermissionEnabled = getBoolean(sellAllUtil.getSellAllConfig().getString("Options.Sell_Permission_Enabled")); - if (sellPermissionEnabled){ - String permission = sellAllUtil.getSellAllConfig().getString("Options.Sell_Permission"); + if (sellAllUtil.isSellAllSellPermissionEnabled){ + String permission = sellAllUtil.permissionSellAllSell; if (permission == null || !p.hasPermission(permission)){ Output.get().sendWarn(new SpigotPlayer(p), SpigotPrison.format(messages.getString("Message.SellAllMissingPermission") + " [" + permission + "]")); return; } } - boolean notifications = !(notification != null && "silent".equalsIgnoreCase( notification )); - boolean bySignOnly = notification != null && "bySignOnly".equalsIgnoreCase( notification ); + boolean notifications = (notification != null && "silent".equalsIgnoreCase( notification )); - sellAllUtil.sellAllSell(p, notifications, bySignOnly); + sellAllUtil.sellAllSell(p, false, notifications, true, true, false, true); + } + + public void sellAllSell(Player p){ + if (!isEnabled()) return; + + if (p == null){ + Output.get().sendInfo(new SpigotPlayer(p), SpigotPrison.format("&cSorry but you can't use that from the console!")); + return; + } + + SellAllUtil sellAllUtil = SellAllUtil.get(); + if (sellAllUtil == null){ + return; + } + + if (sellAllUtil.isPlayerInDisabledWorld(p)) return; + + if (sellAllUtil.isSellAllSellPermissionEnabled){ + String permission = sellAllUtil.permissionSellAllSell; + if (permission == null || !p.hasPermission(permission)){ + Output.get().sendWarn(new SpigotPlayer(p), SpigotPrison.format(messages.getString("Message.SellAllMissingPermission") + " [" + permission + "]")); + return; + } + } + + sellAllUtil.sellAllSell(p, true, false, true, true, false, true); } @Command(identifier = "sellall delaysell", description = "Like SellAll Sell command but this will be delayed for some " + @@ -243,24 +294,27 @@ public void sellAllSellWithDelayCommand(CommandSender sender){ return; } - if (sellAllUtil.isDisabledWorld(p)) return; + SellAllUtil sellAllUtil = SellAllUtil.get(); + if (sellAllUtil == null){ + return; + } - boolean sellPermissionEnabled = getBoolean(sellAllUtil.getSellAllConfig().getString("Options.Sell_Permission_Enabled")); - if (sellPermissionEnabled){ - String permission = sellAllUtil.getSellAllConfig().getString("Options.Sell_Permission"); + if (sellAllUtil.isPlayerInDisabledWorld(p)) return; + + if (sellAllUtil.isSellAllSellPermissionEnabled){ + String permission = sellAllUtil.permissionSellAllSell; if (permission == null || !p.hasPermission(permission)){ Output.get().sendWarn(new SpigotPlayer(p), SpigotPrison.format(messages.getString("Message.SellAllMissingPermission") + " [" + permission + "]")); return; } } - if (!getBoolean(sellAllUtil.sellAllConfig.getString("Options.Full_Inv_AutoSell_EarnedMoneyNotificationDelay_Enabled"))){ + if (!sellAllUtil.isAutoSellEarningNotificationDelayEnabled){ sellAllSellCommand(sender, "silent"); return; } - SellAllUtil.get().addToAutoSellTask(p); - sellAllSellCommand(sender, "silent"); + sellAllUtil.sellAllSell(p, false, false, false, false, true, false); } @@ -277,21 +331,30 @@ private void sellAllAutoEnableUser(CommandSender sender){ return; } - if (sellAllUtil.isDisabledWorld(p)) return; + SellAllUtil sellAllUtil = SellAllUtil.get(); + if (sellAllUtil == null){ + return; + } + + if (sellAllUtil.isPlayerInDisabledWorld(p)) return; - boolean perUserToggleableEnabled = getBoolean(sellAllUtil.getSellAllConfig().getString("Options.Full_Inv_AutoSell_perUserToggleable")); - if (!perUserToggleableEnabled){ + if (!sellAllUtil.isAutoSellPerUserToggleable){ return; } - boolean perUserToggleablePermEnabled = getBoolean(sellAllUtil.getSellAllConfig().getString("Options.Full_Inv_AutoSell_perUserToggleable_Need_Perm")); - String permission = sellAllUtil.getSellAllConfig().getString("Options.Full_Inv_AutoSell_PerUserToggleable_Permission"); - if (perUserToggleablePermEnabled && (permission != null && !p.hasPermission(permission))){ + String permission = sellAllUtil.permissionAutoSellPerUserToggleable; + if (sellAllUtil.isAutoSellPerUserToggleablePermEnabled && (permission != null && !p.hasPermission(permission))){ Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllMissingPermissionToToggleAutoSell") + " [" + permission + "]")); return; } - if (sellAllUtil.autoSellPlayerToggle(p)) return; + if (sellAllUtil.setAutoSellPlayer(p, !sellAllUtil.isPlayerAutoSellEnabled(p))){ + if (sellAllUtil.isPlayerAutoSellEnabled(p)){ + Output.get().sendInfo(new SpigotPlayer(p), SpigotPrison.format(messages.getString("Message.SellAllAutoEnabled"))); + } else { + Output.get().sendInfo(new SpigotPlayer(p), SpigotPrison.format(messages.getString("Message.SellAllAutoDisabled"))); + } + } } @Command(identifier = "sellall gui", description = "SellAll GUI command", altPermissions = "prison.admin", onlyPlayers = true) @@ -307,11 +370,16 @@ private void sellAllGuiCommand(CommandSender sender){ return; } - if (sellAllUtil.openGUI(p)) return; + SellAllUtil sellAllUtil = SellAllUtil.get(); + if (sellAllUtil == null){ + return; + } - // If the sender's an admin (OP or have the prison.admin permission) it'll send an error message. - if (p.hasPermission("prison.admin")) { - Output.get().sendError(sender, SpigotPrison.format(messages.getString("Message.SellAllGUIDisabled"))); + if (!sellAllUtil.openSellAllGUI(p)){ + // If the sender's an admin (OP or have the prison.admin permission) it'll send an error message. + if (p.hasPermission("prison.admin")) { + Output.get().sendError(sender, SpigotPrison.format(messages.getString("Message.SellAllGUIDisabled"))); + } } } @@ -333,7 +401,12 @@ private void sellAllAddCommand(CommandSender sender, return; } - if (sellAllUtil.getSellAllConfig().getConfigurationSection("Items." + itemID) != null){ + SellAllUtil sellAllUtil = SellAllUtil.get(); + if (sellAllUtil == null){ + return; + } + + if (sellAllUtil.sellAllConfig.getConfigurationSection("Items." + itemID) != null){ Output.get().sendWarn(sender, SpigotPrison.format(itemID + messages.getString("Message.SellAllAlreadyAdded"))); return; } @@ -347,14 +420,13 @@ private void sellAllAddCommand(CommandSender sender, return; } - if (sellAllUtil.addBlock(blockAdd, value)) return; + if (sellAllUtil.addSellAllBlock(blockAdd, value)){ + Output.get().sendInfo(sender, SpigotPrison.format("&3 ITEM [" + itemID + ", " + value + messages.getString("Message.SellAllAddSuccess"))); + } } catch (IllegalArgumentException ex){ Output.get().sendError(sender, SpigotPrison.format(messages.getString("Message.SellAllWrongID") + " [" + itemID + "]")); - return; } - - Output.get().sendInfo(sender, SpigotPrison.format("&3 ITEM [" + itemID + ", " + value + messages.getString("Message.SellAllAddSuccess"))); } /** @@ -367,14 +439,19 @@ private void sellAllAddCommand(CommandSender sender, */ public void sellAllAddCommand(XMaterial blockAdd, Double value){ - String itemID = blockAdd.name(); + String itemID = blockAdd.name(); + + SellAllUtil sellAllUtil = SellAllUtil.get(); + if (sellAllUtil == null){ + return; + } - // If the block or item was already configured, then skip this: - if (sellAllUtil.getSellAllConfig().getConfigurationSection("Items." + itemID) != null){ + // If the block or item was already configured, then skip this: + if (sellAllUtil.sellAllConfig.getConfigurationSection("Items." + itemID) != null){ return; } - if (sellAllUtil.addBlock(blockAdd, value)) return; + if (sellAllUtil.addSellAllBlock(blockAdd, value)) return; Output.get().logInfo(SpigotPrison.format("&3 ITEM [" + itemID + ", " + value + messages.getString("Message.SellAllAddSuccess"))); } @@ -388,15 +465,23 @@ private void sellAllDeleteCommand(CommandSender sender, @Arg(name = "Item_ID", d Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllMissingID"))); return; } + itemID = itemID.toUpperCase(); - if (sellAllUtil.getSellAllConfig().getConfigurationSection("Items." + itemID) == null){ - Output.get().sendWarn(sender, SpigotPrison.format(itemID + messages.getString("Message.SellAllNotFoundStringConfig"))); + SellAllUtil sellAllUtil = SellAllUtil.get(); + if (sellAllUtil == null){ return; } - if (sellAllUtil.deleteBlock(itemID)) return; + if (sellAllUtil.sellAllConfig.getConfigurationSection("Items." + itemID) == null){ + Output.get().sendWarn(sender, SpigotPrison.format(itemID + messages.getString("Message.SellAllNotFoundStringConfig"))); + return; + } - Output.get().sendInfo(sender, SpigotPrison.format(itemID + messages.getString("Message.SellAllDeletedSuccess"))); + if (XMaterial.matchXMaterial(itemID).isPresent()) { + if (sellAllUtil.removeSellAllBlock(XMaterial.matchXMaterial(itemID).get())) { + Output.get().sendInfo(sender, SpigotPrison.format(itemID + messages.getString("Message.SellAllDeletedSuccess"))); + } + } } @Command(identifier = "sellall edit", description = "SellAll edit command, edit an item of Shop.", permissions = "prison.admin", onlyPlayers = false) @@ -417,7 +502,12 @@ private void sellAllEditCommand(CommandSender sender, return; } - if (sellAllUtil.getSellAllConfig().getConfigurationSection("Items." + itemID) == null){ + SellAllUtil sellAllUtil = SellAllUtil.get(); + if (sellAllUtil == null){ + return; + } + + if (sellAllUtil.sellAllConfig.getConfigurationSection("Items." + itemID) == null){ Output.get().sendWarn(sender, SpigotPrison.format(itemID + messages.getString("Message.SellAllNotFoundEdit"))); return; } @@ -431,14 +521,13 @@ private void sellAllEditCommand(CommandSender sender, return; } - if (sellAllUtil.editBlock(blockAdd, value)) return; + if (sellAllUtil.editPrice(blockAdd, value)){ + Output.get().sendInfo(sender, SpigotPrison.format("&3ITEM [" + itemID + ", " + value + messages.getString("Message.SellAllCommandEditSuccess"))); + } } catch (IllegalArgumentException ex){ Output.get().sendError(sender, SpigotPrison.format(messages.getString("Message.SellAllWrongID") + " [" + itemID + "]")); - return; } - - Output.get().sendInfo(sender, SpigotPrison.format("&3ITEM [" + itemID + ", " + value + messages.getString("Message.SellAllCommandEditSuccess"))); } @Command(identifier = "sellall multiplier", description = "SellAll multiplier command list", permissions = "prison.admin", onlyPlayers = false) @@ -446,8 +535,12 @@ private void sellAllMultiplierCommand(CommandSender sender){ if (!isEnabled()) return; - boolean multiplierEnabled = getBoolean(sellAllUtil.getSellAllConfig().getString("Options.Multiplier_Enabled")); - if (!multiplierEnabled){ + SellAllUtil sellAllUtil = SellAllUtil.get(); + if (sellAllUtil == null){ + return; + } + + if (!sellAllUtil.isSellAllMultiplierEnabled){ Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllMultipliersAreDisabled"))); return; } @@ -456,7 +549,9 @@ private void sellAllMultiplierCommand(CommandSender sender){ sender.dispatchCommand(registeredCmd); } - @Command(identifier = "sellall multiplier add", description = "SellAll add a multiplier. Permission multipliers for player's prison.sellall.multiplier., example prison.sellall.multiplier.2 will add a 2x multiplier", + @Command(identifier = "sellall multiplier add", description = "SellAll add a multiplier. Permission multipliers for player's prison.sellall.multiplier., example prison.sellall.multiplier.2 will add a 2x multiplier," + + "There's also another kind of Multiplier called permission multipliers, they're permissions that you can give to players to give them a multiplier, remember that their format is prison.sellall.multiplier.2 (for example), and this example will give you a " + + "total of 3x multiplier (1x default + 2x permission = 3x).", permissions = "prison.admin", onlyPlayers = false) private void sellAllAddMultiplierCommand(CommandSender sender, @Arg(name = "Prestige", description = "Prestige to hook to the multiplier.") String prestige, @@ -464,15 +559,19 @@ private void sellAllAddMultiplierCommand(CommandSender sender, if (!isEnabled()) return; - boolean multiplierEnabled = getBoolean(sellAllUtil.getSellAllConfig().getString("Options.Multiplier_Enabled")); - if (!multiplierEnabled){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllMultipliersAreDisabled"))); + SellAllUtil sellAllUtil = SellAllUtil.get(); + if (sellAllUtil == null){ return; } - if (sellAllUtil.addMultiplier(prestige, multiplier)) return; + if (!sellAllUtil.isSellAllMultiplierEnabled){ + Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllMultipliersAreDisabled"))); + return; + } - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllMultiplierEditSaveSuccess"))); + if (sellAllUtil.addPrestigeMultiplier(prestige, multiplier)){ + Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllMultiplierEditSaveSuccess"))); + } } @Command(identifier = "sellall multiplier delete", description = "SellAll delete a multiplier.", permissions = "prison.admin", onlyPlayers = false) @@ -481,15 +580,13 @@ private void sellAllDeleteMultiplierCommand(CommandSender sender, if (!isEnabled()) return; - boolean multiplierEnabled = getBoolean(sellAllUtil.getSellAllConfig().getString("Options.Multiplier_Enabled")); - if (!multiplierEnabled){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllMultipliersAreDisabled"))); + SellAllUtil sellAllUtil = SellAllUtil.get(); + if (sellAllUtil == null){ return; } - String permission = sellAllUtil.getSellAllConfig().getString("Options.Multiplier_Command_Permission"); - if (permission != null && !sender.hasPermission(permission)){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllMissingPermission") + " [" + permission + "]")); + if (!sellAllUtil.isSellAllMultiplierEnabled){ + Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllMultipliersAreDisabled"))); return; } @@ -498,14 +595,14 @@ private void sellAllDeleteMultiplierCommand(CommandSender sender, return; } - if (sellAllUtil.getSellAllConfig().getConfigurationSection("Multiplier." + prestige) == null){ + if (sellAllUtil.sellAllConfig.getConfigurationSection("Multiplier." + prestige) == null){ Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllCantFindMultiplier") + prestige + messages.getString("Message.SellAllCantFindMultiplier2"))); return; } - if (sellAllUtil.deleteMultiplier(prestige)) return; - - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllMultiplierDeleteSuccess"))); + if (sellAllUtil.removePrestigeMultiplier(prestige)){ + Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllMultiplierDeleteSuccess"))); + } } @Command(identifier = "sellall Trigger", description = "Toggle SellAll Shift+Right Click on a tool to trigger the /sellall sell command, true -> Enabled or False -> Disabled.", permissions = "prison.admin", onlyPlayers = false) @@ -515,7 +612,7 @@ private void sellAllToolsTriggerToggle(CommandSender sender, if (!isEnabled()) return; if (enable.equalsIgnoreCase("null")){ - String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "sellall toolsTrigger help" ); + String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "sellall toolsTrigger help" ); sender.dispatchCommand(registeredCmd); return; } @@ -525,25 +622,27 @@ private void sellAllToolsTriggerToggle(CommandSender sender, return; } - boolean sellAllTriggerStatus = getBoolean(sellAllUtil.getSellAllConfig().getString("Options.ShiftAndRightClickSellAll.Enabled")); - boolean enableInput = getBoolean(enable); - if (sellAllTriggerStatus == enableInput) { - if (sellAllTriggerStatus) { + SellAllUtil sellAllUtil = SellAllUtil.get(); + if (sellAllUtil == null){ + return; + } + boolean enableInput = getBoolean(enable); + if (sellAllUtil.isSellAllItemTriggerEnabled == enableInput) { + if (sellAllUtil.isSellAllItemTriggerEnabled) { Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllTriggerAlreadyEnabled"))); } else { - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllTriggerAlreadyDisabled"))); } return; } - if (sellAllUtil.toggleItemTrigger(enableInput)) return; - - if (enableInput){ - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllTriggerEnabled"))); - } else { - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllTriggerDisabled"))); + if (sellAllUtil.setItemTrigger(enableInput)){ + if (enableInput){ + Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllTriggerEnabled"))); + } else { + Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllTriggerDisabled"))); + } } } @@ -553,8 +652,12 @@ private void sellAllTriggerAdd(CommandSender sender, if (!isEnabled()) return; - boolean sellAllTriggerStatus = getBoolean(sellAllUtil.getSellAllConfig().getString("Options.ShiftAndRightClickSellAll.Enabled")); - if (!sellAllTriggerStatus){ + SellAllUtil sellAllUtil = SellAllUtil.get(); + if (sellAllUtil == null){ + return; + } + + if (!sellAllUtil.isSellAllItemTriggerEnabled){ Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllTriggerIsDisabled"))); return; } @@ -574,23 +677,26 @@ private void sellAllTriggerAdd(CommandSender sender, return; } - if (sellAllUtil.addItemTrigger(blockAdd)) return; + if (sellAllUtil.addItemTrigger(blockAdd)){ + Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllTriggerItemAddSuccess") + " [" + itemID + "]")); + } } catch (IllegalArgumentException ex){ Output.get().sendError(sender, SpigotPrison.format(messages.getString("Message.SellAllWrongID") + " [" + itemID + "]")); - return; } - - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllTriggerItemAddSuccess") + " [" + itemID + " ]")); } @Command(identifier = "sellall Trigger delete", description = "Delete an Item from the Shift+Right Click trigger -> /sellall sell command.", permissions = "prison.admin", onlyPlayers = false) private void sellAllTriggerDelete(CommandSender sender, - @Arg(name = "Item", description = "Item name") String itemID){ + @Arg(name = "Item", description = "Item name") String itemID){ if (!isEnabled()) return; - boolean sellAllTriggerStatus = getBoolean(sellAllUtil.getSellAllConfig().getString("Options.ShiftAndRightClickSellAll.Enabled")); - if (!sellAllTriggerStatus){ + SellAllUtil sellAllUtil = SellAllUtil.get(); + if (sellAllUtil == null){ + return; + } + + if (!sellAllUtil.isSellAllItemTriggerEnabled){ Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllTriggerIsDisabled"))); return; } @@ -601,15 +707,20 @@ private void sellAllTriggerDelete(CommandSender sender, } itemID = itemID.toUpperCase(); - if (sellAllUtil.getSellAllConfig().getString("Options.ShiftAndRightClickSellAll.Items." + itemID + ".ITEM_ID") == null){ + if (!XMaterial.matchXMaterial(itemID).isPresent()){ + Output.get().sendError(sender, SpigotPrison.format(messages.getString("Message.SellAllWrongID") + " [" + itemID + "]")); + return; + } + XMaterial xMaterial = XMaterial.matchXMaterial(itemID).get(); + if (!sellAllUtil.getItemTriggerXMaterials().contains(xMaterial)){ Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllTriggerMissingItem"))); return; } - if (sellAllUtil.deleteItemTrigger(itemID)) return; - - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllTriggerItemDeleteSuccess") + " [" + itemID + " ]")); + if (sellAllUtil.removeItemTrigger(xMaterial)) { + Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllTriggerItemDeleteSuccess") + " [" + itemID + "]")); + } } @Command(identifier = "sellall setdefault", description = "SellAll default values ready to go.", permissions = "prison.admin", onlyPlayers = false) @@ -617,14 +728,15 @@ private void sellAllSetDefaultCommand(CommandSender sender){ if (!isEnabled()) return; - // Setup all the prices in sellall: + // Setup all the prices in sellall: SpigotPlatform platform = (SpigotPlatform) Prison.get().getPlatform(); - for ( SellAllBlockData xMatCost : platform.buildBlockListXMaterial() ) { + for ( SellAllBlockData xMatCost : platform.buildBlockListXMaterial() ) { - // Add blocks to sellall: - sellAllAddCommand( xMatCost.getBlock(), xMatCost.getPrice() ); - } + // Add blocks to sellall: + sellAllAddCommand(sender, xMatCost.getBlock().name(), xMatCost.getPrice() ); + } Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllDefaultSuccess"))); } } + diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotCommandSender.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotCommandSender.java index b89ea0601..455b3d0e4 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotCommandSender.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotCommandSender.java @@ -32,6 +32,7 @@ import tech.mcprison.prison.integration.PermissionIntegration; import tech.mcprison.prison.internal.CommandSender; import tech.mcprison.prison.internal.Player; +import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.sellall.SellAllUtil; import tech.mcprison.prison.util.Text; @@ -136,10 +137,10 @@ public double getSellAllMultiplier() { if ( isPlayer() ) { - SellAllUtil sellall = SellAllUtil.get(); + SellAllUtil sellall = SpigotPrison.getInstance().getSellAllUtil(); if ( sellall != null && getWrapper() != null ) { - results = sellall.getMultiplier( new SpigotPlayer( (org.bukkit.entity.Player) getWrapper() ) ); + results = sellall.getPlayerMultiplier((org.bukkit.entity.Player) getWrapper()); } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java index 97d5fb1bf..867df1576 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java @@ -5,7 +5,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; -import java.util.Set; import org.bukkit.Bukkit; import org.bukkit.Material; @@ -43,6 +42,7 @@ import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.SpigotUtil; import tech.mcprison.prison.spigot.backpacks.BackpacksUtil; +import tech.mcprison.prison.spigot.commands.PrisonSpigotSellAllCommands; import tech.mcprison.prison.spigot.compat.Compatibility; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.autofeatures.SpigotAutoBlockGUI; @@ -76,6 +76,7 @@ import tech.mcprison.prison.spigot.gui.sellall.SellAllPrestigesMultiplierGUI; import tech.mcprison.prison.spigot.gui.sellall.SellAllPrestigesSetMultiplierGUI; import tech.mcprison.prison.spigot.gui.sellall.SellAllPriceGUI; +import tech.mcprison.prison.spigot.sellall.SellAllUtil; /** * @author GABRYCA @@ -92,9 +93,6 @@ public class ListenersPrisonManager implements Listener { private final Configuration config = SpigotPrison.getInstance().getConfig(); private final Configuration guiConfig = SpigotPrison.getInstance().getGuiConfig(); - // NOTE: sellAllConfig will be null if sellall is not enbled. - private Configuration sellAllConfig = SpigotPrison.getInstance().updateSellAllConfig(); - private final Configuration messages = SpigotPrison.getInstance().getMessagesConfig(); boolean guiNotEnabled = !(config.getString("prison-gui-enabled").equalsIgnoreCase("true")); private Optional ladder; @@ -144,19 +142,19 @@ public void addChatEventPlayer(Player p){ @EventHandler(priority = EventPriority.HIGHEST) public void onSignEditing(SignChangeEvent e){ - sellAllConfig = SpigotPrison.getInstance().getSellAllConfig(); - - if (sellAllConfig == null){ + if (!SpigotPrison.getInstance().isSellAllEnabled()){ return; } + SellAllUtil sellAllUtil = SpigotPrison.getInstance().getSellAllUtil(); + // Check if the feature's enabled - if (!getBoolean(sellAllConfig.getString("Options.SellAll_Sign_Enabled"))){ + if (!sellAllUtil.isSellAllSignEnabled){ return; } Player p = e.getPlayer(); - String signTag = sellAllConfig.getString("Options.SellAll_Sign_Visible_Tag"); + String signTag = sellAllUtil.sellAllSignTag;; if (signTag == null){ signTag = "&7[&3SellAll&7]"; } @@ -179,43 +177,42 @@ public void onSignEditing(SignChangeEvent e){ @EventHandler(priority = EventPriority.MONITOR) public void onPlayerInteractEvent(PlayerInteractEvent e){ - sellAllConfig = SpigotPrison.getInstance().getSellAllConfig(); - if (sellAllConfig != null) { + if (!SpigotPrison.getInstance().isSellAllEnabled()){ + return; + } - // Check if SellAll Shift + Right Click is enabled. - boolean sellAllTriggerEnabled = getBoolean(sellAllConfig.getString("Options.ShiftAndRightClickSellAll.Enabled")); - if (sellAllTriggerEnabled) { - // Check if the action if Shift + Right Click. - Player p = e.getPlayer(); - if (e.getAction().equals(Action.RIGHT_CLICK_AIR) && p.isSneaking()) { - - // Check if a permission's required. - boolean permissionSellAllTriggerEnabled = getBoolean(sellAllConfig.getString("Options.ShiftAndRightClickSellAll.PermissionEnabled")); - if (permissionSellAllTriggerEnabled) { - String permission = sellAllConfig.getString("Options.ShiftAndRightClickSellAll.Permission"); - if (permission != null && !p.hasPermission(permission)) { - return; - } + SellAllUtil sellAllUtil = SpigotPrison.getInstance().getSellAllUtil(); + + // Check if SellAll Shift + Right Click is enabled. + if (sellAllUtil.isSellAllItemTriggerEnabled) { + // Check if the action if Shift + Right Click. + Player p = e.getPlayer(); + if (e.getAction().equals(Action.RIGHT_CLICK_AIR) && p.isSneaking()) { + + // Check if a permission's required. + if (sellAllUtil.isSellAllItemTriggerPermissionEnabled) { + String permission = sellAllUtil.permissionItemTrigger; + if (permission != null && !p.hasPermission(permission)) { + return; } + } - // Get the Items config section - Set items = null; - try { - items = sellAllConfig.getConfigurationSection("ShiftAndRightClickSellAll.Items").getKeys(false); - } catch (NullPointerException ignored) {} - if (items != null && items.size() != 0) { - for (String itemID : items) { - XMaterial xMaterialConf = SpigotUtil.getXMaterial(sellAllConfig.getString("ShiftAndRightClickSellAll.Items." + itemID + ".ITEM_ID")); - XMaterial inHandXMaterial = null; - if (e.getItem() != null){ - inHandXMaterial = SpigotUtil.getXMaterial(e.getItem().getType()); - } - if (inHandXMaterial != null && xMaterialConf == inHandXMaterial) { - String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "sellall sell" ); + // Get the Items config section + ArrayList items = sellAllUtil.getItemTriggerXMaterials(); + + if (items != null && items.size() != 0) { + XMaterial inHandXMaterial = null; + if (e.getItem() != null){ + inHandXMaterial = SpigotUtil.getXMaterial(e.getItem().getType()); + } + if (inHandXMaterial != null) { + for (XMaterial xMaterialConf : items) { + if (xMaterialConf == inHandXMaterial) { + String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand("sellall sell"); Bukkit.dispatchCommand(p, registeredCmd); return; - } else if (xMaterialConf == SpigotUtil.getXMaterial(p.getInventory().getItemInMainHand().getType())){ - String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "sellall sell" ); + } else if (xMaterialConf == SpigotUtil.getXMaterial(p.getInventory().getItemInMainHand().getType())) { + String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand("sellall sell"); Bukkit.dispatchCommand(p, registeredCmd); return; } @@ -223,63 +220,56 @@ public void onPlayerInteractEvent(PlayerInteractEvent e){ } } } + } - // Check if the feature's enabled. - boolean sellAllSignEnabled = getBoolean(sellAllConfig.getString("Options.SellAll_Sign_Enabled")); - if (sellAllSignEnabled) { - - // Get clicked block. - Material clickedBlock = null; - if (e.getClickedBlock() != null){ - clickedBlock = e.getClickedBlock().getType(); - } - - // Check if the clicked block's a sign - if (clickedBlock == Material.SIGN || clickedBlock == Material.WALL_SIGN) { + // Check if the feature's enabled. + if (sellAllUtil.isSellAllSignEnabled) { - // Get the player - Player p = e.getPlayer(); - String signTag = sellAllConfig.getString("Options.SellAll_Sign_Visible_Tag"); - if (signTag == null) { - signTag = "&7[&3SellAll&7]"; - } + // Get clicked block. + Material clickedBlock = null; + if (e.getClickedBlock() != null){ + clickedBlock = e.getClickedBlock().getType(); + } - // Get the action - Action action = e.getAction(); + // Check if the clicked block's a sign + if (clickedBlock == Material.SIGN || clickedBlock == Material.WALL_SIGN) { - // Check if the action's a click - if (action == Action.RIGHT_CLICK_BLOCK || action == Action.LEFT_CLICK_BLOCK) { + // Get the player + Player p = e.getPlayer(); + String signTag = sellAllUtil.sellAllSignTag; + if (signTag == null) { + signTag = "&7[&3SellAll&7]"; + } - // Get sign - Sign sign = (Sign) e.getClickedBlock().getState(); + // Get the action + Action action = e.getAction(); - // If there aren't lines in the sign this will void an error - try { + // Check if the action's a click + if (action == Action.RIGHT_CLICK_BLOCK || action == Action.LEFT_CLICK_BLOCK) { - // Check if the first like of the sign have the right tag - if (sign.getLine(0).equalsIgnoreCase(SpigotPrison.format(signTag))) { + // Get sign + Sign sign = (Sign) e.getClickedBlock().getState(); - if (sellAllConfig.getString("Options.SellAll_Sign_Use_Permission_Enabled").equalsIgnoreCase("true") && !p.hasPermission(sellAllConfig.getString("Options.SellAll_Sign_Use_Permission"))) { - Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.SellAllSignMissingPermission") + " [&3" + sellAllConfig.getString("Options.SellAll_Sign_Use_Permission") + "&7]"); - return; - } + // If there aren't lines in the sign this will void an error + try { - boolean bySignOnly = sellAllConfig.getString("Options.SellAll_By_Sign_Only").equalsIgnoreCase("true"); - // SellAllUtil sellAll = SellAllUtil.get(); - // if (sellAll != null) { - // sellAll.toggleSellAllSign(); - // } + // Check if the first like of the sign have the right tag + if (sign.getLine(0).equalsIgnoreCase(SpigotPrison.format(signTag))) { + String permissionUseSign = sellAllUtil.permissionUseSign; + if (sellAllUtil.isSellAllSignPermissionToUseEnabled && !p.hasPermission(permissionUseSign)) { + Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.SellAllSignMissingPermission") + " [&3" + permissionUseSign + "&7]"); + return; + } - if (sellAllConfig.getString("Options.SellAll_Sign_Notify").equalsIgnoreCase("true")) { - Output.get().sendInfo(new SpigotPlayer(p), messages.getString("Message.SellAllSignNotify")); - } + if (sellAllUtil.isSellAllSignNotifyEnabled) { + Output.get().sendInfo(new SpigotPlayer(p), messages.getString("Message.SellAllSignNotify")); + } - // Execute the sellall command - String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "sellall sell" ); - Bukkit.dispatchCommand(p, registeredCmd + ( bySignOnly ? " bySignOnly" : "")); + if (PrisonSpigotSellAllCommands.get() != null){ + PrisonSpigotSellAllCommands.get().sellAllSell(p); } - } catch (IndexOutOfBoundsException ignored) {} - } + } + } catch (IndexOutOfBoundsException ignored) {} } } } @@ -329,8 +319,6 @@ public void onChat(AsyncPlayerChatEvent e) { // Check if the boolean is true, this's set manually if (isChatEventActive) { - sellAllConfig = SpigotPrison.getInstance().getSellAllConfig(); - // Get the player Player p = e.getPlayer(); // Check if the player's in the list to not use another one for mistake/conflicting @@ -406,7 +394,6 @@ public void onClick(InventoryClickEvent e){ String[] parts; Module module; String title; - sellAllConfig = SpigotPrison.getInstance().getSellAllConfig(); try { // Get parameters. @@ -968,6 +955,8 @@ private void sellAllMultipliersGUI(InventoryClickEvent e, Player p, String butto return; } else { + Configuration sellAllConfig = SpigotPrison.getInstance().getSellAllConfig(); + // Open setMultiplierGUI String doubleString = sellAllConfig.getString("Multiplier." + parts[0] + ".MULTIPLIER"); if (doubleString != null) { @@ -1132,6 +1121,8 @@ private void sellAllAutoSellAdminGUI(InventoryClickEvent e, Player p, String but } private void sellAllAdminGUI(InventoryClickEvent e, Player p, String buttonNameMain) { + + Configuration sellAllConfig = SpigotPrison.getInstance().getSellAllConfig(); switch (buttonNameMain){ case "Blocks-Shop":{ @@ -1607,6 +1598,8 @@ private void sellAllAdminBlocksGUI(InventoryClickEvent e, Player p, String[] par } else if (e.isLeftClick()){ + Configuration sellAllConfig = SpigotPrison.getInstance().getSellAllConfig(); + String valueString = sellAllConfig.getString("Items." + parts[0] + ".ITEM_VALUE"); if (valueString != null) { SellAllPriceGUI gui = new SellAllPriceGUI(p, Double.parseDouble(valueString), parts[0]); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/guiutility/SpigotGUIComponents.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/guiutility/SpigotGUIComponents.java index b2b02a5b3..1ec47bc8c 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/guiutility/SpigotGUIComponents.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/guiutility/SpigotGUIComponents.java @@ -174,9 +174,9 @@ public static void updateMessages(){ * Reload sellall config for GUIs. * */ public static void updateSellAllConfig(){ - SellAllUtil util = SellAllUtil.get(); - util.updateSellAllConfig(); - sellAllConfig = util.getSellAllConfig(); + SellAllUtil util = SpigotPrison.getInstance().getSellAllUtil(); + util.updateConfig(); + sellAllConfig = util.sellAllConfig; } public static void updateGUIConfig(){ diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllAdminGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllAdminGUI.java index 05cce65ef..43b135d4b 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllAdminGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllAdminGUI.java @@ -61,9 +61,9 @@ public void open() { sellAllDelayLore.setLoreAction(createLore( messages.getString("Lore.ClickToOpen"), - messages.getString("Lore.DelaySellAll") + sellAllConfig.getString("Options.Sell_Delay_Seconds") + "s", messages.getString("Lore.RightClickToDisable"))); sellAllDelayLore.setLoreDescription(createLore( + messages.getString("Lore.DelaySellAll") + sellAllConfig.getString("Options.Sell_Delay_Seconds") + "s", messages.getString("Lore.SellAllDelayInfo"), messages.getString("Lore.SellAllDelayInfo2"))); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java index 463178e6a..dce94d20e 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java @@ -1,17 +1,8 @@ package tech.mcprison.prison.spigot.sellall; - -import java.io.File; -import java.io.IOException; -import java.text.DecimalFormat; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; - +import at.pcgamingfreaks.Minepacks.Bukkit.API.Backpack; +import com.cryptomorin.xseries.XMaterial; +import com.cryptomorin.xseries.XSound; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.Sound; @@ -21,18 +12,12 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; - -import com.cryptomorin.xseries.XMaterial; - -import at.pcgamingfreaks.Minepacks.Bukkit.API.Backpack; import tech.mcprison.prison.Prison; import tech.mcprison.prison.PrisonAPI; -import tech.mcprison.prison.cache.PlayerCache; import tech.mcprison.prison.integration.EconomyCurrencyIntegration; import tech.mcprison.prison.modules.Module; import tech.mcprison.prison.modules.ModuleManager; import tech.mcprison.prison.output.Output; -import tech.mcprison.prison.placeholders.PlaceholdersUtil; import tech.mcprison.prison.ranks.PrisonRanks; import tech.mcprison.prison.ranks.data.PlayerRank; import tech.mcprison.prison.ranks.data.Rank; @@ -45,1679 +30,1569 @@ import tech.mcprison.prison.spigot.gui.sellall.SellAllPlayerGUI; import tech.mcprison.prison.spigot.integrations.IntegrationMinepacksPlugin; +import java.io.File; +import java.io.IOException; +import java.util.*; + /** - * SellAllUtil class, this will replace the whole SellAll mess of a code of SellAllPrisonCommands. - * - * @author GABRYCA - */ + * @author AnonymousGCA (GABRYCA) + * */ public class SellAllUtil { private static SellAllUtil instance; -// private final boolean isEnabled = isEnabled(); - private File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); - public Configuration sellAllConfig = SpigotPrison.getInstance().updateSellAllConfig(); - public static List activePlayerDelay = new ArrayList<>(); - public static Map activeAutoSellPlayers = new HashMap<>(); -// public boolean signUsed = false; + private static final boolean isEnabled = getBoolean(SpigotPrison.getInstance().getConfig().getString("sellall")); private final Compatibility compat = SpigotPrison.getInstance().getCompatibility(); private final ItemStack lapisLazuli = compat.getLapisItemStack(); - private String idBeingProcessedBackpack = null; - public inventorySellMode mode = inventorySellMode.PlayerInventory; - private final Configuration messages = SpigotPrison.getInstance().getMessagesConfig(); - - /** - * SellAll mode. - */ - public enum inventorySellMode { - PlayerInventory, - MinesBackPack, - PrisonBackPackSingle, - PrisonBackPackMultiples - } + public Configuration sellAllConfig; + private HashMap sellAllBlocks; + private HashMap sellAllPrestigeMultipliers; + private HashMap autoSellEarningsNotificationWaiting = new HashMap<>(); + private ArrayList sellAllItemTriggers; + private ArrayList activePlayerDelay = new ArrayList<>(); + private List sellAllDisabledWorlds; + private Configuration messages; + private double defaultMultiplier; + private int defaultSellAllDelay; + private int defaultAutoSellEarningNotificationDelay; + private Sound sellAllSoundSuccess; + private Sound sellAllSoundFail; + public String sellAllSignTag; + public String sellAllCurrency; + public String permissionSellAllSell; + public String permissionBypassSign; + public String permissionGUI; + public String permissionPlayerGUI; + public String permissionPrefixBlocks; + public String permissionUseSign; + public String permissionAutoSellPerUserToggleable; + public String permissionItemTrigger; + public boolean isPerBlockPermissionEnabled; + public boolean isAutoSellEnabled; + public boolean isAutoSellPerUserToggleable; + public boolean isAutoSellPerUserToggleablePermEnabled; + public boolean isAutoSellNotificationEnabled; + public boolean isAutoSellEarningNotificationDelayEnabled; + public boolean isSellAllDelayEnabled; + public boolean isSellAllSellPermissionEnabled; + public boolean isSellAllItemTriggerEnabled; + public boolean isSellAllItemTriggerPermissionEnabled; + public boolean isSellAllGUIEnabled; + public boolean isSellAllPlayerGUIEnabled; + public boolean isSellAllGUIPermissionEnabled; + public boolean isSellAllPlayerGUIPermissionEnabled; + public boolean isSellAllMultiplierEnabled; + public boolean isSellAllPermissionMultiplierOnlyHigherEnabled; + public boolean isSellAllSignEnabled; + public boolean isSellAllBySignOnlyEnabled; + public boolean isSellAllSignNotifyEnabled; + public boolean isSellAllSignPermissionToUseEnabled; + public boolean isSellAllNotificationEnabled; + public boolean isSellAllSoundEnabled; + public boolean isSellAllBackpackItemsEnabled; + public boolean isSellAllMinesBackpacksPluginEnabled; /** - * Get SellAll instance. - */ + * Get cached instance of SellAllUtil, if present, if not then Initialize it, if SellAll is disabled return null. + * + * @return SellAllUtil. + * */ public static SellAllUtil get() { - return instanceUpdater(); - } - - public Configuration getSellAllConfig(){ - return sellAllConfig; + if (!isEnabled){ + return null; + } + if (instance == null){ + instance = new SellAllUtil(); + instance.initCachedData(); + } + return instance; } -// /** -// * Use this to toggle the SellAllSign, essentially this will tell to the SellAll Sell command that you're using a sign -// * for SellAll. -// */ -// public void toggleSellAllSign() { -// sellAllSignToggler(); -// } - /** - * Get the money to give to the Player depending on the multiplier. - * This can be a bit like the SellAll Sell command, but without sellall sounds and options. - * - * @param player - Player - * @param removeItems - True to remove the items from the Player, False to get only the value of the Money + Multiplier - * - Without touching the Player's inventory. - * @return money - */ - public double getMoneyWithMultiplier(Player player, boolean removeItems) { - return getMoneyFinal(player, removeItems); + * Return boolean value from String. + * + * @return boolean. + * */ + public static boolean getBoolean(String string) { + return string != null && string.equalsIgnoreCase("true"); } /** - * Get the player multiplier, requires SpigotPlayer. + * Get an ArrayList of SellAllItemTriggers as XMaterials. + * These items will trigger sellall when a player hold them and then do shift+right click in the air. * - * @param sPlayer SpigotPlayer - * @return multiplier - */ - public double getMultiplier(SpigotPlayer sPlayer) { - return getMultiplierMethod(sPlayer); + * @return ArrayList of XMaterials. + * */ + public ArrayList getItemTriggerXMaterials(){ + return sellAllItemTriggers; } /** - * Set sellSll currency by name + * Get an ArrayList of SellAllItemTriggers as Materials. + * This will essentially do a conversion of the cached internal XMaterial ArrayList of SellAllItemTriggers. * - * @param currency - String currency name - * @return error - true if an error occurred. - */ - public boolean setCurrency(String currency) { - return sellAllCurrencySaver(currency); - } + * @return ArrayList of Materials. + * */ + public ArrayList getItemTriggerMaterials(){ + if (sellAllItemTriggers == null || sellAllItemTriggers.isEmpty()){ + return new ArrayList<>(); + } - /** - * Check if SellAll's enabled. - */ - public boolean isEnabled() { - return getBoolean(SpigotPrison.getInstance().getConfig().getString("sellall")); - } + ArrayList materials = new ArrayList<>(); - /** - * SellAll config updater. - */ - public void updateSellAllConfig() { - sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); - sellAllConfig = YamlConfiguration.loadConfiguration(sellAllFile); - } + for (XMaterial xMaterial : sellAllItemTriggers){ + materials.add(xMaterial.parseMaterial()); + } - /** - * Enable or disable SellAllDelay - * - * @param enableBoolean - True to enable and False to disable. - * @return error - True if an error occurred. - */ - public boolean enableDelay(boolean enableBoolean) { - return sellAllDelayToggle(enableBoolean); + return materials; } /** - * Set SellAll delay. + * Get SellAll XMaterial or Lapis (As Lapis is weird) from an ItemStack. + * + * @param itemStack - ItemStack. * - * @param delayValue - * @return error - True if error occurred. - */ - public boolean setDelay(int delayValue) { - return sellAllDelaySave(delayValue); + * @return XMaterial. + * */ + public XMaterial getXMaterialOrLapis(ItemStack itemStack) { + if (itemStack.isSimilar(lapisLazuli)) { + return XMaterial.LAPIS_LAZULI; + } + return XMaterial.matchXMaterial(itemStack); } /** - * Enable or disable SellAll AutoSell. + * Return SellAll Blocks HashMap cached values. * - * @param enableBoolean - True to enable or False to disable - * @return error - True if error occurred. - */ - public boolean enableAutoSell(boolean enableBoolean) { - return sellAllAutoSellToggle(enableBoolean); + * @return HashMap of XMaterial-Double. + * */ + public HashMap getSellAllBlocks() { + return sellAllBlocks; } /** - * Enable or disable perUserToggleable autoSell. + * Return SellAll Prestige Multiplier HashMap read before from config on init. * - * @param enableBoolean - True to enable or False to disable - * @return error - True if error occurred. - */ - public boolean enableAutoSellPerUserToggleable(boolean enableBoolean) { - return sellAllAutoSellPerUserToggleableToggle(enableBoolean); + * HashMap details: + * String is the name of the Prestige. + * Double is the multiplier (default 1). + * + * @return HashMap of String-Double. + * */ + public HashMap getPrestigeMultipliers() { + return sellAllPrestigeMultipliers; } /** - * Enable or disable autosell to a player. + * Get HashMap of XMaterials and amounts from an Inventory. * - * @param p - Player + * @param inv - Inventory. * - * @return error - True if error occurred, false if success. + * @return HashMap of XMaterials and Integers. * */ - public boolean autoSellPlayerToggle(Player p) { - return sellAllAutoSellPlayerToggle(p); + public HashMap getXMaterialsHashMapFromInventory(Inventory inv){ + + HashMap xMaterialIntegerHashMap = new HashMap<>(); + for (ItemStack itemStack : inv.getContents()){ + if (itemStack != null){ + XMaterial xMaterial = getXMaterialOrLapis(itemStack); + if (xMaterialIntegerHashMap.containsKey(xMaterial) && xMaterialIntegerHashMap.get(xMaterial) != 0){ + xMaterialIntegerHashMap.put(xMaterial, xMaterialIntegerHashMap.get(xMaterial) + itemStack.getAmount()); + } else { + xMaterialIntegerHashMap.put(xMaterial, itemStack.getAmount()); + } + } + } + + return xMaterialIntegerHashMap; } + /** - * SellAll Sell command essentially, but in a method. - * NOTE: It applies sellAll options from the config, except the sellAll permission one. + * get HashMap of XMaterials and Amounts from an ArrayList of ItemStacks. * - * @param p - Player affected by sellall. - */ - public void sellAllSell(Player p) { - sellAllSellPlayer(p); - } - - public void sellAllSell(Player p, boolean notifications, boolean bySignOnly) { - sellAllSellPlayer(p, notifications, bySignOnly); + * @param itemStacks - ArrayList of ItemStacks. + * + * @return HashMap of XMaterials and Integers. + * */ + public HashMap getXMaterialsHashMapFromArrayList(ArrayList itemStacks){ + + HashMap xMaterialIntegerHashMap = new HashMap<>(); + for (ItemStack itemStack : itemStacks){ + if (itemStack != null){ + XMaterial xMaterial = getXMaterialOrLapis(itemStack); + if (xMaterialIntegerHashMap.containsKey(xMaterial) && xMaterialIntegerHashMap.get(xMaterial) != 0){ + xMaterialIntegerHashMap.put(xMaterial, xMaterialIntegerHashMap.get(xMaterial) + itemStack.getAmount()); + } else { + xMaterialIntegerHashMap.put(xMaterial, itemStack.getAmount()); + } + } + } + + return xMaterialIntegerHashMap; } /** - * Open SellAll GUI for Players or Admins depending on their status and/or permissions. + * Get SellAll Player Multiplier. * - * @param p - Player that should open the GUI. - * @return boolean - True if a GUI got open with success, false if Disabled or missing all permissions. - */ - public boolean openGUI(Player p) { - return sellAllOpenGUI(p); - } + * @param p - Player. + * + * @return double. + * */ + public double getPlayerMultiplier(Player p){ - /** - * Add SellAll Block by ID. - * - * @param itemID - String name of Block. - * @param value - Value of the block when sold. - * @return error - True if an error occurred, false if success. - */ - public boolean addBlock(String itemID, Double value) { - return sellAllAddBlockAction(itemID, value); - } + if (!isSellAllMultiplierEnabled){ + return 1; + } - /** - * Add SellAll Block by Material. - * - * @param material - Material of Block. - * @param value - Value of the block when sold. - * @return error - True if an error occurred, false if success. - */ - public boolean addBlock(Material material, Double value) { - return sellAllAddBlockAction(material, value); - } + // Get Ranks module. + ModuleManager modMan = Prison.get().getModuleManager(); + Module module = modMan == null ? null : modMan.getModule(PrisonRanks.MODULE_NAME).orElse(null); + SpigotPlayer sPlayer = new SpigotPlayer(p); + double multiplier = defaultMultiplier; - /** - * Add SellAll Block by ItemStack. - * - * @param itemStack - ItemStack of Block. - * @param value - Value of the block when sold. - * @return error - True if an error occurred, false if success. - */ - public boolean addBlock(ItemStack itemStack, Double value) { - return sellAllAddBlockAction(itemStack, value); - } + // Get multiplier depending on Player + Prestige. NOTE that prestige multiplier will replace + // the actual default multiplier. + if (module != null) { + PrisonRanks rankPlugin = (PrisonRanks) module; + if (rankPlugin.getPlayerManager().getPlayer(sPlayer) != null) { + String playerRankName; + try { + RankPlayer rankPlayer = rankPlugin.getPlayerManager().getPlayer(sPlayer); + PlayerRank pRank = rankPlayer == null ? null : rankPlayer.getRank("prestiges"); + Rank rank = pRank == null ? null : pRank.getRank(); - /** - * Add SellAll Block by ItemStack. - * - * @param xMaterial - XMaterial of Block. - * @param value - Value of the block when sold. - * @return error - True if an error occurred, false if success. - */ - public boolean addBlock(XMaterial xMaterial, Double value) { - return sellAllAddBlockAction(xMaterial, value); - } + playerRankName = rank == null ? null : rank.getName(); + } catch (NullPointerException ex) { + playerRankName = null; + } + if (playerRankName != null) { + String multiplierRankString = sellAllConfig.getString("Multiplier." + playerRankName + ".MULTIPLIER"); + if (multiplierRankString != null && sellAllPrestigeMultipliers.containsKey(playerRankName)){ + multiplier = sellAllPrestigeMultipliers.get(playerRankName); + } + } + } + } - /** - *

This will add the XMaterial and value to the sellall. - * This will update even if the sellall has not been enabled. - *

- * - * @param blockAdd - XMaterial of the Block to add. - * @param value - Double value when sold. - */ - public void sellAllAddCommand(XMaterial blockAdd, Double value) { - sellAllAddCommandMethod(blockAdd, value); - } + // Get Multiplier from multipliers permission's if there's any. + List perms = sPlayer.getPermissions("prison.sellall.multiplier."); + double multiplierExtraByPerms = 0; + for (String multByPerm : perms) { + double multByPermDouble = Double.parseDouble(multByPerm.substring(26)); + if (!isSellAllPermissionMultiplierOnlyHigherEnabled) { + multiplierExtraByPerms += multByPermDouble; + } else if (multByPermDouble > multiplierExtraByPerms) { + multiplierExtraByPerms = multByPermDouble; + } + } + multiplier += multiplierExtraByPerms; - /** - * Remove/Delete SellAll Block from the config. - * - * @param itemID - String name of Block. - * @return error - True if an error occurred or missing item in the config, False if success. - */ - public boolean deleteBlock(String itemID) { - return sellAllDeleteAction(itemID); + return multiplier; } /** - * Remove/Delete SellAll Block from the config. + * Get SellAll Money to give, it requires Player because of SellAll perBlockPermission as an option. + * NOTE: This WON'T remove blocks from the HashMap when sold, and won't edit Inventories of Players, + * but only return the amount of money that the Player would get if he sells now everything from the + * specified HashMap of XMaterials and Integers. * - * @param material - Material of Block. - * @return error - True if an error occurred or missing item in the config, False if success. - */ - public boolean deleteBlock(Material material) { - return sellAllDeleteAction(material); - } - - /** - * Remove/Delete SellAll Block from the config. + * Will also calculate the Multiplier of the Player. * - * @param itemStack - ItemStack of Block. - * @return error - True if an error occurred or missing item in the config, False if success. - */ - public boolean deleteBlock(ItemStack itemStack) { - return sellAllDeleteAction(itemStack); - } - - /** - * Remove/Delete SellAll Block from the config. + * Get SellAll Sell value of HashMap values. + * NOTE: If there aren't blocks in the SellAll shop this will return 0. + * NOTE: This method WON'T remove blocks from HashMap, but only return a double value. + * + * @param p - Player. + * @param xMaterialIntegerHashMap - HashMap of XMaterial-Integer (Blocks of origin). * - * @param xMaterial - XMaterial of Block. - * @return error - True if an error occurred or missing item in the config, False if success. - */ - public boolean deleteBlock(XMaterial xMaterial) { - return sellAllDeleteAction(xMaterial); + * @return double. + * */ + public double getSellMoney(Player p, HashMap xMaterialIntegerHashMap){ + + if (sellAllBlocks.isEmpty()){ + return 0; + } + + double multiplier = getPlayerMultiplier(p); + double earned = 0; + for (HashMap.Entry xMaterialIntegerEntry : xMaterialIntegerHashMap.entrySet()){ + if (sellAllBlocks.containsKey(xMaterialIntegerEntry.getKey())){ + // This is stupid but right now I'm too confused, sorry. + if (isPerBlockPermissionEnabled && !p.hasPermission(permissionPrefixBlocks + xMaterialIntegerEntry.getKey().name())){ + // Nothing will change. + } else { + earned += xMaterialIntegerEntry.getValue() * sellAllBlocks.get(xMaterialIntegerEntry.getKey()); + } + } + } + + return earned * multiplier; } /** - * Edit SellAll Block. + * Get SellAll Money to give, it requires Player because of SellAll perBlockPermission as an option. + * NOTE: This WON'T remove blocks from the ArrayList when sold, and won't edit Inventories of Players, + * but only return the amount of money that the Player would get if he sells now everything from the + * specified ArrayList of ItemStacks. * - * @param itemID - String name of Block. - * @param value - Double value when Sold. + * Will also calculate the Multiplier of the Player. * - * @return error - True if error occurred or block is missing in the config, False if success. - */ - public boolean editBlock(String itemID, Double value) { - return sellAllEditBlockAction(itemID, value); - } - - /** - * Edit SellAll Block. + * Get SellAll Sell value of ArrayList of itemstack. + * NOTE: If there aren't blocks in the SellAll shop this will return 0. + * NOTE: This method WON'T remove blocks from HashMap, but only return a double value. * - * @param material - Material of Block. - * @param value - Double value when Sold. + * @param p - Player. + * @param itemStacks - ArrayList of ItemStacks (Blocks of origin). * - * @return error - True if error occurred or block is missing in the config, False if success. - */ - public boolean editBlock(Material material, Double value) { - return sellAllEditBlockAction(material, value); + * @return double. + * */ + public double getSellMoney(Player p, ArrayList itemStacks){ + HashMap xMaterialIntegerHashMap = getXMaterialsHashMapFromArrayList(itemStacks); + return getSellMoney(p, xMaterialIntegerHashMap); } /** - * Edit SellAll Block. + * Get SellAll Sell Money, calculated from all the enabled backpacks (from sellAll config and integrations) and + * main inventory. + * NOTE: This WON'T remove blocks from Inventories/Backpacks, but only return their value. * - * @param itemStack - ItemStack of Block. - * @param value - Double value when Sold. + * Will also calculate the Multiplier of the Player. * - * @return error - True if error occurred or block is missing in the config, False if success. - */ - public boolean editBlock(ItemStack itemStack, Double value) { - return sellAllEditBlockAction(itemStack, value); - } - - /** - * Edit SellAll Block. + * NOTE: If there aren't blocks in the SellAll shop this will return 0. + * NOTE: This method WON'T remove blocks from HashMap, but only return a double value. * - * @param xMaterial - XMaterial of Block. - * @param value - Double value when Sold. + * @param p - Player. * - * @return error - True if error occurred or block is missing in the config, False if success. - */ - public boolean editBlock(XMaterial xMaterial, Double value) { - return sellAllEditBlockAction(xMaterial, value); + * @return double. + * */ + public double getSellMoney(Player p){ + + if (sellAllBlocks.isEmpty()){ + return 0; + } + + return getSellMoney(p, getHashMapOfPlayerInventories(p)); } /** - * Add SellAll Multiplier. + * Get HashMap with all the items of a Player. * - * @param prestige - Prestige name to hook. - * @param multiplier - Multiplier Double Value. + * Return HashMap of XMaterial-Integer. * - * @return error - True if error occurred and false if success. + * @param p - Player. + * + * @return HashMap - XMaterial-Integer. * */ - public boolean addMultiplier(String prestige, Double multiplier) { - return sellAllAddMultiplierAction(prestige, multiplier); + private HashMap getHashMapOfPlayerInventories(Player p) { + HashMap xMaterialIntegerHashMap = new HashMap<>(); + if (isSellAllBackpackItemsEnabled && getBoolean(SpigotPrison.getInstance().getConfig().getString("backpacks"))){ + BackpacksUtil backpacksUtil = BackpacksUtil.get(); + if (backpacksUtil.isMultipleBackpacksEnabled()){ + for (String id : backpacksUtil.getBackpacksIDs(p)){ + xMaterialIntegerHashMap = addInventoryToHashMap(xMaterialIntegerHashMap, backpacksUtil.getBackpack(p, id)); + } + } else { + xMaterialIntegerHashMap = addInventoryToHashMap(xMaterialIntegerHashMap, backpacksUtil.getBackpack(p)); + } + } + + if (isSellAllMinesBackpacksPluginEnabled && IntegrationMinepacksPlugin.getInstance().isEnabled()){ + Backpack backpack = IntegrationMinepacksPlugin.getInstance().getMinepacks().getBackpackCachedOnly(p); + if (backpack != null) { + xMaterialIntegerHashMap = addInventoryToHashMap(xMaterialIntegerHashMap, backpack.getInventory()); + } + } + + xMaterialIntegerHashMap = addInventoryToHashMap(xMaterialIntegerHashMap, p.getInventory()); + return xMaterialIntegerHashMap; } /** - * Delete SellAll Multiplier. + * Get AutoSell Player toggle if available. + * If he enabled it, AutoSell will work, otherwise it won't. + * If he never used the toggle command, this will return true, just like if he enabled it in the first place. * - * @param prestige - Prestige with the multiplier + * @param p - Player. * - * @return error - True if error occurred or the Multiplier wasn't found, false if success. + * @return boolean. * */ - public boolean deleteMultiplier(String prestige) { - return sellAllDeleteMultiplierAction(prestige); + public boolean isPlayerAutoSellEnabled(Player p){ + if (sellAllConfig.getString("Users." + p.getUniqueId() + ".isEnabled") == null){ + return true; + } + + return getBoolean(sellAllConfig.getString("Users." + p.getUniqueId() + ".isEnabled")); } /** - * Enable or disable SellAll Item Trigger feature. - * This's a feature that makes the player able to Shift and Right click - * On an item in his hand to trigger sellall. + * Check if Player is in a disabled world, where he can't use sellall sell. * - * @param enableInput - True to enable, False to disable. + * Return True if he's in a disabled world, False if not. * - * @return error - True if error occurred, False if success. + * @return boolean. * */ - public boolean toggleItemTrigger(boolean enableInput) { - return sellAllItemToggle(enableInput); + public boolean isPlayerInDisabledWorld(Player p){ + return sellAllDisabledWorlds.contains(p.getWorld().getName()); } /** - * Add an Item to the SellAll item Triggers. + * Check if Player is waiting for the end of SellAll Sell Delay. * - * @param itemID - String name of the Item + * Return True if he's still waiting, False if not. * - * @return error - True if an error occurred, False if success. + * @param p - Player. + * + * @return boolean. * */ - public boolean addItemTrigger(String itemID) { - return sellAllAddTrigger(itemID); + public boolean isPlayerWaitingSellAllDelay(Player p){ + return activePlayerDelay.contains(p); } /** - * Add an Item to the SellAll item Triggers. + * Check if Player is waiting for the end of the AutoSell Delay notification. + * + * Return true if Player is found. * - * @param itemMaterial - XMaterial of the Item + * @param p - Player. * - * @return error - True if an error occurred, False if success. + * @return boolean. * */ - public boolean addItemTrigger(XMaterial itemMaterial) { - return sellAllAddTrigger(itemMaterial); + public boolean isPlayerWaitingAutoSellNotification(Player p){ + return autoSellEarningsNotificationWaiting.containsKey(p); } /** - * Add an Item to the SellAll item Triggers. + * Check if specified string item name is a valid item. * - * @param itemMaterial - Material of the Item + * @param item - String. * - * @return error - True if an error occurred, False if success. + * @return boolean. * */ - public boolean addItemTrigger(Material itemMaterial) { - return sellAllAddTrigger(itemMaterial); + public boolean isValidItem(String item){ + return XMaterial.matchXMaterial(item).isPresent(); } /** - * Add an Item to the SellAll item Triggers. - * - * @param itemStack - ItemStack of the Item - * - * @return error - True if an error occurred, False if success. + * Update SellAll Cached config. * */ - public boolean addItemTrigger(ItemStack itemStack) { - return sellAllAddTrigger(itemStack); + public void updateConfig(){ + sellAllConfig = SpigotPrison.getInstance().updateSellAllConfig(); } /** - * Delete a sellAll Item trigger. - * - * @param itemID - Name of the item. - * - * @return error - True if error occurred or item not found, False if success. + * Init options that will be cached. * */ - public boolean deleteItemTrigger(String itemID) { - return sellAllDeleteTrigger(itemID); + private void initCachedData() { + sellAllConfig = SpigotPrison.getInstance().updateSellAllConfig(); + messages = SpigotPrison.getInstance().getMessagesConfig(); + permissionSellAllSell = sellAllConfig.getString("Options.Sell_Permission"); + permissionBypassSign = sellAllConfig.getString("Options.SellAll_By_Sign_Bypass_Permission"); + permissionUseSign = sellAllConfig.getString("Options.SellAll_Sign_Use_Permission"); + permissionGUI = sellAllConfig.getString("Options.GUI_Permission"); + permissionPlayerGUI = sellAllConfig.getString("Options.Player_GUI_Permission"); + permissionPrefixBlocks = sellAllConfig.getString("Options.Sell_Per_Block_Permission"); + permissionAutoSellPerUserToggleable = sellAllConfig.getString("Options.Full_Inv_AutoSell_PerUserToggleable_Permission"); + permissionItemTrigger = sellAllConfig.getString("Options.ShiftAndRightClickSellAll.Permission"); + sellAllCurrency = sellAllConfig.getString("Options.SellAll_Currency"); + sellAllSoundSuccess = XSound.matchXSound("Options.Sell_Sound_Success_Name").orElse(XSound.ENTITY_PLAYER_LEVELUP).parseSound(); + sellAllSoundFail = XSound.matchXSound("Options.Sell_Sound_Fail_Name").orElse(XSound.BLOCK_ANVIL_PLACE).parseSound(); + sellAllSignTag = SpigotPrison.format(sellAllConfig.getString("Options.SellAll_Sign_Visible_Tag")); + sellAllBlocks = initSellAllBlocks(); + sellAllPrestigeMultipliers = initPrestigeMultipliers(); + sellAllItemTriggers = initSellAllItemTrigger(); + sellAllDisabledWorlds = initSellAllDisabledWorlds(); + defaultMultiplier = Double.parseDouble(sellAllConfig.getString("Options.Multiplier_Default")); + defaultSellAllDelay = Integer.parseInt(sellAllConfig.getString("Options.Sell_Delay_Seconds")); + defaultAutoSellEarningNotificationDelay = Integer.parseInt(sellAllConfig.getString("Options.Full_Inv_AutoSell_EarnedMoneyNotificationDelay_Delay_Seconds")); + isPerBlockPermissionEnabled = getBoolean(sellAllConfig.getString("Options.Sell_Per_Block_Permission_Enabled")); + isAutoSellEnabled = getBoolean(sellAllConfig.getString("Options.Full_Inv_AutoSell")); + isAutoSellNotificationEnabled = getBoolean(sellAllConfig.getString("Options.Full_Inv_AutoSell_Notification")); + isAutoSellEarningNotificationDelayEnabled = getBoolean(sellAllConfig.getString("Options.Full_Inv_AutoSell_EarnedMoneyNotificationDelay_Enabled")); + isAutoSellPerUserToggleable = getBoolean(sellAllConfig.getString("Options.Full_Inv_AutoSell_perUserToggleable")); + isAutoSellPerUserToggleablePermEnabled = getBoolean(sellAllConfig.getString("Options.Full_Inv_AutoSell_perUserToggleable_Need_Perm")); + isSellAllNotificationEnabled = getBoolean(sellAllConfig.getString("Options.Sell_Notify_Enabled")); + isSellAllSoundEnabled = getBoolean(sellAllConfig.getString("Options.Sell_Sound_Enabled")); + isSellAllBackpackItemsEnabled = getBoolean(sellAllConfig.getString("Options.Sell_Prison_BackPack_Items")); + isSellAllMinesBackpacksPluginEnabled = getBoolean(sellAllConfig.getString("Options.Sell_MinesBackPacks_Plugin_Backpack")); + isSellAllDelayEnabled = getBoolean(sellAllConfig.getString("Options.Sell_Delay_Enabled")); + isSellAllSellPermissionEnabled = getBoolean(sellAllConfig.getString("Options.Sell_Permission_Enabled")); + isSellAllItemTriggerEnabled = getBoolean(sellAllConfig.getString("Options.ShiftAndRightClickSellAll.Enabled")); + isSellAllItemTriggerPermissionEnabled = getBoolean(sellAllConfig.getString("Options.ShiftAndRightClickSellAll.PermissionEnabled")); + isSellAllGUIEnabled = getBoolean(sellAllConfig.getString("Options.GUI_Enabled")); + isSellAllPlayerGUIEnabled = getBoolean(sellAllConfig.getString("Options.Player_GUI_Enabled")); + isSellAllGUIPermissionEnabled = getBoolean(sellAllConfig.getString("Options.GUI_Permission_Enabled")); + isSellAllPlayerGUIPermissionEnabled = getBoolean(sellAllConfig.getString("Options.Player_GUI_Permission_Enabled")); + isSellAllMultiplierEnabled = getBoolean(sellAllConfig.getString("Options.Multiplier_Enabled")); + isSellAllPermissionMultiplierOnlyHigherEnabled = getBoolean(sellAllConfig.getString("Options.Multiplier_Permission_Only_Higher")); + isSellAllSignEnabled = getBoolean(sellAllConfig.getString("Options.SellAll_Sign_Enabled")); + isSellAllSignNotifyEnabled = getBoolean(sellAllConfig.getString("Options.SellAll_Sign_Notify")); + isSellAllSignPermissionToUseEnabled = getBoolean(sellAllConfig.getString("Options.SellAll_Sign_Use_Permission_Enabled")); + isSellAllBySignOnlyEnabled = getBoolean(sellAllConfig.getString("Options.SellAll_By_Sign_Only")); } /** - * Delete a sellAll Item trigger. + * Loads sellAll blocks from SellAllConfig.yml + * With XMaterials and double values (money). * - * @param itemMaterial - Material of the item. - * - * @return error - True if error occurred or item not found, False if success. + * @return HashMap XMaterial-Double. * */ - public boolean deleteItemTrigger(XMaterial itemMaterial) { - return sellAllDeleteTrigger(itemMaterial); + public HashMap initSellAllBlocks(){ + + HashMap sellAllXMaterials = new HashMap<>(); + + if (sellAllConfig.getConfigurationSection("Items") == null){ + return sellAllXMaterials; + } + + for (String key : sellAllConfig.getConfigurationSection("Items").getKeys(false)) { + + String itemID = sellAllConfig.getString("Items." + key + ".ITEM_ID"); + + Optional iMatOptional = XMaterial.matchXMaterial(itemID); + XMaterial itemMaterial = iMatOptional.orElse(null); + + if (itemMaterial != null) { + String valueString = sellAllConfig.getString("Items." + key + ".ITEM_VALUE"); + if (valueString != null) { + try { + double value = Double.parseDouble(valueString); + sellAllXMaterials.put(itemMaterial, value); + } catch (NumberFormatException ignored) { + } + } + } + } + return sellAllXMaterials; } /** - * Delete a sellall Item trigger. + * Init sellAll Prestige Multipliers. * - * @param itemMaterial - Material of the item. - * - * @return error - True if error occurred or item not found, False if success. + * @return HashMap String-Double. * */ - public boolean deleteItemTrigger(Material itemMaterial) { - return sellAllDeleteTrigger(itemMaterial); + public HashMap initPrestigeMultipliers(){ + + HashMap prestigeMultipliers = new HashMap<>(); + + if (sellAllConfig.getConfigurationSection("Multiplier") == null){ + return prestigeMultipliers; + } + + for (String key : sellAllConfig.getConfigurationSection("Multiplier").getKeys(false)){ + prestigeMultipliers.put(sellAllConfig.getString("Multiplier." + key + ".PRESTIGE_NAME"), sellAllConfig.getDouble("Multiplier." + key + ".MULTIPLIER")); + } + return prestigeMultipliers; } /** - * Delete a sellAll Item trigger. + * Read SellAll Item Triggers and return them in an ArrayList of XMaterials. + * NOTE: This needs to be enabled, otherwise will return null. * - * @param itemStack - ItemStack of the item. - * - * @return error - True if error occurred or item not found, False if success. + * @return ArrayList of XMaterials. * */ - public boolean deleteItemTrigger(ItemStack itemStack) { - return sellAllDeleteTrigger(itemStack); + public ArrayList initSellAllItemTrigger(){ + + ArrayList xMaterials = new ArrayList<>(); + + if (!isSellAllItemTriggerEnabled){ + return xMaterials; + } + + if (sellAllConfig.getConfigurationSection("ShiftAndRightClickSellAll.Items") == null){ + return xMaterials; + } + + for (String xMaterialID : sellAllConfig.getConfigurationSection("ShiftAndRightClickSellAll.Items").getKeys(false)){ + Optional xMaterialRead = XMaterial.matchXMaterial(sellAllConfig.getString("ShiftAndRightClickSellAll.Items." + xMaterialID + ".ITEM_ID")); + xMaterialRead.ifPresent(xMaterials::add); + } + + return xMaterials; } /** - * Check if the world the player is in is disabled. - * - * @param p - Player - * - * @return boolean - true if the player is in a disabled world, false if not. + * Get List of names of disabled worlds. + * If a Player is in one of these worlds, he won't be able to use SellAll. * */ - public boolean isDisabledWorld(Player p) { - return playerPositionIsDisabledWorld(p); + public List initSellAllDisabledWorlds(){ + return sellAllConfig.getStringList("Options.DisabledWorlds"); } /** - * Add Player to AutoSell delay for earned money notification. - * This will add the player only if missing, if already added then will do nothing. + * Add a block to SellAll config. + * + * Return True if no error occurred, false if error. + * + * @param xMaterial - XMaterial of block to add. + * @param value - Value of the block to add. + * + * @return boolean. * */ - public void addToAutoSellTask(Player p) { - if (!activeAutoSellPlayers.containsKey(p) && getBoolean(sellAllConfig.getString("Options.Full_Inv_AutoSell_EarnedMoneyNotificationDelay_Enabled"))) { - activeAutoSellPlayers.put(p, 0.00); - int delay = Integer.parseInt(sellAllConfig.getString("Options.Full_Inv_AutoSell_EarnedMoneyNotificationDelay_Delay_Seconds")); - Bukkit.getScheduler().scheduleSyncDelayedTask(SpigotPrison.getInstance(), () -> taskSellAllAutoActions(p), 20L * delay); + public boolean addSellAllBlock(XMaterial xMaterial, double value){ + try { + File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); + FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); + conf.set("Items." + xMaterial.name() + ".ITEM_ID", xMaterial.name()); + conf.set("Items." + xMaterial.name() + ".ITEM_VALUE", value); + if (getBoolean(sellAllConfig.getString("Options.Sell_Per_Block_Permission_Enabled"))) { + conf.set("Items." + xMaterial.name() + ".ITEM_PERMISSION", sellAllConfig.getString("Options.Sell_Per_Block_Permission") + xMaterial.name()); + } + conf.save(sellAllFile); + } catch (IOException e) { + e.printStackTrace(); + return false; } + updateConfig(); + sellAllBlocks.put(xMaterial, value); + return true; } /** - * Remove Player from AutoSell delay for earned money notification. - * This's usually handled only internally and should be used only for some rare exceptions. + * Add a block to SellAll config. + * + * Return True if no error occurred, false if error. + * + * @param material - Material of block to add. + * @param value - Value of the block to add. + * + * @return boolean. * */ - public void removeFromAutoSellTask(Player p){ - activeAutoSellPlayers.remove(p); + public boolean addSellAllBlock(Material material, double value){ + return addSellAllBlock(XMaterial.matchXMaterial(material), value); } /** - * Java getBoolean's broken so I made my own. - */ - public boolean getBoolean(String string) { - return string != null && string.equalsIgnoreCase("true"); - } - + * Add Multiplier to SellAll depending on the Prestige Rank (Rank from the prestiges ladder). + * + * Return true if edited with success, false if error or Prestige not found. + * + * @param prestigeName - Name of the Prestige as String. + * @param multiplier - Double value. + * + * @return boolean. + * */ + public boolean addPrestigeMultiplier(String prestigeName, double multiplier){ + PrisonRanks rankPlugin = (PrisonRanks) (Prison.get().getModuleManager() == null ? null : Prison.get().getModuleManager().getModule(PrisonRanks.MODULE_NAME).orElse(null)); + if (rankPlugin == null) { + return false; + } - private boolean playerPositionIsDisabledWorld(Player p) { - updateSellAllConfig(); - String worldName = p.getWorld().getName(); - List disabledWorlds = sellAllConfig.getStringList("Options.DisabledWorlds"); - return disabledWorlds.contains(worldName); - } + boolean isPrestigeLadder = rankPlugin.getLadderManager().getLadder("prestiges") != null; + if (!isPrestigeLadder) { + return false; + } - private boolean sellAllDeleteTrigger(ItemStack itemStack) { - try { - File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); - FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("ShiftAndRightClickSellAll.Items." + itemStack.getType().name() + ".ITEM_ID", null); - conf.set("ShiftAndRightClickSellAll.Items." + itemStack.getType().name(), null); - conf.save(sellAllFile); - } catch (IOException e) { - e.printStackTrace(); - return true; + boolean isARank = rankPlugin.getRankManager().getRank(prestigeName) != null; + if (!isARank) { + return false; } - updateSellAllConfig(); - return false; - } - private boolean sellAllDeleteTrigger(Material itemMaterial) { - try { - File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); - FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("ShiftAndRightClickSellAll.Items." + itemMaterial.name() + ".ITEM_ID", null); - conf.set("ShiftAndRightClickSellAll.Items." + itemMaterial.name(), null); - conf.save(sellAllFile); - } catch (IOException e) { - e.printStackTrace(); - return true; + boolean isInPrestigeLadder = rankPlugin.getLadderManager().getLadder("prestiges").containsRank(rankPlugin.getRankManager().getRank(prestigeName)); + if (!isInPrestigeLadder) { + return false; } - updateSellAllConfig(); - return false; - } - private boolean sellAllDeleteTrigger(XMaterial itemMaterial) { try { File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("ShiftAndRightClickSellAll.Items." + itemMaterial.name() + ".ITEM_ID", null); - conf.set("ShiftAndRightClickSellAll.Items." + itemMaterial.name(), null); + conf.set("Multiplier." + prestigeName + ".PRESTIGE_NAME", prestigeName); + conf.set("Multiplier." + prestigeName + ".MULTIPLIER", multiplier); conf.save(sellAllFile); } catch (IOException e) { e.printStackTrace(); - return true; + return false; } - updateSellAllConfig(); - return false; + sellAllPrestigeMultipliers.put(prestigeName, multiplier); + updateConfig(); + return true; } - private boolean sellAllDeleteTrigger(String itemID) { - if (sellAllConfig.getString("Options.ShiftAndRightClickSellAll.Items." + itemID + ".ITEM_ID") == null){ - return true; + /** + * Add SellAll Item Trigger. + * + * Return true if run with success, false if error or item already added. + * + * @param xMaterial - XMaterial to add. + * + * @return boolean. + * */ + public boolean addItemTrigger(XMaterial xMaterial){ + if (sellAllItemTriggers.contains(xMaterial)){ + return false; } try { File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("ShiftAndRightClickSellAll.Items." + itemID + ".ITEM_ID", null); - conf.set("ShiftAndRightClickSellAll.Items." + itemID, null); + conf.set("ShiftAndRightClickSellAll.Items." + xMaterial.name() + ".ITEM_ID", xMaterial.name()); conf.save(sellAllFile); } catch (IOException e) { e.printStackTrace(); - return true; + return false; } - updateSellAllConfig(); - return false; + sellAllItemTriggers.add(xMaterial); + updateConfig(); + return true; } - private boolean sellAllAddTrigger(ItemStack blockAdd) { - try { - File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); - FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("ShiftAndRightClickSellAll.Items." + blockAdd.getType().name() + ".ITEM_ID", blockAdd.getType().name()); - conf.save(sellAllFile); - } catch (IOException e) { - e.printStackTrace(); - return true; + /** + * Add SellAll Item Trigger. + * + * Return true if success, false if error or already added item. + * + * @param material - Material to add. + * + * @return boolean. + * */ + public boolean addItemTrigger(Material material){ + return addItemTrigger(XMaterial.matchXMaterial(material)); + } + + /** + * Add Player to active delay. + * He'll be removed at the end of it. + * Also start delay. + * + * @param p - Player. + * */ + public void addToDelay(Player p){ + if (!isPlayerWaitingSellAllDelay(p)){ + activePlayerDelay.add(p); + Bukkit.getScheduler().scheduleSyncDelayedTask(SpigotPrison.getInstance(), () -> removeFromDelay(p), 20L * defaultSellAllDelay); } - updateSellAllConfig(); - return false; } - private boolean sellAllAddTrigger(Material blockAdd) { - try { - File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); - FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("ShiftAndRightClickSellAll.Items." + blockAdd.name() + ".ITEM_ID", blockAdd.name()); - conf.save(sellAllFile); - } catch (IOException e) { - e.printStackTrace(); + /** + * Add Player to active delay for AutoSell Notification. + * + * Return true if added with success, False if error or Player already added or disabled. + * + * @param p - Player. + * + * @return boolean. + * */ + public boolean addToAutoSellNotificationDelay(Player p){ + + if (!isAutoSellEarningNotificationDelayEnabled){ + return false; + } + + if (!isPlayerWaitingAutoSellNotification(p)){ + autoSellEarningsNotificationWaiting.put(p, 0.00); + Bukkit.getScheduler().scheduleSyncDelayedTask(SpigotPrison.getInstance(), () -> removeFromAutoSellDelayAndNotify(p), 20L * defaultAutoSellEarningNotificationDelay); return true; } - updateSellAllConfig(); + return false; } - private boolean sellAllAddTrigger(XMaterial blockAdd) { + /** + * Add balance to Delayed earnings of AutoSell Notification. + * + * @param p - Player. + * @param value - double. + * */ + public void addDelayedEarningAutoSellNotification(Player p, double value){ + if (isPlayerWaitingAutoSellNotification(p)){ + autoSellEarningsNotificationWaiting.put(p, autoSellEarningsNotificationWaiting.get(p) + value); + } + } + + private HashMap addInventoryToHashMap(HashMap xMaterialIntegerHashMap, Inventory inv) { + for (ItemStack itemStack : inv.getContents()){ + if (itemStack != null){ + XMaterial xMaterial = getXMaterialOrLapis(itemStack); + if (xMaterialIntegerHashMap.containsKey(xMaterial)){ + xMaterialIntegerHashMap.put(xMaterial, xMaterialIntegerHashMap.get(xMaterial) + itemStack.getAmount()); + } else { + xMaterialIntegerHashMap.put(xMaterial, itemStack.getAmount()); + } + } + } + return xMaterialIntegerHashMap; + } + + /** + * Check if Player meets requirements to use SellAll. + * + * This will return true if everything is meet, False if even only isn't. + * What will be checked is: + * - Is in a world where SellAll Sell isn't locked by config. + * - Check if SellAll Signs and SellAll by Sign only is enabled and Player isn't selling through a Sign right now or + * doesn't have the bypass permission (To tell to this method if Player is selling through a sign, please set the boolean + * parameter to true). + * - Check if a permission to sell is required and then if the Player has it. + * - Check if SellAll Delay is enabled and Player did wait until the end of it. + * + * @param p - Player. + * @param isUsingSign - boolean. + * + * @return boolean. + * */ + public boolean canPlayerSell(Player p, boolean isUsingSign){ + + if (isSellAllSellPermissionEnabled && !p.hasPermission(permissionSellAllSell)){ + return false; + } + + if (isPlayerInDisabledWorld(p)){ + return false; + } + + if (isSellAllSignEnabled && isSellAllBySignOnlyEnabled && !isUsingSign && !p.hasPermission(permissionBypassSign)){ + return false; + } + + if (isSellAllDelayEnabled && isPlayerWaitingSellAllDelay(p)){ + return false; + } + + return true; + } + + + /** + * Edit price of a block. + * + * Return true if edited with success, false if error or block not found. + * + * @param xMaterial - XMaterial to edit. + * @param value - New price as a double. + * + * @return boolean. + * */ + public boolean editPrice(XMaterial xMaterial, double value){ + + if (!sellAllBlocks.containsKey(xMaterial)){ + return false; + } + try { File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("ShiftAndRightClickSellAll.Items." + blockAdd.name() + ".ITEM_ID", blockAdd.name()); + conf.set("Items." + xMaterial.name() + ".ITEM_ID", xMaterial.name()); + conf.set("Items." + xMaterial.name() + ".ITEM_VALUE", value); + if (getBoolean(sellAllConfig.getString("Options.Sell_Per_Block_Permission_Enabled"))) { + conf.set("Items." + xMaterial + ".ITEM_PERMISSION", sellAllConfig.getString("Options.Sell_Per_Block_Permission") + xMaterial.name()); + } conf.save(sellAllFile); } catch (IOException e) { e.printStackTrace(); - return true; + return false; } - updateSellAllConfig(); - return false; + updateConfig(); + sellAllBlocks.put(xMaterial, value); + return true; } - private boolean sellAllAddTrigger(String itemID) { - try { - XMaterial blockAdd; - try { - blockAdd = XMaterial.valueOf(itemID); - } catch (IllegalArgumentException ex) { - return true; - } + /** + * Edit price of a block using Material. + * + * Return true if edited with success, false if error or not found. + * + * @param material - Material. + * @param value - New price as a double. + * + * @return boolean, + * */ + public boolean editPrice(Material material, double value){ + return editPrice(XMaterial.matchXMaterial(material), value); + } - try { - File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); - FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("ShiftAndRightClickSellAll.Items." + itemID + ".ITEM_ID", blockAdd.name()); - conf.save(sellAllFile); - } catch (IOException e) { - e.printStackTrace(); - return true; - } - } catch (IllegalArgumentException ex) { - return true; + /** + * Edit Prestige Multiplier value. + * + * Return true if success, false if error or not found. + * + * @param prestigeName - String. + * @param multiplier - Double value. + * */ + public boolean editPrestigeMultiplier(String prestigeName, double multiplier) { + + if (!sellAllPrestigeMultipliers.containsKey(prestigeName)) { + return false; } - updateSellAllConfig(); - return false; + + return addPrestigeMultiplier(prestigeName, multiplier); } - private boolean sellAllItemToggle(boolean enableInput) { + /** + * Remove block by XMaterial name. + * + * Return true if removed with success, false if not found or error. + * + * @param xMaterial - XMaterial to remove. + * + * @return boolean. + * */ + public boolean removeSellAllBlock(XMaterial xMaterial){ + + if (!sellAllBlocks.containsKey(xMaterial)){ + return false; + } + try { File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("Options.ShiftAndRightClickSellAll.Enabled", enableInput); + conf.set("Items." + xMaterial.name(), null); conf.save(sellAllFile); } catch (IOException e) { - return true; + e.printStackTrace(); + return false; } - updateSellAllConfig(); - return false; + updateConfig(); + sellAllBlocks.remove(xMaterial); + return true; } - private boolean sellAllDeleteMultiplierAction(String prestige) { - if (sellAllConfig.getConfigurationSection("Multiplier." + prestige) == null){ - return true; + /** + * Remove block by XMaterial name. + * + * Return true if removed with success, false if not found or error. + * + * @param material - XMaterial to remove. + * + * @return boolean. + * */ + public boolean removeSellAllBlock(Material material){ + return removeSellAllBlock(XMaterial.matchXMaterial(material)); + } + + /** + * Remove a Prestige Multiplier by name. + * + * Return true if success, false if error or not found. + * + * @param prestigeName - String. + * + * @return boolean. + * */ + public boolean removePrestigeMultiplier(String prestigeName){ + + if (!sellAllPrestigeMultipliers.containsKey(prestigeName)){ + return false; } try { File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("Multiplier." + prestige, null); + conf.set("Multiplier." + prestigeName, null); conf.save(sellAllFile); } catch (IOException e) { - return true; + return false; } - updateSellAllConfig(); - return false; + sellAllPrestigeMultipliers.remove(prestigeName); + updateConfig(); + return true; } - private boolean sellAllAddMultiplierAction(String prestige, Double multiplier) { - if (addMultiplierConditions(prestige)) return true; + /** + * Delete SellAll Item Trigger. + * + * Return true if success, false if error or item not found. + * + * @param xMaterial - XMaterial to remove. + * + * @return boolean. + * */ + public boolean removeItemTrigger(XMaterial xMaterial){ + + if (!sellAllItemTriggers.contains(xMaterial)){ + return false; + } try { File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("Multiplier." + prestige + ".PRESTIGE_NAME", prestige); - conf.set("Multiplier." + prestige + ".MULTIPLIER", multiplier); + conf.set("ShiftAndRightClickSellAll.Items." + xMaterial.name() + ".ITEM_ID", null); + conf.set("ShiftAndRightClickSellAll.Items." + xMaterial.name(), null); conf.save(sellAllFile); } catch (IOException e) { + e.printStackTrace(); return true; } - updateSellAllConfig(); - return false; + sellAllItemTriggers.remove(xMaterial); + updateConfig(); + return true; } - private boolean sellAllEditBlockAction(XMaterial xMaterial, Double value) { - if (sellAllConfig.getConfigurationSection("Items." + xMaterial.name()) == null) { - return true; + /** + * Delete SellAll Item Trigger. + * + * Return true if success, false if error or item not found. + * + * @param material - Material to remove. + * + * @return boolean. + * */ + public boolean removeItemTrigger(Material material){ + return removeItemTrigger(XMaterial.matchXMaterial(material)); + } + + /** + * Remove Sellable Blocks from HashMap of XMaterial-Integer given as a parameter. + * NOTE: If there aren't blocks in the SellAll shop, nothing will change. + * NOTE: This method will remove blocks from the HashMap, but it WON'T return the value of money, for that please use + * the getSellAllSellMoney method. + * + * @param p - Player. + * @param xMaterialIntegerHashMap - HashMap of XMaterial-Integer (Blocks of origin). + * + * + * @return HashMap - XMaterial-Integer. + * */ + public HashMap removeSellableItems(Player p, HashMap xMaterialIntegerHashMap){ + + if (sellAllBlocks.isEmpty()){ + return xMaterialIntegerHashMap; } - try { - try { - File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); - FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("Items." + xMaterial.name() + ".ITEM_ID", xMaterial.name()); - conf.set("Items." + xMaterial.name() + ".ITEM_VALUE", value); - if (getBoolean(sellAllConfig.getString("Options.Sell_Per_Block_Permission_Enabled"))) { - conf.set("Items." + xMaterial.name() + ".ITEM_PERMISSION", sellAllConfig.getString("Options.Sell_Per_Block_Permission") + xMaterial.name()); + /* Not necessary now, as this only removes what's sellable, this should be checked in another place before. + if (isPlayerInDisabledWorld(p)){ + return xMaterialIntegerHashMap; + } + */ + + for (HashMap.Entry xMaterialIntegerEntry : xMaterialIntegerHashMap.entrySet()){ + if (sellAllBlocks.containsKey(xMaterialIntegerEntry.getKey())){ + // This is stupid but right now I'm too confused, sorry. + if (isPerBlockPermissionEnabled && !p.hasPermission(permissionPrefixBlocks + xMaterialIntegerEntry.getKey().name())){ + // Nothing will happen. + } else { + xMaterialIntegerHashMap.remove(xMaterialIntegerEntry.getKey()); } - conf.save(sellAllFile); - } catch (IOException e) { - e.printStackTrace(); - return true; } - } catch (IllegalArgumentException ex) { - return true; } - updateSellAllConfig(); - return false; + + return xMaterialIntegerHashMap; } - private boolean sellAllEditBlockAction(ItemStack itemStack, Double value) { - if (sellAllConfig.getConfigurationSection("Items." + itemStack.getType().name()) == null) { - return true; + /** + * Remove Sellable Blocks from ArrayList of ItemStacks given as a parameter. + * NOTE: If there aren't blocks in the SellAll shop, nothing will change. + * NOTE: This method will remove blocks from the HashMap, but it WON'T return the value of money, for that please use + * the getSellAllSellMoney method. + * + * @param p - Player. + * @param itemStacks - ItemStacks. + * + * @return ArrayList - ItemStacks. + * */ + public ArrayList removeSellableItems(Player p, ArrayList itemStacks){ + + if (sellAllBlocks.isEmpty()){ + return itemStacks; } + + HashMap xMaterialIntegerHashMap = getXMaterialsHashMapFromArrayList(itemStacks); - try { - XMaterial xMaterial; - try { - xMaterial = XMaterial.matchXMaterial(itemStack); - } catch (IllegalArgumentException ex) { - return true; + xMaterialIntegerHashMap = removeSellableItems(p, xMaterialIntegerHashMap); + + ArrayList newItemStacks = new ArrayList<>(); + for (HashMap.Entry xMaterialIntegerEntry : xMaterialIntegerHashMap.entrySet()){ + Material material = xMaterialIntegerEntry.getKey().parseMaterial(); + if (material != null) { + newItemStacks.add(new ItemStack(material, xMaterialIntegerEntry.getValue())); } + } - try { - File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); - FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("Items." + xMaterial.name() + ".ITEM_ID", xMaterial.name()); - conf.set("Items." + xMaterial.name() + ".ITEM_VALUE", value); - if (getBoolean(sellAllConfig.getString("Options.Sell_Per_Block_Permission_Enabled"))) { - conf.set("Items." + xMaterial.name() + ".ITEM_PERMISSION", sellAllConfig.getString("Options.Sell_Per_Block_Permission") + xMaterial.name()); + return newItemStacks; + } + + /** + * Remove Sellable blocks from an Inventory of a Player. + * + * Return an Inventory with the unsold items. + * + * @param p - Player. + * @param inv - Inventory. + * + * @return inv - Inventory. + * */ + public Inventory removeSellableItems(Player p, Inventory inv){ + if (sellAllBlocks.isEmpty()){ + return inv; + } + + for (ItemStack itemStack : inv.getContents()){ + if (itemStack != null){ + XMaterial xMaterial = getXMaterialOrLapis(itemStack); + if (sellAllBlocks.containsKey(xMaterial)){ + if (isPerBlockPermissionEnabled && !p.hasPermission(permissionPrefixBlocks + xMaterial.name())){ + // Nothing will change. + } else { + inv.remove(itemStack); + } } - conf.save(sellAllFile); - } catch (IOException e) { - e.printStackTrace(); - return true; } - } catch (IllegalArgumentException ex) { - return true; } - updateSellAllConfig(); - return false; + + return inv; } + + /** + * Remove Sellable blocks from all Player inventories directly hooked. + * + * @param p - Player. + * */ + public void removeSellableItems(Player p){ - private boolean sellAllEditBlockAction(Material material, Double value) { - if (sellAllConfig.getConfigurationSection("Items." + material.name()) == null) { - return true; + if (sellAllBlocks.isEmpty()){ + return; } - try { - XMaterial xMaterial; - try { - xMaterial = XMaterial.matchXMaterial(material); - } catch (IllegalArgumentException ex) { - return true; - } - - try { - File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); - FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("Items." + xMaterial.name() + ".ITEM_ID", xMaterial.name()); - conf.set("Items." + xMaterial.name() + ".ITEM_VALUE", value); - if (getBoolean(sellAllConfig.getString("Options.Sell_Per_Block_Permission_Enabled"))) { - conf.set("Items." + xMaterial.name() + ".ITEM_PERMISSION", sellAllConfig.getString("Options.Sell_Per_Block_Permission") + xMaterial.name()); + if (isSellAllBackpackItemsEnabled && getBoolean(SpigotPrison.getInstance().getConfig().getString("backpacks"))){ + BackpacksUtil backpacksUtil = BackpacksUtil.get(); + if (backpacksUtil.isMultipleBackpacksEnabled()){ + for (String id : backpacksUtil.getBackpacksIDs(p)){ + backpacksUtil.setInventory(p, removeSellableItems(p, backpacksUtil.getBackpack(p, id)), id); } - conf.save(sellAllFile); - } catch (IOException e) { - e.printStackTrace(); - return true; + } else { + backpacksUtil.setInventory(p, removeSellableItems(p, backpacksUtil.getBackpack(p))); } - } catch (IllegalArgumentException ex) { - return true; } - updateSellAllConfig(); - return false; - } - private boolean sellAllEditBlockAction(String itemID, Double value) { - if (sellAllConfig.getConfigurationSection("Items." + itemID) == null) { - return true; + if (isSellAllMinesBackpacksPluginEnabled && IntegrationMinepacksPlugin.getInstance().isEnabled()){ + Backpack backpack = IntegrationMinepacksPlugin.getInstance().getMinepacks().getBackpackCachedOnly(p); + if (backpack != null) { + removeSellableItems(p, backpack.getInventory()); + } } - try { - XMaterial xMaterial; - try { - xMaterial = XMaterial.valueOf(itemID); - } catch (IllegalArgumentException ex) { - return true; - } + removeSellableItems(p, p.getInventory()); + } - try { - File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); - FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("Items." + itemID + ".ITEM_ID", xMaterial.name()); - conf.set("Items." + itemID + ".ITEM_VALUE", value); - if (getBoolean(sellAllConfig.getString("Options.Sell_Per_Block_Permission_Enabled"))) { - conf.set("Items." + itemID + ".ITEM_PERMISSION", sellAllConfig.getString("Options.Sell_Per_Block_Permission") + xMaterial.name()); - } - conf.save(sellAllFile); - } catch (IOException e) { - e.printStackTrace(); - return true; - } - } catch (IllegalArgumentException ex) { - return true; + /** + * Remove Player from delay. + * + * @param p - Player. + * */ + public void removeFromDelay(Player p){ + activePlayerDelay.remove(p); + } + + /** + * Remove Player from AutoSell Delay Notification and also send a notification to him with the balance until then. + * + * @param p - Player. + * */ + public void removeFromAutoSellDelayAndNotify(Player p){ + if (autoSellEarningsNotificationWaiting.containsKey(p) && autoSellEarningsNotificationWaiting.get(p) > 0.00){ + Output.get().sendInfo(new SpigotPlayer(p), SpigotPrison.format(messages.getString("Message.SellAllAutoSellEarnedMoney") + autoSellEarningsNotificationWaiting.get(p) + messages.getString("Message.SellAllAutoSellEarnedMoneyCurrency"))); } - updateSellAllConfig(); - return false; + autoSellEarningsNotificationWaiting.remove(p); } - private boolean sellAllDeleteAction(XMaterial xMaterial) { - if (sellAllConfig.getConfigurationSection("Items." + xMaterial.name()) == null) { - return true; + /** + * Set SellAll item trigger. + * + * Return true if run with success, false if error or already enabled/disabled. + * + * @param isEnabled - True to enable, False to disable. + * + * @return boolean. + * */ + public boolean setItemTrigger(Boolean isEnabled){ + if (isSellAllItemTriggerEnabled == isEnabled){ + return false; } try { File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("Items." + xMaterial.name(), null); + conf.set("Options.ShiftAndRightClickSellAll.Enabled", isEnabled); conf.save(sellAllFile); } catch (IOException e) { - e.printStackTrace(); return true; } - updateSellAllConfig(); - return false; + isSellAllItemTriggerEnabled = isEnabled; + updateConfig(); + return true; } - private boolean sellAllDeleteAction(ItemStack itemStack) { - - XMaterial xMaterial; - try { - xMaterial = XMaterial.matchXMaterial(itemStack); - } catch (IllegalArgumentException ex) { - return true; - } - - if (sellAllConfig.getConfigurationSection("Items." + xMaterial.name()) == null) { - return true; + /** + * Set SellAll AutoSell. + * + * Return true if success, false if error or already enabled/disabled. + * + * @param isEnabled - True to enable, False to disable. + * + * @return boolean. + * */ + public boolean setAutoSell(Boolean isEnabled){ + if (isAutoSellEnabled == isEnabled){ + return false; } try { File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("Items." + xMaterial.name(), null); + conf.set("Options.Full_Inv_AutoSell", isEnabled); conf.save(sellAllFile); } catch (IOException e) { e.printStackTrace(); - return true; + return false; } - updateSellAllConfig(); - return false; - } - private boolean sellAllDeleteAction(Material material) { + isAutoSellEnabled = isEnabled; + updateConfig(); + return true; + } - XMaterial xMaterial; - try { - xMaterial = XMaterial.matchXMaterial(material); - } catch (IllegalArgumentException ex) { - return true; + /** + * Set AutoSell Player. + * + * Return True if success, False if error or already enabled/disabled or missing permission. + * + * @param p - Player. + * @param enable - boolean. + * + * @return boolean. + * */ + public boolean setAutoSellPlayer(Player p, boolean enable){ + if (!isAutoSellEnabled || !isAutoSellPerUserToggleable){ + return false; } - if (sellAllConfig.getConfigurationSection("Items." + xMaterial.name()) == null) { - return true; + if (isAutoSellPerUserToggleablePermEnabled && !p.hasPermission(permissionAutoSellPerUserToggleable)){ + return false; } try { File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("Items." + xMaterial.name(), null); + conf.set("Users." + p.getUniqueId() + ".isEnabled", enable); conf.save(sellAllFile); } catch (IOException e) { + Output.get().sendError(new SpigotPlayer(p), SpigotPrison.format(messages.getString("Message.SellAllConfigSaveFail"))); e.printStackTrace(); - return true; + return false; } - updateSellAllConfig(); - return false; + return true; } - private boolean sellAllDeleteAction(String itemID) { - - XMaterial xMaterial; - try { - xMaterial = XMaterial.valueOf(itemID); - } catch (IllegalArgumentException ex) { - return true; - } - - if (sellAllConfig.getConfigurationSection("Items." + xMaterial.name()) == null) { - return true; + /** + * Set SellAllAutoSellPerUserToggleable. + * + * Return true if success, false if error or already enabled/disabled. + * + * @param isEnabled - True to enable, False to disable. + * + * @return boolean. + * */ + public boolean setAutoSellPerUserToggleable(boolean isEnabled){ + if (isAutoSellPerUserToggleable == isEnabled){ + return false; } try { File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("Items." + xMaterial.name(), null); + conf.set("Options.Full_Inv_AutoSell_perUserToggleable", isEnabled); conf.save(sellAllFile); } catch (IOException e) { e.printStackTrace(); - return true; + return false; } - updateSellAllConfig(); - return false; + isAutoSellPerUserToggleable = isEnabled; + updateConfig(); + return true; } - private boolean sellAllAddBlockAction(XMaterial xMaterial, Double value) { - try { - File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); - FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("Items." + xMaterial.name() + ".ITEM_ID", xMaterial.name()); - conf.set("Items." + xMaterial.name() + ".ITEM_VALUE", value); - if (getBoolean(sellAllConfig.getString("Options.Sell_Per_Block_Permission_Enabled"))) { - conf.set("Items." + xMaterial.name() + ".ITEM_PERMISSION", sellAllConfig.getString("Options.Sell_Per_Block_Permission") + xMaterial.name()); - } - conf.save(sellAllFile); - } catch (IOException e) { - e.printStackTrace(); - return true; - } - updateSellAllConfig(); - return false; - } - - private boolean sellAllAddBlockAction(ItemStack itemStack, Double value) { - try { - XMaterial blockAdd; - try { - blockAdd = XMaterial.matchXMaterial(itemStack); - } catch (IllegalArgumentException ex) { - return true; - } - - try { - File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); - FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("Items." + blockAdd.name() + ".ITEM_ID", blockAdd.name()); - conf.set("Items." + blockAdd.name() + ".ITEM_VALUE", value); - if (getBoolean(sellAllConfig.getString("Options.Sell_Per_Block_Permission_Enabled"))) { - conf.set("Items." + blockAdd.name() + ".ITEM_PERMISSION", sellAllConfig.getString("Options.Sell_Per_Block_Permission") + blockAdd.name()); - } - conf.save(sellAllFile); - } catch (IOException e) { - e.printStackTrace(); - return true; - } - } catch (IllegalArgumentException ex) { - return true; - } - updateSellAllConfig(); - return false; - } - - private boolean sellAllAddBlockAction(Material material, Double value) { - try { - XMaterial blockAdd; - try { - blockAdd = XMaterial.matchXMaterial(material); - } catch (IllegalArgumentException ex) { - return true; - } - - try { - File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); - FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("Items." + blockAdd.name() + ".ITEM_ID", blockAdd.name()); - conf.set("Items." + blockAdd.name() + ".ITEM_VALUE", value); - if (getBoolean(sellAllConfig.getString("Options.Sell_Per_Block_Permission_Enabled"))) { - conf.set("Items." + blockAdd.name() + ".ITEM_PERMISSION", sellAllConfig.getString("Options.Sell_Per_Block_Permission") + blockAdd.name()); - } - conf.save(sellAllFile); - } catch (IOException e) { - e.printStackTrace(); - return true; - } - } catch (IllegalArgumentException ex) { - return true; - } - updateSellAllConfig(); - return false; - } - - private boolean sellAllAddBlockAction(String itemID, Double value) { - try { - XMaterial blockAdd; - try { - blockAdd = XMaterial.valueOf(itemID); - } catch (IllegalArgumentException ex) { - return true; - } - - try { - File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); - FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("Items." + blockAdd.name() + ".ITEM_ID", blockAdd.name()); - conf.set("Items." + blockAdd.name() + ".ITEM_VALUE", value); - if (getBoolean(sellAllConfig.getString("Options.Sell_Per_Block_Permission_Enabled"))) { - conf.set("Items." + blockAdd.name() + ".ITEM_PERMISSION", sellAllConfig.getString("Options.Sell_Per_Block_Permission") + blockAdd.name()); - } - conf.save(sellAllFile); - } catch (IOException e) { - e.printStackTrace(); - return true; - } - } catch (IllegalArgumentException ex) { - return true; - } - updateSellAllConfig(); - return false; - } - - private void sellAllAddCommandMethod(XMaterial xMaterial, Double value) { - String itemID = xMaterial.name(); - - // If the block or item was already configured, then skip this: - if (sellAllConfig.getConfigurationSection("Items." + itemID) != null) { - return; - } - - try { - File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); - FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("Items." + itemID + ".ITEM_ID", xMaterial.name()); - conf.set("Items." + itemID + ".ITEM_VALUE", value); - if (getBoolean(sellAllConfig.getString("Options.Sell_Per_Block_Permission_Enabled"))) { - conf.set("Items." + itemID + ".ITEM_PERMISSION", sellAllConfig.getString("Options.Sell_Per_Block_Permission") + xMaterial.name()); - } - conf.save(sellAllFile); - } catch (IOException e) { - Output.get().logError(SpigotPrison.format(messages.getString("Message.SellAllConfigSaveFail")), e); - return; - } - - Output.get().logInfo(SpigotPrison.format("&3 ITEM [" + itemID + ", " + value + messages.getString("Message.SellAllAddSuccess"))); - sellAllConfigUpdater(); - } - - private boolean sellAllOpenGUI(Player p) { - updateSellAllConfig(); - // If the Admin GUI's enabled will enter do this, if it isn't it'll try to open the Player GUI. - boolean guiEnabled = getBoolean(sellAllConfig.getString("Options.GUI_Enabled")); - if (guiEnabled) { - // Check if a permission's required, if it isn't it'll open immediately the GUI. - if (getBoolean(sellAllConfig.getString("Options.GUI_Permission_Enabled"))) { - // Check if the sender have the required permission. - String guiPermission = sellAllConfig.getString("Options.GUI_Permission"); - if (guiPermission != null && p.hasPermission(guiPermission)) { - SellAllAdminGUI gui = new SellAllAdminGUI(p); - gui.open(); - return true; - // Try to open the Player GUI anyway. - } else if (sellAllPlayerGUI(p)) return true; - // Open the Admin GUI because a permission isn't required. - } else { - SellAllAdminGUI gui = new SellAllAdminGUI(p); - gui.open(); - return true; - } - } - - // If the admin GUI's disabled, it'll try to use the Player GUI anyway. - return sellAllPlayerGUI(p); - } - - private void sellAllSellPlayer(Player p) { - sellAllSellPlayer( p, true, false ); - } - private void sellAllSellPlayer(Player p, boolean notifications, boolean bySignOnly) { - - updateSellAllConfig(); - - boolean sellAllSignEnabled = getBoolean(sellAllConfig.getString("Options.SellAll_Sign_Enabled")); - boolean sellAllBySignOnlyEnabled = getBoolean(sellAllConfig.getString("Options.SellAll_By_Sign_Only")); - String byPassPermission = sellAllConfig.getString("Options.SellAll_By_Sign_Bypass_Permission"); - if (sellAllSignEnabled && sellAllBySignOnlyEnabled && (byPassPermission == null || byPassPermission != null && !p.hasPermission(byPassPermission))) { - if (!bySignOnly) { - Output.get().sendWarn(new SpigotPlayer(p), SpigotPrison.format(messages.getString("Message.SellAllSignOnly"))); - return; - } - } - -// if (signUsed) signUsed = false; - - boolean sellSoundEnabled = notifications && getBoolean(sellAllConfig.getString("Options.Sell_Sound_Enabled")); - Compatibility compat = SpigotPrison.getInstance().getCompatibility(); - if (!(sellAllConfig.getConfigurationSection("Items.") == null)) { - - if (sellAllCommandDelay(p)) return; - - // Get Spigot Player. - SpigotPlayer sPlayer = new SpigotPlayer(p); - - // Get money to give + multiplier. - double moneyToGive = getMoneyWithMultiplier(p, true); - - // Check if Ranks are enabled. - ModuleManager modMan = Prison.get().getModuleManager(); - Module module = modMan == null ? null : modMan.getModule( PrisonRanks.MODULE_NAME ).orElse( null ); - PrisonRanks rankPlugin = (PrisonRanks) module; - if (rankPlugin == null){ - Output.get().sendError(new SpigotPlayer(p), SpigotPrison.format("Ranks are disabled, you can't use this without Ranks enabled!")); - return; - } - - RankPlayer rankPlayer = PrisonRanks.getInstance().getPlayerManager().getPlayer(sPlayer.getUUID(), sPlayer.getName()); - String currency = sellAllConfig.getString("Options.SellAll_Currency"); - if (currency != null && currency.equalsIgnoreCase("default")) currency = null; - - rankPlayer.addBalance(currency, moneyToGive); - - boolean sellNotifyEnabled = notifications && getBoolean(sellAllConfig.getString("Options.Sell_Notify_Enabled")); - if (moneyToGive < 0.001) { - if (sellSoundEnabled) { - Sound sound; - try { - sound = Sound.valueOf(sellAllConfig.getString("Options.Sell_Sound_Fail_Name")); - } catch (IllegalArgumentException ex) { - sound = compat.getAnvilSound(); - } - p.playSound(p.getLocation(), sound, 3, 1); - } - if (sellNotifyEnabled) { - Output.get().sendInfo(new SpigotPlayer(p), SpigotPrison.format(messages.getString("Message.SellAllNothingToSell"))); - } - } else { - if (activeAutoSellPlayers.containsKey(p) && getBoolean(sellAllConfig.getString("Options.Full_Inv_AutoSell_EarnedMoneyNotificationDelay_Enabled"))) { - activeAutoSellPlayers.put(p, activeAutoSellPlayers.get(p) + moneyToGive); - } else { - if (sellSoundEnabled) { - Sound sound; - try { - sound = Sound.valueOf(sellAllConfig.getString("Options.Sell_Sound_Success_Name")); - } catch (IllegalArgumentException ex) { - sound = compat.getLevelUpSound(); - } - p.playSound(p.getLocation(), sound, 3, 1); - } - if (sellNotifyEnabled) { - DecimalFormat formatDecimal = new DecimalFormat("###,##0.00"); - Output.get().sendInfo(new SpigotPlayer(p), SpigotPrison.format(messages.getString("Message.SellAllYouGotMoney") + PlaceholdersUtil.formattedKmbtSISize(moneyToGive, formatDecimal, ""))); - } - } - } - } else { - if (sellSoundEnabled) { - Sound sound; - try { - sound = Sound.valueOf(sellAllConfig.getString("Options.Sell_Sound_Fail_Name")); - } catch (IllegalArgumentException ex) { - sound = compat.getAnvilSound(); - } - p.playSound(p.getLocation(), sound, 3, 1); - } - Output.get().sendWarn(new SpigotPlayer(p), SpigotPrison.format(messages.getString("Message.SellAllEmpty"))); - } - } - - private static SellAllUtil instanceUpdater() { - if (SpigotPrison.getInstance().getConfig().getString("sellall").equalsIgnoreCase("true") && instance == null) { - instance = new SellAllUtil(); - } - - return instance; - } - - private boolean sellAllAutoSellPerUserToggleableToggle(boolean enableBoolean) { - try { - File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); - FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("Options.Full_Inv_AutoSell_perUserToggleable", enableBoolean); - conf.save(sellAllFile); - } catch (IOException e) { - e.printStackTrace(); - return true; + /** + * Set SellAll Currency by name. + * + * Return True if success, False if error or invalid currency. + * + * @param currency - String. + * + * @return boolean. + * */ + public boolean setCurrency(String currency){ + EconomyCurrencyIntegration currencyEcon = PrisonAPI.getIntegrationManager().getEconomyForCurrency(currency); + if (currencyEcon == null && !currency.equalsIgnoreCase("default")) { + return false; } - updateSellAllConfig(); - return false; - } - private boolean sellAllAutoSellToggle(boolean enableBoolean) { try { File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("Options.Full_Inv_AutoSell", enableBoolean); + conf.set("Options.SellAll_Currency", currency); conf.save(sellAllFile); } catch (IOException e) { e.printStackTrace(); - return true; - } - sellAllConfigUpdater(); - return false; - } - - private boolean sellAllAutoSellPlayerToggle(Player p) { - // Get Player UUID. - UUID playerUUID = p.getUniqueId(); - - if (sellAllConfig.getString("Users." + playerUUID + ".isEnabled") != null){ - - boolean isEnabled = getBoolean(sellAllConfig.getString("Users." + playerUUID + ".isEnabled")); - try { - File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); - FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("Users." + playerUUID + ".isEnabled", !isEnabled); - conf.save(sellAllFile); - } catch (IOException e) { - Output.get().sendError(new SpigotPlayer(p), SpigotPrison.format(messages.getString("Message.SellAllConfigSaveFail"))); - e.printStackTrace(); - return true; - } - - if (isEnabled){ - Output.get().sendInfo(new SpigotPlayer(p), SpigotPrison.format(messages.getString("Message.SellAllAutoDisabled"))); - } else { - Output.get().sendInfo(new SpigotPlayer(p), SpigotPrison.format(messages.getString("Message.SellAllAutoEnabled"))); - } - - } else { - - // Enable it for the first time - try { - File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); - FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("Users." + playerUUID + ".isEnabled", true); - conf.set("Users." + playerUUID + ".name", p.getName()); - conf.save(sellAllFile); - } catch (IOException e) { - Output.get().sendError(new SpigotPlayer(p), SpigotPrison.format(messages.getString("Message.SellAllConfigSaveFail"))); - e.printStackTrace(); - return true; - } - - Output.get().sendInfo(new SpigotPlayer(p), SpigotPrison.format(messages.getString("Message.SellAllAutoEnabled"))); + return false; } - return false; + sellAllCurrency = currency; + updateConfig(); + return true; } - private boolean sellAllDelaySave(int delayValue) { + /** + * Enable or disable SellAll delay. + * + * Return True if success, False if error. + * + * @param enabled - Boolean. + * + * @return boolean. + * */ + public boolean setDelayEnable(boolean enabled){ try { File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("Options.Sell_Delay_Seconds", delayValue); + conf.set("Options.Sell_Delay_Enabled", enabled); conf.save(sellAllFile); } catch (IOException e) { e.printStackTrace(); - return true; + return false; } - sellAllConfigUpdater(); - return false; + isSellAllDelayEnabled = enabled; + updateConfig(); + return true; } - private boolean sellAllDelayToggle(boolean enableBoolean) { + /** + * Set SellAll Delay. + * + * Return True if success, False if error. + * + * @param delay - Integer. + * + * @return boolean. + * */ + public boolean setDelay(int delay){ try { File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("Options.Sell_Delay_Enabled", enableBoolean); + conf.set("Options.Sell_Delay_Seconds", delay); conf.save(sellAllFile); } catch (IOException e) { e.printStackTrace(); - return true; + return false; } - sellAllConfigUpdater(); - return false; + defaultSellAllDelay = delay; + updateConfig(); + return true; } - private boolean sellAllCurrencySaver(String currency) { - - EconomyCurrencyIntegration currencyEcon = PrisonAPI.getIntegrationManager().getEconomyForCurrency(currency); - if (currencyEcon == null && !currency.equalsIgnoreCase("default")) { - return true; - } - - try { - File sellAllFile = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); - FileConfiguration conf = YamlConfiguration.loadConfiguration(sellAllFile); - conf.set("Options.SellAll_Currency", currency); - conf.save(sellAllFile); - } catch (IOException e) { - e.printStackTrace(); - return true; + /** + * Sell removing items from Inventories and checking all the possible conditions that a Player must meet to sell + * items, this includes method parameters like: + * - Is using SellAll Sign. + * - If tell the Player how much did he earn (if this's disabled by config, the parameter will be ignored). + * - If do this action without making the player notice it, disabling sounds and all messages. + * - If tell the Player to wait the end of SellAll Delay if not ended (if this's disabled by config, the parameter will be ignored). + * - If tell the Player how much did he earn only after a delay (AutoSell Delay Earnings will use this option for example). + * - If play sound on SellAll Sell (If sounds are disabled from the config, this parameter will be ignored. + * + * Return True if success, False if error or nothing changed or Player not meeting requirements. + * + * Default usage of this method: sellAllSell(p, false, false, true, false, false, true); + * + * @param p - Player. + * @param isUsingSign - boolean. + * @param completelySilent - boolean. + * @param notifyPlayerEarned - boolean. + * @param notifyPlayerDelay - boolean. + * @param notifyPlayerEarningDelay - boolean. + * @param playSoundOnSellAll - boolean. + * + * @return boolean. + * */ + public boolean sellAllSell(Player p, boolean isUsingSign, boolean completelySilent, boolean notifyPlayerEarned, boolean notifyPlayerDelay, boolean notifyPlayerEarningDelay, boolean playSoundOnSellAll){ + if (!isUsingSign && isSellAllSignEnabled && isSellAllBySignOnlyEnabled && !p.hasPermission(permissionBypassSign)){ + if (!completelySilent) { + Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.SellAllSignOnly")); + } + return false; } - sellAllConfigUpdater(); - return false; - } - - private double getNewMoneyToGive(Player p, boolean removeItems) { - // Money to give value, Player Inventory, Items config section. - double moneyToGive = 0; - Inventory inv = p.getInventory(); - Set items = sellAllConfig.getConfigurationSection("Items").getKeys(false); - - // Get values and XMaterials from config. - HashMap sellAllXMaterials = getDoubleXMaterialHashMap(items); - - // Get the items from the player inventory and for each of them check the conditions. - mode = inventorySellMode.PlayerInventory; - for (ItemStack itemStack : inv.getContents()) { - moneyToGive += getNewMoneyToGiveManager(p, inv, itemStack, removeItems, sellAllXMaterials); + if (isSellAllDelayEnabled && isPlayerWaitingSellAllDelay(p)){ + if (notifyPlayerDelay && !completelySilent) { + Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.SellAllWaitDelay")); + } + return false; } - // Check option and if enabled. - if (IntegrationMinepacksPlugin.getInstance().isEnabled() && - getBoolean(sellAllConfig.getString("Options.Sell_MinesBackPacks_Plugin_Backpack"))) { - - // Get money to give depending on Mines Backpacks plugin. - moneyToGive = sellAllGetMoneyToGiveMinesBackpacksPlugin(p, removeItems, moneyToGive, sellAllXMaterials); + if (sellAllBlocks.isEmpty()){ + if (!completelySilent){ + Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.SellAllEmpty")); + } + return false; } - // Check if enabled Prison backpacks and sellall on it. - if (getBoolean(SpigotPrison.getInstance().getConfig().getString("backpacks")) && - getBoolean(sellAllConfig.getString("Options.Sell_Prison_BackPack_Items"))) { + double money = getSellMoney(p); + if (money != 0){ - // Get money to give from the Prison backpacks. - moneyToGive = sellAllGetMoneyToGivePrisonBackpacks(p, removeItems, moneyToGive, sellAllXMaterials); - } + SpigotPlayer sPlayer = new SpigotPlayer(p); + RankPlayer rankPlayer = PrisonRanks.getInstance().getPlayerManager().getPlayer(sPlayer.getUUID(), sPlayer.getName()); + if (sellAllCurrency != null && sellAllCurrency.equalsIgnoreCase("default")) sellAllCurrency = null; + removeSellableItems(p); + rankPlayer.addBalance(sellAllCurrency, money); - return moneyToGive; - } + if (isSellAllDelayEnabled){ + addToDelay(p); + } - private double sellAllGetMoneyToGivePrisonBackpacks(Player p, boolean removeItems, double moneyToGive, HashMap sellAllXMaterials) { - if (BackpacksUtil.get().isMultipleBackpacksEnabled()) { - if (!BackpacksUtil.get().getBackpacksIDs(p).isEmpty()) { - for (String id : BackpacksUtil.get().getBackpacksIDs(p)) { - // If the backpack's the default one with a null ID then use this, if not get something else. - if (id == null) { - - Inventory backPack = BackpacksUtil.get().getBackpack(p); - mode = inventorySellMode.PrisonBackPackSingle; - - if (backPack != null) { - for (ItemStack itemStack : backPack.getContents()) { - if (itemStack != null) { - moneyToGive += getNewMoneyToGiveManager(p, backPack, itemStack, removeItems, sellAllXMaterials); - } - } - BackpacksUtil.get().setInventory(p, backPack); - } + if (!completelySilent) { + if (isSellAllSoundEnabled && playSoundOnSellAll) { + p.playSound(p.getLocation(), sellAllSoundSuccess, 3, 1); + } + if (notifyPlayerEarningDelay && isAutoSellEarningNotificationDelayEnabled){ + if (!isPlayerWaitingAutoSellNotification(p)){ + addToAutoSellNotificationDelay(p); } else { - - Inventory backPack = BackpacksUtil.get().getBackpack(p, id); - mode = inventorySellMode.PrisonBackPackMultiples; - idBeingProcessedBackpack = id; - if (backPack != null) { - for (ItemStack itemStack : backPack.getContents()) { - if (itemStack != null) { - moneyToGive += getNewMoneyToGiveManager(p, backPack, itemStack, removeItems, sellAllXMaterials); - } - } - BackpacksUtil.get().setInventory(p, backPack, id); - } + addDelayedEarningAutoSellNotification(p, money); } + } else if (notifyPlayerEarned){ + Output.get().sendInfo(sPlayer, messages.getString("Message.SellAllYouGotMoney") + money); } - idBeingProcessedBackpack = null; } - + return true; } else { - // Set mode and get Prison Backpack inventory - mode = inventorySellMode.PrisonBackPackSingle; - Inventory backPack = BackpacksUtil.get().getBackpack(p); - - if (backPack != null) { - for (ItemStack itemStack : backPack.getContents()) { - if (itemStack != null) { - moneyToGive += getNewMoneyToGiveManager(p, backPack, itemStack, removeItems, sellAllXMaterials); - } + if (!completelySilent){ + if (isSellAllSoundEnabled && playSoundOnSellAll) { + p.playSound(p.getLocation(), sellAllSoundFail, 3, 1); } - BackpacksUtil.get().setInventory(p, backPack); + Output.get().sendInfo(new SpigotPlayer(p), messages.getString("Message.SellAllNothingToSell")); } + return false; } - return moneyToGive; } - private double sellAllGetMoneyToGiveMinesBackpacksPlugin(Player p, boolean removeItems, double moneyToGive, HashMap sellAllXMaterials) { - // Set mode and get backpack - mode = inventorySellMode.MinesBackPack; - Backpack backPack = IntegrationMinepacksPlugin.getInstance().getMinepacks().getBackpackCachedOnly(p); - - if (backPack != null) { - Inventory inv = backPack.getInventory(); - for (ItemStack itemStack : inv.getContents()) { - if (itemStack != null) { - moneyToGive += getNewMoneyToGiveManager(p, inv, itemStack, removeItems, sellAllXMaterials); - } + /** + * Sell removing items from Inventories and checking all the possible conditions that a Player must meet to sell + * items, this includes method parameters like: + * - Is using SellAll Sign. + * - If tell the Player how much did he earn (if this's disabled by config, the parameter will be ignored). + * - If do this action without making the player notice it, disabling sounds and all messages. + * - If tell the Player to wait the end of SellAll Delay if not ended (if this's disabled by config, the parameter will be ignored). + * - If tell the Player how much did he earn only after a delay (AutoSell Delay Earnings will use this option for example). + * - If play sound on SellAll Sell (If sounds are disabled from the config, this parameter will be ignored. + * + * NOTE: With this method you can add an ArrayList of ItemStacks to sell, remove sold items (this will return the ArrayList without + * sold items), and give money to the player, also note that this will also trigger the usual sellall sell and sell everything sellable + * from all inventories and enabled backpacks of the Player. + * + * Return True if success, False if error or nothing changed or Player not meeting requirements. + * + * Default usage of this method: sellAllSell(p, false, false, true, false, false, true); + * + * @param p - Player. + * @param itemStacks - ArrayList of ItemStacks. + * @param isUsingSign - boolean. + * @param completelySilent - boolean. + * @param notifyPlayerEarned - boolean. + * @param notifyPlayerDelay - boolean. + * @param notifyPlayerEarningDelay - boolean. + * @param playSoundOnSellAll - boolean. + * + * @return boolean. + * */ + public ArrayList sellAllSell(Player p, ArrayList itemStacks, boolean isUsingSign, boolean completelySilent, boolean notifyPlayerEarned, boolean notifyPlayerDelay, boolean notifyPlayerEarningDelay, boolean playSoundOnSellAll){ + if (!isUsingSign && isSellAllSignEnabled && isSellAllBySignOnlyEnabled && !p.hasPermission(permissionBypassSign)){ + if (!completelySilent) { + Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.SellAllSignOnly")); } + return itemStacks; } - return moneyToGive; - } - - private HashMap getDoubleXMaterialHashMap(Set items) { - HashMap sellAllXMaterials = new HashMap<>(); - for (String key : items) { - // ItemID -// XMaterial itemMaterial = null; - String itemID = sellAllConfig.getString("Items." + key + ".ITEM_ID"); - - // NOTE: XMaterial is an exhaustive matching algorythem and will match on more than just the XMaterial enum name. - // WARNING: Do not use XMaterial.valueOf() since that only matches on enum name and appears to fail if the internal cache is empty? - Optional iMatOptional = XMaterial.matchXMaterial(itemID); - XMaterial itemMaterial = iMatOptional.orElse(null); - - if (itemMaterial != null) { - String valueString = sellAllConfig.getString("Items." + key + ".ITEM_VALUE"); - if (valueString != null) { - try { - // If we cannot get a valid value, then there is no point in adding the - // itemMaterial to the hash since it will be zero anyway: - double value = Double.parseDouble(valueString); - sellAllXMaterials.put(itemMaterial, value); - } catch (NumberFormatException ignored) { - } - } + if (isSellAllDelayEnabled && isPlayerWaitingSellAllDelay(p)){ + if (notifyPlayerDelay && !completelySilent) { + Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.SellAllWaitDelay")); } + return itemStacks; } - return sellAllXMaterials; - } - - private double getNewMoneyToGiveManager(Player p, Inventory inv, ItemStack itemStack, boolean removeItems, HashMap sellAllXMaterials) { - - double moneyToGive = 0; - - if (itemStack != null) { - - boolean perBlockPermissionEnabled = getBoolean(sellAllConfig.getString("Options.Sell_Per_Block_Permission_Enabled")); - String permission = sellAllConfig.getString("Options.Sell_Per_Block_Permission"); - - // First map itemStack to XMaterial: - try { - XMaterial invMaterial = getXMaterialOrLapis(itemStack); - - if (invMaterial != null && sellAllXMaterials.containsKey(invMaterial)) { - Double itemValue = sellAllXMaterials.get(invMaterial); - int amount = itemStack.getAmount(); - - // Check if per-block permission's enabled and if player has permission. - if (perBlockPermissionEnabled) { - permission = permission + invMaterial.name(); - - // Check if player have this permission, if not return 0 money earned for this item and don't remove it. - if (!p.hasPermission(permission)) { - return 0; - } - } - - if (removeItems) { - if (mode == inventorySellMode.PlayerInventory) { - inv.remove(itemStack); - } else if (IntegrationMinepacksPlugin.getInstance().isEnabled() && mode == inventorySellMode.MinesBackPack) { - inv.remove(itemStack); - } else if (mode == inventorySellMode.PrisonBackPackSingle) { - inv.remove(itemStack); - } else if (mode == inventorySellMode.PrisonBackPackMultiples) { - if (idBeingProcessedBackpack != null) { - inv.remove(itemStack); - } - } - } - - if (itemValue != null && amount > 0) { - moneyToGive += itemValue * amount; - } - } - } catch (IllegalArgumentException ignored) { + if (sellAllBlocks.isEmpty()){ + if (!completelySilent){ + Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.SellAllEmpty")); } + return itemStacks; } - return moneyToGive; - } - - private XMaterial getXMaterialOrLapis(ItemStack itemStack) { - if (itemStack.isSimilar(lapisLazuli)) { - return XMaterial.LAPIS_LAZULI; - } - return XMaterial.matchXMaterial(itemStack); - } - /** - * Open SellAll GUI for Players if enabled. - * - * @param p Player - * @return boolean - */ - private boolean sellAllPlayerGUI(Player p) { - - // Check if the Player GUI's enabled. - boolean playerGUIEnabled = getBoolean(sellAllConfig.getString("Options.Player_GUI_Enabled")); - if (playerGUIEnabled) { - // Check if a permission's required, if not it'll open directly the Player's GUI. - boolean playerGUIPermissionEnabled = getBoolean(sellAllConfig.getString("Options.Player_GUI_Permission_Enabled")); - if (playerGUIPermissionEnabled) { - // Check if the sender has the required permission. - String permission = sellAllConfig.getString("Options.Player_GUI_Permission"); - if (permission != null && p.hasPermission(permission)) { - SellAllPlayerGUI gui = new SellAllPlayerGUI(p, 0); - gui.open(); - // If missing will send a missing permission error message. - } else { - Output.get().sendInfo(new SpigotPlayer(p), SpigotPrison.format(messages.getString("Message.SellAllMissingPermission") + " [" + permission + "]")); - } - // Because a permission isn't required, it'll open directly the GUI. - } else { - SellAllPlayerGUI gui = new SellAllPlayerGUI(p, 0); - gui.open(); - } - return true; + double arrayListMoney = getSellMoney(p, itemStacks); + if (arrayListMoney != 0.00){ + itemStacks = removeSellableItems(p, itemStacks); } - return false; - } - /** - * Check if a player's waiting for his delay to end. - * Check if SellAllDelay's enabled. - * - * @param p Player - * @return boolean - */ - private boolean sellAllCommandDelay(Player p) { - - boolean sellDelayEnabled = getBoolean(sellAllConfig.getString("Options.Sell_Delay_Enabled")); - if (sellDelayEnabled) { + double money = getSellMoney(p) + arrayListMoney; + if (money != 0){ - if (activePlayerDelay.contains(p.getName())) { - Output.get().sendInfo(new SpigotPlayer(p), SpigotPrison.format(messages.getString("Message.SellAllWaitDelay"))); - return true; - } - - addPlayerToDelay(p); + SpigotPlayer sPlayer = new SpigotPlayer(p); + RankPlayer rankPlayer = PrisonRanks.getInstance().getPlayerManager().getPlayer(sPlayer.getUUID(), sPlayer.getName()); + if (sellAllCurrency != null && sellAllCurrency.equalsIgnoreCase("default")) sellAllCurrency = null; + removeSellableItems(p); + rankPlayer.addBalance(sellAllCurrency, money); - String delayInSeconds = sellAllConfig.getString("Options.Sell_Delay_Seconds"); - if (delayInSeconds == null) { - delayInSeconds = "1"; + if (isSellAllDelayEnabled){ + addToDelay(p); } - Bukkit.getScheduler().scheduleSyncDelayedTask(SpigotPrison.getInstance(), () -> removePlayerFromDelay(p), 20L * Integer.parseInt(delayInSeconds)); - } - - return false; - } - private boolean addMultiplierConditions(String prestige) { - - PrisonRanks rankPlugin = (PrisonRanks) (Prison.get().getModuleManager() == null ? null : Prison.get().getModuleManager().getModule(PrisonRanks.MODULE_NAME).orElse(null)); - if (rankPlugin == null) { - return true; - } - - boolean isPrestigeLadder = rankPlugin.getLadderManager().getLadder("prestiges") != null; - if (!isPrestigeLadder) { - return true; - } - - boolean isARank = rankPlugin.getRankManager().getRank(prestige) != null; - if (!isARank) { - return true; - } - - boolean isInPrestigeLadder = rankPlugin.getLadderManager().getLadder("prestiges").containsRank(rankPlugin.getRankManager().getRank(prestige)); - if (!isInPrestigeLadder) { - return true; - } - return false; - } - - private double getMultiplierByRank(SpigotPlayer sPlayer, Module module, double multiplier) { - if (module != null) { - PrisonRanks rankPlugin = (PrisonRanks) module; - if (rankPlugin.getPlayerManager().getPlayer(sPlayer) != null) { - String playerRankName; - try { - RankPlayer rankPlayer = rankPlugin.getPlayerManager().getPlayer(sPlayer); - PlayerRank pRank = rankPlayer == null ? null : rankPlayer.getRank("prestiges"); - Rank rank = pRank == null ? null : pRank.getRank(); - - playerRankName = rank == null ? null : rank.getName(); - } catch (NullPointerException ex) { - playerRankName = null; + if (!completelySilent) { + if (isSellAllSoundEnabled && playSoundOnSellAll) { + p.playSound(p.getLocation(), sellAllSoundSuccess, 3, 1); } - if (playerRankName != null) { - String multiplierRankString = sellAllConfig.getString("Multiplier." + playerRankName + ".MULTIPLIER"); - if (multiplierRankString != null) { - try { - multiplier = Double.parseDouble(multiplierRankString); - } catch (NumberFormatException ignored) { - } + + if (notifyPlayerEarningDelay && isAutoSellEarningNotificationDelayEnabled){ + if (!isPlayerWaitingAutoSellNotification(p)){ + addToAutoSellNotificationDelay(p); + } else { + addDelayedEarningAutoSellNotification(p, money); } + } else if (notifyPlayerEarned){ + Output.get().sendInfo(sPlayer, messages.getString("Message.SellAllYouGotMoney") + money); } } - } - return multiplier; - } - - private double getMultiplierExtraByPerms(List perms, double multiplierExtraByPerms) { - boolean multiplierPermissionHighOption = getBoolean(sellAllConfig.getString("Options.Multiplier_Permission_Only_Higher")); - for (String multByPerm : perms) { - double multByPermDouble = Double.parseDouble(multByPerm.substring(26)); - if (!multiplierPermissionHighOption) { - multiplierExtraByPerms += multByPermDouble; - } else if (multByPermDouble > multiplierExtraByPerms) { - multiplierExtraByPerms = multByPermDouble; + return itemStacks; + } else { + if (!completelySilent){ + if (isSellAllSoundEnabled && playSoundOnSellAll) { + p.playSound(p.getLocation(), sellAllSoundFail, 3, 1); + } + Output.get().sendInfo(new SpigotPlayer(p), messages.getString("Message.SellAllNothingToSell")); } + return itemStacks; } - return multiplierExtraByPerms; - } - - /** - * Get sellAllConfig updated. - */ - private void sellAllConfigUpdater() { - - // Get updated config. - sellAllConfig = YamlConfiguration.loadConfiguration(new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml")); } /** - * Add a Player to delay. + * Open SellAll GUI to the specified Player. + * NOTE: SellAll GUI must be enabled from the config or nothing will happen. + * NOTE #2: A Player if admin will open another GUI if meets requirements, if not it will try to check + * if it meets the normal Player GUI requirements and open that one instead. * - * @param p Player - */ - private void addPlayerToDelay(Player p) { - - if (!isEnabled()) return; - - if (!activePlayerDelay.contains(p.getName())) { - activePlayerDelay.add(p.getName()); - } - } - - /** - * Removes a Player from delay. + * Return true if success, false if error, disabled or missing permission. * - * @param p Player - */ - private void removePlayerFromDelay(Player p) { - - if (!isEnabled()) return; - - activePlayerDelay.remove(p.getName()); - } - -// private void sellAllSignToggler() { -// if (!signUsed) { -// signUsed = true; -// } -// } - - private double getMoneyFinal(Player player, boolean removeItems) { - SpigotPlayer sPlayer = new SpigotPlayer(player); - - // Get money to give - double moneyToGive = getNewMoneyToGive(sPlayer.getWrapper(), removeItems); - boolean multiplierEnabled = getBoolean(sellAllConfig.getString("Options.Multiplier_Enabled")); - if (multiplierEnabled) { - moneyToGive = moneyToGive * getMultiplier(sPlayer); - } - - // Log the amount of money earned to generate the average earned per minute for the player: - if ( moneyToGive > 0 ) { - PlayerCache.getInstance().addPlayerEarnings( sPlayer, moneyToGive ); - } - return moneyToGive; - } - - private double getMultiplierMethod(SpigotPlayer sPlayer) { - // Get Ranks module. - ModuleManager modMan = Prison.get().getModuleManager(); - Module module = modMan == null ? null : modMan.getModule(PrisonRanks.MODULE_NAME).orElse(null); - - // Get default multiplier - String multiplierString = sellAllConfig.getString("Options.Multiplier_Default"); - double multiplier = 0; - if (multiplierString != null) { - multiplier = Double.parseDouble(multiplierString); + * @param p - Player. + * + * @return boolean. + * */ + public boolean openSellAllGUI(Player p){ + if (!isSellAllGUIEnabled){ + return false; } - // Get multiplier depending on Player + Prestige. NOTE that prestige multiplier will replace - // the actual default multiplier. - multiplier = getMultiplierByRank(sPlayer, module, multiplier); + if (isSellAllGUIPermissionEnabled && !p.hasPermission(permissionGUI)){ - // Get Multiplier from multipliers permission's if there's any. - List perms = sPlayer.getPermissions("prison.sellall.multiplier."); - double multiplierExtraByPerms = 0; - multiplierExtraByPerms = getMultiplierExtraByPerms(perms, multiplierExtraByPerms); - multiplier += multiplierExtraByPerms; - - return multiplier; - } + if (!isSellAllPlayerGUIEnabled){ + return false; + } - private void taskSellAllAutoActions(Player p) { - if (activeAutoSellPlayers.containsKey(p)) { - if (activeAutoSellPlayers.get(p) != 0.00) { - Output.get().sendInfo(new SpigotPlayer(p), SpigotPrison.format(messages.getString("Message.SellAllAutoSellEarnedMoney") + activeAutoSellPlayers.get(p) + messages.getString("Message.SellAllAutoSellEarnedMoneyCurrency"))); + if (isSellAllPlayerGUIPermissionEnabled && !p.hasPermission(permissionPlayerGUI)){ + return false; } - activeAutoSellPlayers.remove(p); + + SellAllPlayerGUI gui = new SellAllPlayerGUI(p, 0); + gui.open(); + return true; } + + SellAllAdminGUI gui = new SellAllAdminGUI(p); + gui.open(); + return true; } } \ No newline at end of file From 2508ec4b15d0781e4c5bfb24e5c7beec32d3cb06 Mon Sep 17 00:00:00 2001 From: AnonymousGCA Date: Tue, 24 Aug 2021 19:36:47 +0200 Subject: [PATCH 002/283] Changelogs: - Minor changes to SellAll Util. - Added /SellAll Hand command. - Added an option to enable or disable SellAll Hand from the sellallconfig.yml. --- docs/changelog_v3.3.x.md | 7 +++ .../commands/PrisonSpigotSellAllCommands.java | 49 ++++++++++++++++++- .../prison/spigot/configs/SellAllConfig.java | 1 + .../prison/spigot/sellall/SellAllUtil.java | 19 +++++-- 4 files changed, 69 insertions(+), 7 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 53e5174e9..d10ca11bb 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -14,6 +14,13 @@ These build logs represent the work that has been going on within prison. # 3.2.11 2021-08-23 + +* **Added /sellall hand command.** + + +* **Minor changes to SellAll Util.** + + * **Much better performance for SellAll generally.** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotSellAllCommands.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotSellAllCommands.java index c31952b65..e88ef4aff 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotSellAllCommands.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotSellAllCommands.java @@ -5,6 +5,7 @@ import com.cryptomorin.xseries.XMaterial; +import org.bukkit.inventory.ItemStack; import tech.mcprison.prison.Prison; import tech.mcprison.prison.PrisonAPI; import tech.mcprison.prison.commands.Arg; @@ -15,10 +16,14 @@ import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.SpigotPlatform; import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.compat.Compatibility; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.sellall.SellAllBlockData; import tech.mcprison.prison.spigot.sellall.SellAllUtil; +import java.util.ArrayList; +import java.util.Collection; + /** * @author GABRYCA * @author RoyalBlueRanger (rBluer) @@ -27,6 +32,7 @@ public class PrisonSpigotSellAllCommands extends PrisonSpigotBaseCommands { private static PrisonSpigotSellAllCommands instance; private final Configuration messages = SpigotPrison.getInstance().getMessagesConfig(); + private final Compatibility compat = SpigotPrison.getInstance().getCompatibility(); /** * Check if SellAll's enabled. @@ -182,7 +188,7 @@ private void sellAllAutoSell(CommandSender sender, } } - @Command(identifier = "sellall autosell perUserToggleable", description = "Enable AutoSell perUserToggleable", onlyPlayers = false, permissions = "prison.autosell.edit") + @Command(identifier = "sellall autosell perUserToggleable", description = "Enable AutoSell perUserToggleable.", onlyPlayers = false, permissions = "prison.autosell.edit") private void sellAllAutoSellPerUserToggleable(CommandSender sender, @Arg(name = "boolean", description = "True to enable or false to disable", def = "null") String enable){ @@ -217,7 +223,7 @@ private void sellAllAutoSellPerUserToggleable(CommandSender sender, } } - @Command(identifier = "sellall sell", description = "SellAll sell command", onlyPlayers = true) + @Command(identifier = "sellall sell", description = "SellAll sell command.", onlyPlayers = true) public void sellAllSellCommand(CommandSender sender, @Arg(name = "notification", def="", description = "Notification about the sellall transaction. Defaults to normal. " + @@ -252,6 +258,45 @@ public void sellAllSellCommand(CommandSender sender, sellAllUtil.sellAllSell(p, false, notifications, true, true, false, true); } + @Command(identifier = "sellall hand", description = "Sell only what is in your hand if sellable.", onlyPlayers = true) + public void sellAllSellHandCommand(CommandSender sender){ + + if (!isEnabled()) return; + + SellAllUtil sellAllUtil = SellAllUtil.get(); + + if (sellAllUtil == null){ + return; + } + + if (!sellAllUtil.isSellAllHandEnabled){ + Output.get().sendWarn(sender, "The command /sellall hand is disabled from the config!"); + return; + } + + Player p = getSpigotPlayer(sender); + + if (p == null){ + Output.get().sendInfo(sender, SpigotPrison.format("&cSorry but you can't use that from the console!")); + return; + } + + if (sellAllUtil.isPlayerInDisabledWorld(p)) return; + + if (sellAllUtil.isSellAllSellPermissionEnabled){ + String permission = sellAllUtil.permissionSellAllSell; + if (permission == null || !p.hasPermission(permission)){ + Output.get().sendWarn(new SpigotPlayer(p), SpigotPrison.format(messages.getString("Message.SellAllMissingPermission") + " [" + permission + "]")); + return; + } + } + + ArrayList itemStacks = new ArrayList<>(); + itemStacks.add(compat.getItemInMainHand(p)); + + sellAllUtil.sellAllSell(p, itemStacks, false, false, true, true, false, true, true); + } + public void sellAllSell(Player p){ if (!isEnabled()) return; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/SellAllConfig.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/SellAllConfig.java index ca8a3c01c..46ac1ee81 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/SellAllConfig.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/SellAllConfig.java @@ -91,6 +91,7 @@ private void values(){ dataConfig("Options.SellAll_By_Sign_Only_Bypass_Permission", "prison.admin"); dataConfig("Options.SellAll_Sign_Notify", false); dataConfig("Options.SellAll_Sign_Visible_Tag", "&7[&3SellAll&7]"); + dataConfig("Options.SellAll_Hand_Enabled", true); dataConfig("Options.Player_GUI_Enabled", true); dataConfig("Options.Player_GUI_Permission_Enabled",false); dataConfig("Options.Player_GUI_Permission","prison.sellall.playergui"); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java index dce94d20e..faa71f87e 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java @@ -90,6 +90,7 @@ public class SellAllUtil { public boolean isSellAllSoundEnabled; public boolean isSellAllBackpackItemsEnabled; public boolean isSellAllMinesBackpacksPluginEnabled; + public boolean isSellAllHandEnabled; /** * Get cached instance of SellAllUtil, if present, if not then Initialize it, if SellAll is disabled return null. @@ -528,6 +529,7 @@ private void initCachedData() { isSellAllSignNotifyEnabled = getBoolean(sellAllConfig.getString("Options.SellAll_Sign_Notify")); isSellAllSignPermissionToUseEnabled = getBoolean(sellAllConfig.getString("Options.SellAll_Sign_Use_Permission_Enabled")); isSellAllBySignOnlyEnabled = getBoolean(sellAllConfig.getString("Options.SellAll_By_Sign_Only")); + isSellAllHandEnabled = getBoolean(sellAllConfig.getString("Options.SellAll_Hand_Enabled")); } /** @@ -1472,6 +1474,7 @@ public boolean sellAllSell(Player p, boolean isUsingSign, boolean completelySile * - If tell the Player to wait the end of SellAll Delay if not ended (if this's disabled by config, the parameter will be ignored). * - If tell the Player how much did he earn only after a delay (AutoSell Delay Earnings will use this option for example). * - If play sound on SellAll Sell (If sounds are disabled from the config, this parameter will be ignored. + * - If Sell only stuff from the input arrayList and not sell what is in the many Player inventories and supported backpacks. * * NOTE: With this method you can add an ArrayList of ItemStacks to sell, remove sold items (this will return the ArrayList without * sold items), and give money to the player, also note that this will also trigger the usual sellall sell and sell everything sellable @@ -1479,7 +1482,7 @@ public boolean sellAllSell(Player p, boolean isUsingSign, boolean completelySile * * Return True if success, False if error or nothing changed or Player not meeting requirements. * - * Default usage of this method: sellAllSell(p, false, false, true, false, false, true); + * Default usage of this method: sellAllSell(p, false, false, true, false, false, true, false); * * @param p - Player. * @param itemStacks - ArrayList of ItemStacks. @@ -1489,10 +1492,11 @@ public boolean sellAllSell(Player p, boolean isUsingSign, boolean completelySile * @param notifyPlayerDelay - boolean. * @param notifyPlayerEarningDelay - boolean. * @param playSoundOnSellAll - boolean. + * @param sellInputArrayListOnly - boolean. * * @return boolean. * */ - public ArrayList sellAllSell(Player p, ArrayList itemStacks, boolean isUsingSign, boolean completelySilent, boolean notifyPlayerEarned, boolean notifyPlayerDelay, boolean notifyPlayerEarningDelay, boolean playSoundOnSellAll){ + public ArrayList sellAllSell(Player p, ArrayList itemStacks, boolean isUsingSign, boolean completelySilent, boolean notifyPlayerEarned, boolean notifyPlayerDelay, boolean notifyPlayerEarningDelay, boolean playSoundOnSellAll, boolean sellInputArrayListOnly){ if (!isUsingSign && isSellAllSignEnabled && isSellAllBySignOnlyEnabled && !p.hasPermission(permissionBypassSign)){ if (!completelySilent) { Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.SellAllSignOnly")); @@ -1519,7 +1523,13 @@ public ArrayList sellAllSell(Player p, ArrayList itemStack itemStacks = removeSellableItems(p, itemStacks); } - double money = getSellMoney(p) + arrayListMoney; + double money; + if (sellInputArrayListOnly){ + money = arrayListMoney; + } else { + money = getSellMoney(p) + arrayListMoney; + } + if (money != 0){ SpigotPlayer sPlayer = new SpigotPlayer(p); @@ -1547,7 +1557,6 @@ public ArrayList sellAllSell(Player p, ArrayList itemStack Output.get().sendInfo(sPlayer, messages.getString("Message.SellAllYouGotMoney") + money); } } - return itemStacks; } else { if (!completelySilent){ if (isSellAllSoundEnabled && playSoundOnSellAll) { @@ -1555,8 +1564,8 @@ public ArrayList sellAllSell(Player p, ArrayList itemStack } Output.get().sendInfo(new SpigotPlayer(p), messages.getString("Message.SellAllNothingToSell")); } - return itemStacks; } + return itemStacks; } /** From 012d2b5be8e6b37d6212e9e4e8f8f2aecc5401d4 Mon Sep 17 00:00:00 2001 From: AnonymousGCA Date: Tue, 24 Aug 2021 19:40:12 +0200 Subject: [PATCH 003/283] Changelogs: - Correction to SellAllUtil method for sellall hand. --- .../tech/mcprison/prison/spigot/sellall/SellAllUtil.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java index faa71f87e..19bec56d4 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java @@ -1535,7 +1535,10 @@ public ArrayList sellAllSell(Player p, ArrayList itemStack SpigotPlayer sPlayer = new SpigotPlayer(p); RankPlayer rankPlayer = PrisonRanks.getInstance().getPlayerManager().getPlayer(sPlayer.getUUID(), sPlayer.getName()); if (sellAllCurrency != null && sellAllCurrency.equalsIgnoreCase("default")) sellAllCurrency = null; - removeSellableItems(p); + + if (!sellInputArrayListOnly) { + removeSellableItems(p); + } rankPlayer.addBalance(sellAllCurrency, money); if (isSellAllDelayEnabled){ From e44d33a718b7410868090f0a885adcb08d92ce2a Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Tue, 24 Aug 2021 15:29:18 -0400 Subject: [PATCH 004/283] Fixed a problem with Prison's ExplosiveBlockBreakHandler in that it has a typo in the getHandlerList() and was not included with the registration processes. It also needed to be included with the generation of the listener dumps. --- docs/changelog_v3.3.x.md | 949 +----------------- docs/prison_changelog_v3.2.10.md | 6 +- .../prison/spigot/SpigotPlatform.java | 10 +- .../spigot/api/ExplosiveBlockBreakEvent.java | 8 +- .../events/AutoManagerBlockBreakEvents.java | 16 +- 5 files changed, 36 insertions(+), 953 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index d10ca11bb..0e11438c3 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -12,7 +12,11 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11 2021-08-23 + +# 3.2.11-alpha.1 2021-08-24 + +* **Fixed a problem with Prison's ExplosiveBlockBreakHandler** + in that it has a typo in the getHandlerList() and was not included with the registration processes. It also needed to be included with the generation of the listener dumps. * **Added /sellall hand command.** @@ -32,951 +36,10 @@ These build logs represent the work that has been going on within prison. * **SellAllUtil Rewrite:** New internals for SellAll and SellAll API. -# v3.2.10 2021-08-22 - -* **Prison Release v3.2.10** - - -* **Updated to the support of the Prison's ExplosiveBlockBreakEvent. There were a few adjustments that were needed.** - - -* **Some blocks within the liners are not compatible with all versions of bukkit/spigot/minecraft.** -Added minimal versions to the patterns so as to help prevent the use of the wrong patterns for the server version. - - -* **Found an error with two Mine Liners that had pillar_quartz_block instead of quartz_pillar.** - - -* **Added support for Prison's own ExplosiveBlockBreakEvent.** -This will be used for Prison's up coming Prison Bombs. Also this can be used by other plugins too. - - -* **Update the PrisonEnchants code for handing their PEExplosionEvent object.** - - -* **Fix a problem with NPE when getting the player's Locale when it wasn't set.** - - -* **More adjustments to the /ranks list to add information about the player's current multipliers on all the ladders.** -This makes it easier to understand why the rank multiplier is a specific value. - - -* **Some adjustments to `/ranks list` to remove "admin stuff" from the list for non-admins.** - - -* **v3.2.10-alpha.14b 2021-08-22** - - -* **Removed the option to delete a rank from the ranks info command since it should not be that easy to remove a rank, which could easily be clicked on in game.** -Also commented out dead code. - - -* **Hook up the process to have all unjoined players added to prison by giving them the default rank.** -This is also ran now at the end of the /ranks autoConfigure to ensure all players are hooked up as soon as the default ladder and it's ranks exists. - - -* **Player join bug: Fixed a bug... if a player is not on the default ladder, then this was preventing them from being added.** - - -* **Added virtual checks to prevent placeholders from trying to access mine features that do not exist.** - - -* **v3.2.10-alpha.14 2021-08-21** - - -* **reduce what is shown on /rank if for non-op players.** - - -* **Decrease the autoConfigure's prestige costs from 2 B to just 1 B.** - - -* **Reload auto features after running ranks autoconfigure to enable the auto pickup.** -It wasn't working right after generating the mines. - - -* **Fixed an issue with virtual mines not being included in /mines list all command.** - - -* **Now `/ranks autoConfigure` creates 10 prestiges ranks. ** - - -* **Have placeholders reload after mines or ranks are created, removed, or renamed.** -Create mine and create rank now has an option to suppress updating placeholders since commands like autoConfigure will cause tons of messages to be generated. The placeholders are regenerated after all mines and ranks are created. - - -* **Command '/mines set area' fixed confirmation to use yes or confirm.** -Added the ability to set size when using feet. The size is what is used with the '/mines set size' command. So 20 width is really 41 since it's adding 40 blocks in all directions. - - - -* **Redesign the /mines info command to reduce and compact the listing.** -`/mines info ` is the reduced listing where disabled features are not shown. `/mines info all` is the expanded listing that includes more details. -Reworked the block list to use the String.format for spacing instead of manual adjustments. - - -* **v3.2.10-alpha.13 2021-08-20** - - -* **Fixed an issue with null for the playerUuid..** -it's rare, but it could be null. This prevents the failures. - - -* **Fixed a few issues with ranks, a NPEs.** - - -* **The text for ladder info was changed to remove player's name, which does not make sense to include, especially if ran from console.** - - -* **Yet another situation where CMI needed prison to start with a delay; confirmed setting is correct.** -It was confirmed for the second time that 'Economy_CMI' works so I moved that to the 'vault-economy-name:' setting. - - -* **Fixes a bug when checking offline players which was returning a null with rPlayer.getRank(). Was fixed.** - - -* **Ranks autoConfigure: Add to the prestiges ladder the base rank cost multiplier of 10 percent.** -Provide a few messages to document it when the /ranks autoConfigure command is ran. - - -* **For the /ranks autoConfigure command, setup an alias to /prison autoConfigure.** - - -* **Setup a task that is to be ran whenever there is a rank change within a ladder, or if the ladder has the base rank cost multiplier changed.** -This helps to ensure that the rank costs are correct for all players. - - -* **Renamed the command `/ranks remove rank` to `/ranks removeRank` since the prior command was a single command within it's own sub-group.** -This change will now list the command with the others when using `/ranks`. It was "lost" and "hidden" and admins were not able to find it that easily. - - -* **Changed the /ranks ladder delete command to prevent a ladder from being deleted if it has any ranks associated with it.** -To delete a ladder with ranks would corrupt the ranks. The ranks would have to be removed first to ensure no players are on the ranks. - - -* **After a change in a player's rank, have the player's Rank Cost Multipliers recalculated.** - - -* **The command /ranks player perms was generating an error with offline players so this fixes that issue.** - - -* **Changed config.yml to enable and disable prestige confirmations.** -Updated the GUI to support this. Settings where changed and config.yml may need to be reset when updating prison to use these new features. - - -* **Fixed bug with `/ranks ladder moveRank`.** -It was not removing the rank from the source ladder, but was also adding it to the destination ladder. This was fixed and is now working correctly. - - -* **Removed the remainder of the ladder/rank permissions that were never used.** - - -* **Start to setup MineBombs basics.** - - -* **Add to the World object, a function to set the block.** -The SpigotWorld class uses prison's compatibility functions to perform this action. - - -* **v3.2.10-alpha.12 2021-08-16** -Released alpha.12 - - -* **Updates to fix the prestige issues.** -Moved more of the processing in to the PlayerRank object to reduce issues. Shutdown one of the constructors since it could lead to the wrong amounts. -Prestige was fixed by rewriting the way the rankup handled the ranks and playerRanks. - - -* **Fixed an issue with logging when using a debug target mode.** -It was not logging when the global debug was off. - - -* **Added some rankup debug logging details.** -Enable with `/prison debug rankup`. - - -* **v3.2.10-alpha.11 2021-08-15** -Bump the version - - -* **Changed the /ranks info to show the ranks multiplier information.** - - -* **Work on /ranks list to improve the content to better present the rank cost multiplier.** - - -* **General changes to code that uses getRank() that returns a PlayerData object... ** -Since that is a player's instance of a rank, this may be null for a lot of players. A lot of the old code would not take in to consideration that there may be no value, so hence the NPEs that we've been seeing. This should address a lot of the potential issues. - - -* **Found situations where players are not on a ladder and its causing issues.** -Need to expand to other code... - - -* **Bump to v3.2.10-alpha.10f.** -Will be trying to release a more formal alpha later today. - - -* **Fixed a typo in the name of a function. Prevent a possible NPE. Revised how one of the PlayerRank constructors works so it will actually calculate the correct multiplier.** - - -* **v3.2.10-alpha.10e 2021-08-13** - - -* **More adjustments to rankups and PlayerRanks.** I think I've addressed all issues with ranks. - - -* **Remove three redundant ladder commands dealing with ranks: listranks, addrank, and delrank.** - - -* **There was a report that the mine would continue to reset after it was deleted.** -Cleaned up a few things and added a boolean field to indicate it's delete. If its set to deleted, then it will prevent the resets from happening. Just as a safety check. Not 100% sure that this was actually an issue. - - -* **Setup the AsyncPlayerChatEvent listener within Prison to be able to dynamically set the priority based upon a new setting in the config.yml file.** - - -* **Bug fixes: Fixed some issues with the use of the new PlayerRank object.** -They were not always not-null, and there were some instances of the wrong variable being used. - - -* **Fixed an issue with the regular expression block quote... didn't need the second backslash.** - - -* **Bug fix: Fixed a few issues with PlayerRank object not being set correctly everywhere.** -Was also checking the wrong object for null. These fix about 3 different NPEs. - - -* **Removal of the obsolete ranks related permissions and permission groups.** -This was a failed attempt to automate the user of permissions with ranks. This did not work, since vault does not support the creation of permission groups, plus a few other issues and limitations with vault. - - -* **Initial setup of ladder rank cost multipliers.** -All ladders a player has, will contribute to the total rank cost multiplier value, and all ranks for that player will have their cost adjusted. -Overall this will allow an increasing rank cost as players rankup on the prestige ladder, and/or it can help reduce rank costs if donor ranks provide a negative adjustment. -Currently there is no way to set the ladder's multiplier... that's next. But everything else is hooked up and should be functional. - - -* **v3.2.10-alpha.10 2021-08-11** - - -* **Added a missing ranks message: when removing a player from a rank and it fails.** - - -* **LocalManager.getLocale: Fixed an issue with player being null when the player object originated from a task processing offline players.** - - -* **Added the event level MONITOR and changed the event listeners to only register the MONITOR event when the config is set to MONITOR.** - - -* **Updates to the JumboTextFont by adding most of the lowercase characters.** - - -* **Alter the use of accessing the player to help eliminate the risk of concurrent modification events.** - - -* **Added a spigot module en_US.properties language file.** - - -* **Added a new function to the PrisonEventManager to return the list of event listeners as a string so they can be logged to the console, or through helpch.at which is not yet hooked up.** - - -* **Added JumboTextFonts to prison support submit ranks.** -Fixed a few issues and added more characters to the fonts. Added /ranks info all to the ranks output for more detailed information. - - -* **Found and fixed an obscure bug with regular expression quotes.** -It was duplicating text and making the results much larger than what they should have been. - - -* **Created a JumboTextFont to be included in the prison support submit documents.** -Hooked up to mines. This will make it easier to identify the various mines in the listings. - - -* **Add the capture and display of all support submit URLs in each additional submission.** - - -* **Expand '/prison support submit mines' details by including the '/mines info all' command.** -Had to redesign some of the mine commands to be able to capture all of those details. Added a table of contents to the submission so it's clear all these details are included, since it could be a HUGE file. - - -* **Added 6 new placeholders to provide the whole line for the prison_top_mine_block_ plus the heading and total line.** - - -* **Placeholders with _nnn_ numeric ranges: Fixes a potential problem of where it was unable to match a placeholder if placeholder escape characters were not used.** -Now it will properly identify and match the series. - - -* **Fixed a problem with block constrains, the min number of blocks, when no blocks were initially added to the mine.** -When revisiting to ensure the min amount is set, it did not have the correct values set for the ranges. -This has been fixed by adding a low and high limit field that not does record the actual block positions of this block type, but of the limits as defined by the constraints. This allows adding more blocks to reach the min amount, when no block has been added before. - - -* **Prevent the use of % in the ranks and ladder commands.** -Could not use them before, but they would cause errors when messaging details about the commands. Now the command will be rejected and it will have to be submitted correctly. - - -* **ButtonLore Utility got a couple of new methods.** - - -* **Some GUIs were still using the old deprecated buttons. This got fixed.** - - -* **All GUIs got a new common lore Format.** - - -* **All GUIs now use ButtonLore utility and lore format.** - - -* **Fixed an issue with spigot 1.17.1 where they appear to be extending the BlockBreakEvent for FurnaceExtractEvent but not isolating the listeners.** -Forced to check to ensure the event is actually a BlockBreakEvent to ensure the correct event is really being fired correctly. - - -* **Added prison's version to the chat display's title.** -is will help support since it wil help show us what version someone is using. - - -* **Added the recording of earnings per mine.** -The add earnings must be called within the time limit as defined by the session timeout for mining, which is currently 15 seconds. -If something is sold outside of that session timeout, then it will not be attributed to the mine. - - -* **Minor design changes to the main GUI /gui**: to apply them you should reset (delete it) your en_US.yml at this path -> - Prison/module_conf/lang/en_US.yml. More changes will come in the future. - - -* **ButtonLore is quite ready and already in use for the /gui main GUI, only the first page uses it.** - - -* **Started working on a new ButtonLore Utility that will be included in the SpigotGUI Utility.** - - -* **v3.2.10-alpha.9 2021-08-04** -Released... -Upgraded gradle to use v6.1.0 of Jengleman's ShadowJar... was v5.2.0. - - -* **Modify the block break events to merge most of the preliminary processing from all of the different kind of block events.** -This enables a single function to be able to handle most of the initial setup processes for all of the different block break events. This will reduce the amount of code, eliminate possible errors, and make it a lot easier to enable more events to be processed. - - -* **Add the option for using '*all*' for mine name for adding block events, which will add the event to all mines.** - - -* **All GUIs now use PrisonGUI Utility, finally it should be done now.** - - -* **2 more autofeatures GUIs now use PrisonGUI Utility.** - - -* **All SellAll GUIs now use PrisonGUI Utility.** - - -* **All Mines GUIs now use PrisonGUI Utility.** - - -* **Disabled some old Block model code in use for GUIs.** - - -* **Mines Blocks List GUI now uses PrisonGUI utility.** - - -* **Fixed Mines Blocks List GUI (the one that shows the blocks currently in the mine).** The GUI wasn't translating -correctly blocks, and showing a "barrier" instead of the block, the GUI was working anyway, just - not good looking, now it's fixed for newer versions. - - -* **Mines Reset Time GUI now uses PrisonGUI utility.** - - -* **Mines Set Notification Mode GUI now uses PrisonGUI utility.** - - -* **Mines Notification Radius GUI now uses PrisonGUI utility.** - - -* **Mines Blocks Set Percentage GUI now uses PrisonGUI utility.** - - -* **Updated Buttons PrisonGUI Utility to support enchantments.** - - -* **For the fortune calculations, converted the use of the old block model over to use XMaterial instead.** -Updated to include the newest 1.17 blocks too. - - -* **Updated smelting to use the newer 1.17 blocks, such as all of the deepslate variations, and the raw iron, raw copper, and raw gold.** -Updated all code that had these variations. - - -* **Updated the XP calculations to include the newer blocks from 1.17** - - -* **Upgrade XSeries from v8.2.0 to v8.3.0** - - -* **Remove the dump of block break events from the command /prison version all since it was appearing first.** -It will need to be rewritten to capture in a list of strings. - - -* **Added mining time by Mine.** -This will also track in which mine, players are mining. - - -* **Found a bug in the TokenEnchant event listener class.** -It was casting to the wrong class for the Monitor event. - - -* **Fixed an issue with PlayerCache and mining duration.** -Also added logging if unable to rename a temp file. - - -* **Added support for jumbo and full ladder types with the mine liners.** - - -* **Update the custom ladder type feature in mine liners.** -Now you can select none, normal, and wide. - - -* **Provide break the list of placeholders down by placeholder types, along with sub total counts.** -Also added total count at the top of the list. Breaking down the large list in to sub-types will make it easier to read the list. - - -* **Provided a way to specify a last next rank message for the placeholder:** -prison_rankup_rank_tag_default -This will only apply on the default ladder and when the next rank tag is empty. - - -* **Started to look in to providing the ability to import player ranks** based upon perms, but ran in to an issue that if the player is not online, then it can be very difficult to get their actual perms. Would not be able to get a listing of all perms, as if they were online, so it would make this less flexible. -This has been canned because the person who was needing it, is no longer needing it. May revisit in the future. - - -* **About 56 new placeholders!** SpigotPlayerUtil has been updated to provide support for all of the functionality that it needs. It's been hooked up to the placeholders so they should be functional. - - -* **Setup the Platform to be able to provide a SpigotPlayerUtil object.** -This is needed for placeholder support and a few other things. - - -* **There was a concurrent modification exception on the line with** `playerData.setDirty( false );`. -These changes will not prevent that issue, but it will trap it so it does not register in the log files. If this happens, then the player's cache will be saved on the next attempt. This should be a rare event. -The changes needed are more complex that this simple "fix" and will be made in the near future. - - -* **Prison Mines Blocks Set Percentage GUI now uses PrisonGUI Utility.** - - -* **Prison Mine Blocks List GUI now uses PrisonGUI Utility.** - - -* **Prison Blocks List GUI now uses PrisonGUI Utility.** - - -* **Fixed some errors of the Prison Mines Blocks Set Percentage GUI:** There were some ArrayOutOfBonds exceptions. - - -* **Auto Features: Added food exhaustion calculations.** -Now on each block break, Configurable to be disabled. For explosions events, only applies to the one block they actually mined. - - -* **For various add commands, the messages for the 'placeholders' was being sent to the console instead of the player issuing the command. This was an issue in game, but not the console.** - -* **Placeholders durability: add support for a percentage and bars.** -* **3 new Backpacks GUIs for admins now use PrisonGUI Utility.** - - -* **Bug fixes with the setup of token enchant event listeners.** - - -* **Added many more features to SpigotPlayerUtil and getting ready for the new placeholders.** - - -* **Started to add a PlayerUtil and SpigotPlayerUtil to prison.** -This will allow an easier access to specific player values in other parts of prison with just a single call to a util function. This will be used with a number of new placeholders. - - -* **Removal of a function from the prison Player object that is no longer being used.** - - -* **A couple of updates for CMI economy.** -Added a note on what value to try first for cmi with prison. - - -* **Changed some logging information from debug to info so it will be registered when requested by the admin.** - - -* **PrisonEnchants changed the class name of their event.** -This updates prison's code and changes the api jar file. - - -* **Created a new group within auto features for durability related items and created a new group autoManager just for the isAutoManagerEnabled to get it out of the options.general grouping since that is the main "switch" and it is getting lost in the configs.** -There was too many for the general group, and they were not being kept together, especially since we have a comment now. - - -* **Backpacks admin GUI now uses PrisonGUI Utility.** - - -* **v3.2.10-alpha.8 2021-07-25** - - -* **Auto features: Removed unused classes and cleaned up a few things. Fixed a reference to one of the deleted classes.** - - -* **Auto features events: Added an abstract class to manage the unregisterListeners in one place, to eliminate duplication of code.** - - -* **For the command /prison reload autoFeatures hooked it up to include unregistering all of the event listeners that auto features setup, then it uses the configurations to reregister them all.** - - -* **Fixes a major problem with how Zenchantments works because the plugin extends the BlockBreakEvent with their BlockShredEvent.** -It has issues.. but... this ensures that the correct event is being trapped. - - -* **Change to player cache field that was not so clear with it's name.** -It's supposed to be the config field name, but the description did not reflect that. - - -* **Fixed GuiUtility button add lore method:** The method to add a line to an already existing button got now fixed. - - -* **Adjustments to get the new event listeners working fully. Still need to hook them up to the reloading.** - - -* **Next step in rewriting how the event listeners are setup...** - - -* **Move the event listener managers in to a common package to prepare to extend them to the non-auto features event listeners.** - - -* **Rewriting how the event listeners are being registered.** -Added ability to unregister. This is working, but is only for the auto pickups. WIll need more work to hook up to the non-auto manager. - - -* **Setup the ability to log more than just the BlockBreakEvent.** -It it mow able to log details to Lists so they can be included in other output, such as support submits. - - -* **Rewrote how the event listener is registered so the priority is dynamic.** -This appears to be working well. - - -* **clean up some of the /prison version all commands to better reflect the actual details with dependencies with the settings for auto features.** -This should help better convey what the settings are doing, especially when a setting disables another setting. This should help reduce support issues. - - -* **Prestige confirming fix:** Fixing Prestige confirm by chat or GUI when possible. - - -* **v3.2.10-alpha.7 2021-07-23** - - - -* **Fixed the way some of the autofeature block settings were named.** -They had "autoBlock" when auto has nothing to do with it anymore, since those setting will be applied for normal drops too. -Fixed an issue with auto smelt and auto block where it was not using the config settings, so now it's working correctly. -Added more debugInfo messages to better understand what's going on when something is not working correctly. - - -* **Added a note on how fortune works... it's been confusing...** - - -* **Updates to the liner to allow the use of '*all*' for the mine name to apply the same pattern to all mines.** -For auto configure, ensure that the random liner applied to the mines is not remove, removeAll, or repair. - - -* **Prevent slime fun from registering if it is disabled.** - - -* **Fixed a problem with the registration of the events failed due to the parameter of ExplosiveEvent.** -Had to set it to Object to allow it to be registered when the plugin and class does not exist on the server. - - -* **Added more internal debug details.** - - -* **Mine liners: Added glowstone and also added the ability to apply a liner change, or removal, from all mines with one command by using `*all*` for the mine name.** - - -* **Add the debugInfo to more functions and a few more messages.** - - -* **Changed the debugInfo variable to a StringBuilder instead of just a String.** -This will provide a little bit of a performance improvement, plus it can then be passed in to the functions to gather more information. - - -* **A few minor adjustments to better identify the function that is running when logging the debug information on BlockBreaks.** -Tweaks to the PrisonEnchant's plugin code. Missed a few changes. - - -* **Changed some of the DebugTarget names to better reflect where in the project they are occurring.** - - -* **Bug Fix: If a message is removed, such that there is nothing left of the = character in the language properties files, it will now not throw an index out of bounds exception.** -Removal of the message was not expected and there was unable to handle that situation. - - -* **Added support for 4 new types of placeholders that uses the PlayerCache:** -Player's total block count. And player's count per mine. - - -* **Issue with using offline players with the playerCache.** -The playerCache should typically only contain active players, but in testing, like using /prison placeholders search, it may add an offline player to get placeholder data from them. -This prevents null issues with the locations, and eliminates the excessive error message when trying to use getLocation() on an offline player. - - -* **PlayerCache changes: Start to take in to consideration that a player within the cache may be offline.** -If that's the case, then prevent some calculations, and remove them from the cache. Offline players would be added to look up some stats, but then they would be safe to purge. -When checking the timerTasks, add an earnings of zero to purge past earnings. This will prevent the average earnings from staying there forever when the player stops mining. - - -* **Added a debug logging entry for XP Calculations.** -This will be able to provide detail infomation on if it's working and what the results are. - - -* **Add support for PrisonEnchants' ExplosiveEvent.** -While adding support for the ExplosiveEvent, found a few issues and fixed them. Some changes were just in names of functions, others were functional, such as improving the support of unbreakable and blocks that fall outside of a mine. - - -* **Simplified how the title, subtitle, and actionBar are setup with the /prison utils titles title command. ** - - -* **New Feature: Prison now tracks average earnings per minute.** -If you have auto sell enabled (sell upon each block break, see autoFeaturesConfig.yml) then prison will be able to report your average earnings over the last 5 minutes of mining activity. -`prison_player_balance_earnings_per_minute` prison_pb_epm -`prison_player_balance_earnings_per_minute_formatted` prison_pb_epmf - - -* **Rewrite how the player uses title, subtitle, and actionBar for the /prison utils titles command.** -Spigot 1.8 does not support any of this. -Spigot 1.8.8 is when this was introduced. But 1.8.8 does not have actionBar, so instead it shows the message in the subtitle. -Spigot 1.9+ are able to display title, subtitle, and actionBar at the same time. - - -* **Release of v3.2.10-alpha.6 - 2021-07-19** - - - -* **Try to better handle situations where integrations fail when integrating.** -Now has the ability to disable the integration and remove it when it fails. - - -* **New feature: prison utils titles.** -This enables sending messages to the player's console as either a title, a subtitle, and/or actionBar. Can also clear, reset, or set the timings on the titles. -All three can be sent through the title by using a double colon to indicate the various parts. -For example: 'Hello Title!::Subtitle is Here!::I'm on an actionBar!' - - -* **Add feature to Auto Features to prevent tools from breaking or being used when durability is equal to or greater than maxDurability.** - - -* **Added some documentation to the ExplosiveBlockBreakEvent so users can better understand how it should be used.** - - -* **This is an example of an explosive block break event that should be used so prison can monitor for it, and consume it.** - - -* **More adjustments to the Taiwanese language files.** - - -* **More tweaks to player cache file saving... ** - - -* **PlayerCache adjustments for timing tracking. A work in progress.** - - -* **Updates to he Taiwanese language files.** - - -* **Improvements to adding new players to prison upon startup.** -This process scans bukkit's offline players and finds everyone who is not already setup in prison and adds them. -It now uses the /ranks set rank command now. - - -* **Added support for zh_TW Taiwanese.** -This is just an initial setup for now. To enable it, set the language in the config.yml file to zh_TW. - - -* **Player Cache: Hooked up block tracking for players.** -Appears to be working as far as tracking blocks that are being broke. It loads and unloads when a player joins and leaves the server so only active players have their data online. Performs periodical updates on saving. -This tracks total blocks, block counts by mine, and block counts by block type. -Starting to setup time tracking. - - -* **More changes to setting up a player cache.** -The basics should be represented, with startup and shutdown of the cache, running a periodical task to refresh the data, running a periodical task to save the data. -No data is processed as of yet, but the cache should be reactive to players logging on and off the server. - - -* **Initial work on setting up the Player Cache.** - - -* **Minor SellAll utility changes.** - - -* **SellAll Player Blocks List GUI now supports pages.** - - -* **Minor improvements for GUIs to improve performance.** - - -* **PrisonGUI Buttons utility minor changes.** - - -* **Add the ability to play sounds through the /prison utils sound command.** - - -* **Update docs... scale back what we support with WorldGuard regions since access by ranks solves so many problems.** - - -* **SellAll Admin Blocks List GUI now supports pages.** Note: This was **not** part of the v3.2.10-alpha.5 release. - - -* **SpigotGUIComponents minor changes.** Note: This was **not** part of the v3.2.10-alpha.5 release. - - -* **SellAll Blocks GUI now uses PrisonGUI Utility.** Note: This was **not** part of the v3.2.10-alpha.5 release. - - - -* **v3.2.10-alpha.5 2021-07-14** - - - -* **Made the RankLadder comparable and in the RankPlayer changed the map to a TreeMap.** -This should fix the inconsistencies that I was seeing earlier. - - -* **If a player is detected to be lacking a rank on the default ladder, it will adde the default rank.** -Ran in a problem where getting the current rank for a ladder was failing when it was ran, but worked when stepped through a debugger. - - -* **When checking for players not hooked up to prison, prison now ensures there is a default rank configured or it won't try to check the players.** -This change also checks players within prison to ensure they have a rank on the default ladder. - - -* **MineInfo GUI now uses PrisonGUI Utility.** - - -* **Removed unused imports from some GUI classes.** - - -* **MineInfo GUI TP Button now has an Arrow instead of a red_bed:** red_bed can't be translated to a legacy block in 1.8.8. - - -* **Fixed performance issues for MinesInfo GUI.** - - -* **Added information to the language files on how to use utf-8 text in these properties files.** - - -* **Setup prison to ensure all compliers within gradle is using utf-8.** - - -* **Enable loading utf-8 encoding from the properties files. Java 1.8 is unable load them as utf-8, so this provides a work around.** -At this point, this ensures that if a properties file contains utf-8 encoded text, that it can be packaged in the prison jar, extracted to the file system, then loaded and used and maintain full utf-8 encoding all the way until it hits bukkit. bukkit corrupts it and confirmed it was corrupted in spigot 1.8.8, 1.3.4, and 1.16.5 so its not an isolated issue for just one spigot version. - - -* **Updated cryptomorin's XSeries to v8.2.0.** - - -* **Convert the CommandHandler.getHelpMessage() to return a ChatDisplay object to allow the use of creating clickable URLs in the help messages.** -The help messages now has headers which shows the command that's being listed. -Updated the /mines blockEvent add command to include two docURLs to use as an example; improved the help message. - - -* **If a Ladder has a bad rank that is already in another ladder, that rank will not be added to the new ladder that is being loaded.** -An error message is already being logged, but this change will update the ladder to resave it without the duplicate rank. - - -* **Clean up Ranks a little more by removing more of the rank position and report failures if a rank is already loaded in another rank to prevent internal failures if a ladder save file is corrupted by manual editing.** - - -* **Removed the use of rank.getPosition() from all saved information within ranks and ladders.** -Position is no longer used to access any rank. It is only used to compare if one rank is higher or lower than another. It's lazy loaded only when it is needed the first time. If a rank is removed from a ladder, or inserted in to a ladder other than at the end, then all ranks in the ladder are set to -1 for the position so they recalculate when they are used the next time. - - -* **This fixes a user error situation, which is not a bug, in the listing of ranks.** -The user copied the contents of one ladder to another ladder, without deleting the source ladder. Thus there were two instances of a series of ranks, when there should ever be only one instance of a rank. A rank can be in at most one ladder, or no ladder. -The result of this issue is that when the second ladder was hookedup at prison's startup, it corrupted the ranks in the first ladder. -This works around such problems by changing /ranks list by using the list of ranks within the ladder, instead of using the rank's prior and next associations. -These changes also add the rankId to both the '/ranks list' and '/ranks ladder rankList' commands, and also '-' and '+' notations to indicate a rank is linked to a prior and next rank. - - -* **Simplify the command /mines blockEvent add by removing the permissions and taskMode from the add.** -This was causing too muchh confusion for a lot of people. It should help to keep the add much more basic. There have been alternative commands to modify those settings so it really isn't important to set them on the add. Also odds are they will not anything but the default values for these two fields. The defaults are perms = none and taskMode = sync. TaskMode is not defaulting to inline due to increased risk of lag and prison being falsely blamed for it. If desired, the admin can always change the taskMode to what they need. - - -* **Bug fix: Fixed an issue where the "on click" events were using the wrong row number.** -The row number was getting incremented at the wrong time. - - -* **v3.2.10-alpha.4 2021-07-10 ** - - -* **Few minor tweaks to the mines info command with formatting.** - - -* **Added player counts to the rank list command.** - - -* **Hooked up the /ranks list all command to the /prison support submit ranks command.** - - -* **Add option to /ranks list to include all ranks through the use of the "all" in place of the ladder name.** - - -* **Fixed a bug where getting a player was returning a null.** -When that null was encountered, it was not processing the placeholders, especially for the bars. -Not really sure why it was failing, but replaced the use of getting the player balance with the most recent use of RankPlayer's getBalance() works perfectly. - - -* **More adjustments on the /ranks list to prepare for listing all ladders.** -Also added a couple of more messages. - - -* **Added an error message if there is a failure when using /prison support submit.** -I assumed that other error messages would exist, but having doubts if it always will have other errors displayed. - - -* **Improvements to the /ranks list command.** -Enhanced the header so it's clear which ladder is involved. Also cleaned up the formatting with the tag colors so it does not impact the column alignments. Also doing a little more with injecting the "default" tag so it does not shift the columns. - - -* **Adds the listing of all mines to the /prison support submit mines command.** -This provides an overview of all mines and is included at the top of the listing. - - -* **Improve the layout of all of the mines with the command /mines list all.** - - -* **pasteChat update to keep the color codes.** It will only keep the color codes that start with &, and all others will be removed. - - -* **New feature: /prison reload locales. Its now possible to reload the language files that prison uses.** -Added a new debug item to test to see if utf-8 is working: /prison debug testLocale. No, it does not work with utf-8 text yet. -I did confirm that if the properties files are setup with UTF-8 and are a part of the prion jar, that the UTF-8 encoding will properly be saved to the local file system. -The area that I think is causing failures is with the Properties object itself since that is not utf-8 compatible, so it appears. - - -* **v3.2.10-alpha.3 2021-07-09** - - -* **reformat the /mines list command to mak it easier to read** - - -* **Added support for prison support submit for ranks and ladders, and also for mines.** -These two new commands will submit the raw json files. - - -* **New Feature!! Major support feature! Send all of prison's configs to paste.helpch.at so we can know exactly how servers are configured.** -This logs the following config files: config.yml plugin.yml autoFeaturesConfig.yml modules.yml module_conf/mines/config.json - SellAllConfig.yml GuiConfig.yml backpacks/backpacksconfig.yml - - -* **Added a success message when a player is added to prison's default rank.** - - -* **Fixed issue with a few placeholders that were not working.** -Was using the wrong translator so a number of mine related placeholders stopped working. -The mineplayers were not working too. The bug was introduced by hooking up STATSMINES. - - -* **Hooked up STATSRANKS placeholders and got rid of obsolete ones. Still more testing needed.** - - -* **Added a player check on prison startup that will add all offline players that are not hooked up to prison yet. Plus it will register name changes too.** - - -* **Added top rank balance placeholders: 6 for now and more will be added soon once these are fully working.** -These are based upon the player's balance within the rank. -Also added a Hesitancy Delay Penalty to help encourage players to rankup instead of trying to dominate a single rank. -These have not yet been tested. - - -* **Added RankPlayers to Ranks.** -This will allow quicker access to all players at each rank, which will help for top ranking reporting. - - -* **Clean up some rank and ladder function to eliminate the use of magic numbers: both rank ids and ladder ids.** -These were bad, since the objects were already linked together, so using these functions were just adding unneeded overhead. - - -* **v3.2.10-alpha.2 2021-07-06** - - -* **Added the ability to fail silently for the Localizable object to prevent the message ID from flooding certain messages.** -This will be employed in the Output.get() functions so if it cannot load the prefixes and level colors, then the message IDs will not be injected in to the messages. -This new feature should never be used without careful consideration since it is important to identify when messages fail so they can be fixed properly. - - -* **Adjustments to LocaleManager for updating the internal checks for if the external files need to be updated.** -Also finalize how Prison object works with the LocaleManager. - - -* **Removed obsolete placeholders that are not used anymore.** - - -* **Adjustments to when the LocalManager is started so it can be activated as soon as possible.** -This is because of the need for Output.get() to use externalized messages for it's prefixes and color codes. This does present some problems, but it actually works fine at runtime and also for junit tests too. - - -* **Setup a getConfigString in the Platform with a default value.** - - -* **New placeholders for mine block stats: Renamed percent to chance. Added prison_top_mine_block_remaining_bar_nnn_minename.** - - -* **Used the wrong numeric formatter... needed to be an integer.** - - -* **Added 10 new placeholders to provide stats on mine blocks.** -These use a series value in the placeholder to specify the specific block. The series number is not limited and can range from 1 through a large reasonable value. The number can be one or more digits, with or without a left padding zeros. - - -* **Renamed the field PrisonBlockStatusData.getResetBlockCount() to getBlockPlacedCount() to be more descriptive of what it actually is.** - - -* **Add the ability of a PlaceholderFlag to self identify as having a sequence.** -This will allow for automatic processing of these kind of placeholders without having to hard code for them. - - -* **Placeholders test: Fixed issue with player name being incorrect and also added player information if it is provided in the output.** - - -* **Fixed a typo that was made a long time ago. Placeholder has a capitol H in the name.** - - -* **Increased the number of rows displayed when using the placeholder search. It was showing six placeholders and I increased it to 10.** - - -* **Renamed the PlaceHolderFlags from PLAYERMINES to MINEPLAYERS which is more consistent in how it is being used.** - - -* **v3.2.10-alpha.1 2021-07-05** - - -* **Bug fix... when selling on each block break event, it needs to suppress the per-sale messages.** - - -* **Fix a few other issues with the new placeholders.** - - -* **Enhance the /ranks autoConfigure to work much better with existing mines and ranks when doing a force.** - - -* **New 18 new placeholders added to prison. Hooked up the following placeholders, but have not yet ran through testing yet.** -prison_rank_ladder_position (prison_rlp), prison_rank_ladder_position_laddername (prison_rlp_laddername), -prison_rank__ladder_position_rankname (prison_r_lp_rankname), prison_rank__player_cost_rankname (prison_r_pcst_rankname), -prison_rank__player_cost_formatted_rankname (prison_r_pcf_rankname), prison_rank__player_cost_remaining_rankname (prison_r_pcf_rankname), -prison_rank__player_cost_remaining_formatted_rankname (prison_r_pcf_rankname), prison_rank__player_cost_percent_rankname (prison_r_pcp_rankname), -prison_rank__player_cost_bar_rankname (prison_r_pcb_rankname) - - -* **Refactored ranks and RankLadders to eliminate old and inefficient ways to get the ranks and next ranks.** -These change will help improve the performance of processing the placeholders. -This also allows the elimination of a few functions that are now obsolete. +# v3.2.10 2021-08-22 # v3.2.9 2021-07-03 diff --git a/docs/prison_changelog_v3.2.10.md b/docs/prison_changelog_v3.2.10.md index 78c3d6290..699fa0041 100644 --- a/docs/prison_changelog_v3.2.10.md +++ b/docs/prison_changelog_v3.2.10.md @@ -32,7 +32,9 @@ These build logs represent the work that has been going on within prison. * Provide a more robust support system in prison, in addition to the support submit features. Can now enable more debug mode targets to better trackdown potential issues. -* Prison now supports reloadable locales and auto features. For the auto features, it also reregisters the block break events listeners that auto features use. +* Prison now supports reloadable locales and auto features. For the auto features, it now unregisters all previously registered block event listeners, and the re-registers them based upon the updates to the settings in the reloaded auto features. The server no longer needs to be restarted if the configuration settings for event listeners have changed in any way. + +* Auto features has undergone more refactoring to prepare for future enhancements, and to streamline the existing processes. A few undiscovered bugs were found and fixed during these enhancements. As a result, auto features works better with other enchantment plugins. * Rewrote some of the auto features to resolve some obscure issues, and to provide performance improvements and greater flexibility. @@ -43,7 +45,7 @@ These build logs represent the work that has been going on within prison. * Update many of the internal libraries. -* Rewrites of the GUIs and Sellall features. +* Performance improvements with GUIs, backpack, and Sellall features. Includes fixs and some layout functional improvements too. * Expand Prison's utils features. Added a few more utilities. diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java index 7d260aaf7..0aa844cb2 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java @@ -90,6 +90,7 @@ import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerBlockBreakEvents; import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerCrazyEnchants; import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerPrisonEnchants; +import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerPrisonsExplosiveBlockBreakEvents; import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerTokenEnchant; import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerZenchantments; import tech.mcprison.prison.spigot.block.OnBlockBreakEventListener.BlockBreakPriority; @@ -2038,12 +2039,15 @@ public String dumpEventListenersBlockBreakEvents() { sb.append( "\n" ); - AutoManagerCrazyEnchants crazyEnchants = new AutoManagerCrazyEnchants(); - crazyEnchants.dumpEventListeners( sb ); - AutoManagerPrisonEnchants prisonEnchants = new AutoManagerPrisonEnchants(); prisonEnchants.dumpEventListeners( sb ); + AutoManagerPrisonsExplosiveBlockBreakEvents prisonExplosiveEnchants = new AutoManagerPrisonsExplosiveBlockBreakEvents(); + prisonExplosiveEnchants.dumpEventListeners( sb ); + + AutoManagerCrazyEnchants crazyEnchants = new AutoManagerCrazyEnchants(); + crazyEnchants.dumpEventListeners( sb ); + AutoManagerTokenEnchant tokenEnchant = new AutoManagerTokenEnchant(); tokenEnchant.dumpEventListeners( sb ); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/ExplosiveBlockBreakEvent.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/ExplosiveBlockBreakEvent.java index 493030918..b2543ff78 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/ExplosiveBlockBreakEvent.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/ExplosiveBlockBreakEvent.java @@ -50,15 +50,16 @@ public class ExplosiveBlockBreakEvent private String triggeredBy; + public ExplosiveBlockBreakEvent( Block theBlock, Player player, - List explodedBlocks, String triggeredBy ) { + List explodedBlocks, String triggeredBy ) { super( theBlock, player ); this.explodedBlocks = explodedBlocks; this.triggeredBy = triggeredBy; } public ExplosiveBlockBreakEvent( Block theBlock, Player player, - List explodedBlocks ) { + List explodedBlocks ) { this( theBlock, player, explodedBlocks, null ); } public ExplosiveBlockBreakEvent( Block theBlock, Player player ) { @@ -107,7 +108,8 @@ public void setTriggeredBy( String triggeredBy ) { public HandlerList getHandlers(){ return handlers; } - public static HandlerList getHandlersList(){ + + public static HandlerList getHandlerList(){ return handlers; } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerBlockBreakEvents.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerBlockBreakEvents.java index a0e901f1d..0c7588e98 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerBlockBreakEvents.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerBlockBreakEvents.java @@ -28,13 +28,25 @@ public AutoManagerBlockBreakEvents() { } - + /** + *

When a listener is registered within prison's auto manager, the events + * are tracked internally and can be unregistered later. This function does not + * make it obvious the instantiated object is "stored", but it is. + *

+ * + *

For more info on the storage of these registered events, please see: + *

+ * + *
SpigotPrison.getRegisteredBlockListeners()
+ * + */ @Override public void registerEvents() { - initialize(); + // Prison's own internal event and listener: + new AutoManagerPrisonsExplosiveBlockBreakEvents().registerEvents(); new AutoManagerCrazyEnchants().registerEvents(); new AutoManagerPrisonEnchants().registerEvents(); From 96529799ec5ce3b8b3229d0b518d9b4b2d0b7cd5 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Tue, 24 Aug 2021 18:12:30 -0400 Subject: [PATCH 005/283] Fixed the way some of the language files were being generated so it can include the spigot module, which makes it self-contained for actual Modules, since it's always based upon the module name. Core and spigot are not technially modules, so they have special setups. Changed the Module folder from dataFolder to moduleDataFolder so it would not conflict with the SpigotPrison object. --- docs/changelog_v3.3.x.md | 7 +++ .../java/tech/mcprison/prison/Prison.java | 23 ++++++++- .../mcprison/prison/error/ErrorManager.java | 2 +- .../prison/localization/LocaleManager.java | 4 +- .../tech/mcprison/prison/modules/Module.java | 13 ++--- .../mcprison/prison/modules/PluginEntity.java | 2 +- .../mcprison/prison/mines/PrisonMines.java | 2 +- .../mcprison/prison/spigot/SpigotPrison.java | 51 ++++++++++++++++++- 8 files changed, 91 insertions(+), 13 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 0e11438c3..d42cb256c 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -15,6 +15,13 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-08-24 + +* **Fixed the way some of the language files were being generated** +so it can include the spigot module, which makes it self-contained for actual Modules, since it's always based upon the module name. +Core and spigot are not technically modules, so they have special setups. +Changed the Module folder from dataFolder to moduleDataFolder so it would not conflict with the SpigotPrison object. + + * **Fixed a problem with Prison's ExplosiveBlockBreakHandler** in that it has a typo in the getHandlerList() and was not included with the registration processes. It also needed to be included with the generation of the listener dumps. diff --git a/prison-core/src/main/java/tech/mcprison/prison/Prison.java b/prison-core/src/main/java/tech/mcprison/prison/Prison.java index bbf1b9ae8..2c47766ff 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/Prison.java +++ b/prison-core/src/main/java/tech/mcprison/prison/Prison.java @@ -88,7 +88,10 @@ public class Prison private CommandHandler commandHandler; private SelectionManager selectionManager; private EventBus eventBus; + private LocaleManager localeManager; + private File moduleDataFolder; + // private ItemManager itemManager; private ErrorManager errorManager; private TroubleshootManager troubleshootManager; @@ -135,11 +138,27 @@ public static Prison get() { public LocaleManager getLocaleManager() { if ( this.localeManager == null ) { + this.localeManager = new LocaleManager(this, "lang/core"); } return localeManager; } + /** + * Returns this module's data folder, where all data can be stored. + * It is located in the Prison data folder, and has the name of the module. + * It is automatically generated. + * + * @return The {@link File} representing the data folder. + */ + public File getModuleDataFolder() { + + if ( moduleDataFolder == null ) { + this.moduleDataFolder = Module.setupModuleDataFolder( "core" ); + } + return moduleDataFolder; + } + /** * Initializes prison-core. In the implementations, this should be called when the plugin is * enabled. After this is called, every getter in this class will return a value. @@ -503,7 +522,7 @@ public void setStorageSize( long storageSize ) { private boolean initDataFolder() { // Creates the /Prison directory, for core configuration. this.dataFolder = getPlatform().getPluginDirectory(); - return this.dataFolder.exists() || this.dataFolder.mkdir(); + return this.dataFolder.exists() || this.dataFolder.mkdirs(); } private boolean initMetaDatabase() { @@ -634,6 +653,8 @@ public File getDataFolder() { return dataFolder; } + + /** diff --git a/prison-core/src/main/java/tech/mcprison/prison/error/ErrorManager.java b/prison-core/src/main/java/tech/mcprison/prison/error/ErrorManager.java index f6185730c..cca993416 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/error/ErrorManager.java +++ b/prison-core/src/main/java/tech/mcprison/prison/error/ErrorManager.java @@ -31,7 +31,7 @@ public class ErrorManager { public ErrorManager(PluginEntity owner) { this.owner = owner; - this.errorDir = new File(owner.getDataFolder(), "errors"); + this.errorDir = new File(owner.getModuleDataFolder(), "errors"); if (!this.errorDir.exists()) { this.errorDir.mkdir(); } diff --git a/prison-core/src/main/java/tech/mcprison/prison/localization/LocaleManager.java b/prison-core/src/main/java/tech/mcprison/prison/localization/LocaleManager.java index 644889ef4..4ec090789 100755 --- a/prison-core/src/main/java/tech/mcprison/prison/localization/LocaleManager.java +++ b/prison-core/src/main/java/tech/mcprison/prison/localization/LocaleManager.java @@ -189,7 +189,7 @@ public String toString() { public File getLocalDataFolder() { // Setup the local folders: - File dataFolder = fixPrisonCoreLanguagePath( getOwningPlugin().getDataFolder() ); + File dataFolder = fixPrisonCoreLanguagePath( getOwningPlugin().getModuleDataFolder() ); File localeDirectory = new File(dataFolder, LOCALE_FOLDER); // if the folder does not exist, try to create it: @@ -497,7 +497,7 @@ private void loadCustomLocales() { private File fixPrisonCoreLanguagePath( File targetPath ) { if ( !targetPath.getAbsolutePath().startsWith( ModuleManager.getModuleRootDefault().getAbsolutePath() ) ) { - targetPath = Module.setupDataFolder( Prison.PSEDUO_MODLE_NAME ); + targetPath = Module.setupModuleDataFolder( Prison.PSEDUO_MODLE_NAME ); } return targetPath; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/modules/Module.java b/prison-core/src/main/java/tech/mcprison/prison/modules/Module.java index 4c95f0cab..65a982a9e 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/modules/Module.java +++ b/prison-core/src/main/java/tech/mcprison/prison/modules/Module.java @@ -37,7 +37,8 @@ public abstract class Module implements PluginEntity { */ private String name, version; - private File dataFolder; + private File moduleDataFolder; + private int apiTarget; private ModuleStatus status; private ErrorManager errorManager; @@ -58,18 +59,18 @@ public Module(String name, String version, int target) { this.version = version; this.apiTarget = target; - this.dataFolder = setupDataFolder( name ); + this.moduleDataFolder = setupModuleDataFolder( name ); this.status = new ModuleStatus(); this.errorManager = new ErrorManager(this); } - public static File setupDataFolder( String name ) { + public static File setupModuleDataFolder( String name ) { File dataFolder = new File(ModuleManager.getModuleRootDefault(), name.toLowerCase().replace(" ", "_")); if (!dataFolder.exists()) { - dataFolder.mkdir(); + dataFolder.mkdirs(); } return dataFolder; } @@ -185,8 +186,8 @@ public ModuleStatus getStatus() { * * @return The {@link File} representing the data folder. */ - public File getDataFolder() { - return dataFolder; + public File getModuleDataFolder() { + return moduleDataFolder; } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/modules/PluginEntity.java b/prison-core/src/main/java/tech/mcprison/prison/modules/PluginEntity.java index 03b3da3f6..6e64f95ff 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/modules/PluginEntity.java +++ b/prison-core/src/main/java/tech/mcprison/prison/modules/PluginEntity.java @@ -30,6 +30,6 @@ public interface PluginEntity { String getName(); - File getDataFolder(); + File getModuleDataFolder(); } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/PrisonMines.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/PrisonMines.java index 3111f2930..4146ca9b7 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/PrisonMines.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/PrisonMines.java @@ -178,7 +178,7 @@ private void initDb() { private void initConfig() { config = new MinesConfig(); - File configFile = new File(getDataFolder(), "config.json"); + File configFile = new File(getModuleDataFolder(), "config.json"); if (!configFile.exists()) { getJsonFileIO().saveJsonFile( configFile, config ); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPrison.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPrison.java index f90091301..1fc10086e 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPrison.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPrison.java @@ -48,11 +48,13 @@ import tech.mcprison.prison.alerts.Alerts; import tech.mcprison.prison.integration.Integration; import tech.mcprison.prison.internal.block.PrisonBlockTypes; +import tech.mcprison.prison.localization.LocaleManager; import tech.mcprison.prison.mines.PrisonMines; import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.mines.managers.MineManager; import tech.mcprison.prison.modules.Module; import tech.mcprison.prison.modules.ModuleElementType; +import tech.mcprison.prison.modules.PluginEntity; import tech.mcprison.prison.output.ChatDisplay; import tech.mcprison.prison.output.LogLevel; import tech.mcprison.prison.output.Output; @@ -99,7 +101,9 @@ * @author Faizaan A. Datoo * @author GABRYCA */ -public class SpigotPrison extends JavaPlugin { +public class SpigotPrison + extends JavaPlugin + implements PluginEntity { private static SpigotPrison config; @@ -126,6 +130,9 @@ public class SpigotPrison extends JavaPlugin { private static boolean isSellAllEnabled = false; + private LocaleManager localeManager; + private File moduleDataFolder; + private List registeredBlockListeners; public static SpigotPrison getInstance(){ @@ -138,6 +145,7 @@ public SpigotPrison() { config = this; this.registeredBlockListeners = new ArrayList<>(); + } @Override @@ -197,6 +205,9 @@ public void onEnable() { .init(new SpigotPlatform(this), Bukkit.getVersion()); + // Enable the spigot locale manager: + getLocaleManager(); + this.compatibility = SpigotCompatibility.getInstance(); // initCompatibility(); Obsolete... @@ -328,6 +339,44 @@ public void onDisable() { Prison.get().deinit(); } + + + + /** + * Lazy load LocalManager which ensures Prison is already loaded so + * can get the default language to use from the plugin configs. + * + * Returns the {@link LocaleManager} for the plugin. This contains the global messages that Prison + * uses to run its command library, and the like. {@link Module}s have their own {@link + * LocaleManager}s, so that each module can have independent localization. + * + * @return The global locale manager instance. + */ + public LocaleManager getLocaleManager() { + + if ( this.localeManager == null ) { + + this.localeManager = new LocaleManager(this, "lang/spigot"); + } + return localeManager; + } + + /** + * Returns this module's data folder, where all data can be stored. + * It is located in the Prison data folder, and has the name of the module. + * It is automatically generated. + * + * @return The {@link File} representing the data folder. + */ + public File getModuleDataFolder() { + + if ( moduleDataFolder == null ) { + this.moduleDataFolder = Module.setupModuleDataFolder( "spigot" ); + } + return moduleDataFolder; + } + + public FileConfiguration getGuiConfig() { if (guiConfig == null) { guiConfig = new GuiConfig(); From 89ddae0f62219705eb9f75dcbf5d5888b0aaaa16 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Tue, 24 Aug 2021 18:48:30 -0400 Subject: [PATCH 006/283] Transitioning over to the correct way to get the compatibility object. Just a few classes are using the old way, but they will be switched over when they are done with the edits. --- docs/changelog_v3.3.x.md | 4 ++++ .../mcprison/prison/spigot/SpigotListener.java | 10 +++------- .../mcprison/prison/spigot/SpigotPlatform.java | 3 ++- .../tech/mcprison/prison/spigot/SpigotUtil.java | 7 ++++--- .../spigot/autofeatures/AutoManagerFeatures.java | 9 +++++---- .../spigot/backpacks/BackpacksListeners.java | 3 ++- .../prison/spigot/backpacks/BackpacksUtil.java | 3 ++- .../mcprison/prison/spigot/block/SpigotBlock.java | 14 +++++++------- .../prison/spigot/block/SpigotItemStack.java | 4 ++-- .../mcprison/prison/spigot/game/SpigotPlayer.java | 10 +++++----- .../prison/spigot/game/SpigotPlayerUtil.java | 12 ++++++------ .../prison/spigot/gui/ListenersPrisonManager.java | 3 ++- .../spigot/inventory/SpigotPlayerInventory.java | 10 +++++----- .../spigot/slime/SlimeBlockFunEventListener.java | 3 ++- .../prison/spigot/utils/PrisonUtilsRepair.java | 4 ++-- 15 files changed, 53 insertions(+), 46 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index d42cb256c..54829082d 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-08-24 +* **Transitioning over to the correct way to get the compatibility object.** +Just a few classes are using the old way, but they will be switched over when they are done with the edits. + + * **Fixed the way some of the language files were being generated** so it can include the spigot module, which makes it self-contained for actual Modules, since it's always based upon the module name. Core and spigot are not technically modules, so they have special setups. diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotListener.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotListener.java index 2436295f4..3f421a655 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotListener.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotListener.java @@ -42,19 +42,15 @@ import org.bukkit.plugin.PluginManager; import tech.mcprison.prison.Prison; -import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; import tech.mcprison.prison.internal.events.Cancelable; import tech.mcprison.prison.internal.events.player.PlayerChatEvent; import tech.mcprison.prison.internal.events.player.PlayerPickUpItemEvent; import tech.mcprison.prison.internal.events.player.PlayerSuffocationEvent; import tech.mcprison.prison.internal.events.world.PrisonWorldLoadEvent; import tech.mcprison.prison.output.Output; -import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerBlockBreakEvents.AutoManagerBlockBreakEventListener; -import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerBlockBreakEvents.OnBlockBreakEventListenerNormal; -import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerBlockBreakEvents.OnBlockBreakEventListenerNormalMonitor; -import tech.mcprison.prison.spigot.block.OnBlockBreakEventListener; import tech.mcprison.prison.spigot.block.OnBlockBreakEventListener.BlockBreakPriority; import tech.mcprison.prison.spigot.compat.Compatibility; +import tech.mcprison.prison.spigot.compat.SpigotCompatibility; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.game.SpigotWorld; import tech.mcprison.prison.util.BlockType; @@ -226,7 +222,7 @@ public void onPlayerInteract(PlayerInteractEvent e) { // This one's a workaround for the double-interact event glitch. // The wand can only be used in the main hand - if ( SpigotPrison.getInstance().getCompatibility().getHand(e) != + if ( SpigotCompatibility.getInstance().getHand(e) != Compatibility.EquipmentSlot.HAND) { return; } @@ -236,7 +232,7 @@ public void onPlayerInteract(PlayerInteractEvent e) { new tech.mcprison.prison.internal.events.player.PlayerInteractEvent( new SpigotPlayer(e.getPlayer()), SpigotUtil.bukkitItemStackToPrison( - SpigotPrison.getInstance().getCompatibility().getItemInMainHand(e)), + SpigotCompatibility.getInstance().getItemInMainHand(e)), tech.mcprison.prison.internal.events.player.PlayerInteractEvent.Action .valueOf(e.getAction().name()), new Location(new SpigotWorld(block.getWorld()), block.getX(), block.getY(), diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java index 0aa844cb2..c720f5478 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java @@ -95,6 +95,7 @@ import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerZenchantments; import tech.mcprison.prison.spigot.block.OnBlockBreakEventListener.BlockBreakPriority; import tech.mcprison.prison.spigot.commands.PrisonSpigotSellAllCommands; +import tech.mcprison.prison.spigot.compat.SpigotCompatibility; import tech.mcprison.prison.spigot.game.SpigotCommandSender; import tech.mcprison.prison.spigot.game.SpigotHandlerList; import tech.mcprison.prison.spigot.game.SpigotOfflinePlayer; @@ -539,7 +540,7 @@ public void toggleDoor(Location doorLocation) { // state.setData((MaterialData) openable); // state.update(); - SpigotPrison.getInstance().getCompatibility() + SpigotCompatibility.getInstance() .playIronDoorSound(block.getLocation()); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotUtil.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotUtil.java index 81293545d..c93b150fe 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotUtil.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotUtil.java @@ -49,6 +49,7 @@ import tech.mcprison.prison.spigot.block.SpigotBlock; import tech.mcprison.prison.spigot.block.SpigotItemStack; import tech.mcprison.prison.spigot.compat.BlockTestStats; +import tech.mcprison.prison.spigot.compat.SpigotCompatibility; import tech.mcprison.prison.spigot.game.SpigotWorld; import tech.mcprison.prison.spigot.integrations.IntegrationMinepacksPlugin; import tech.mcprison.prison.util.BlockType; @@ -90,7 +91,7 @@ public static XMaterial getXMaterial( String materialName ) { */ public static XMaterial getXMaterial( BlockType prisonBlockType ) { - XMaterial xMat = SpigotPrison.getInstance().getCompatibility() + XMaterial xMat = SpigotCompatibility.getInstance() .getXMaterial( prisonBlockType ); return xMat; @@ -112,7 +113,7 @@ public static Material getMaterial( BlockType prisonBlockType ) { public static BlockType blockToBlockType( Block spigotBlock ) { - BlockType results = SpigotPrison.getInstance().getCompatibility() + BlockType results = SpigotCompatibility.getInstance() .getBlockType( spigotBlock ); // @@ -809,7 +810,7 @@ else if ( !xMat.isSupported() ) { } // Next test all of the spigot/bukkit Materials: - BlockTestStats stats = SpigotPrison.getInstance().getCompatibility() + BlockTestStats stats = SpigotCompatibility.getInstance() .testCountAllBlockTypes(); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java index 6a913240f..ca5a1b462 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java @@ -38,6 +38,7 @@ import tech.mcprison.prison.spigot.block.SpigotBlock; import tech.mcprison.prison.spigot.block.SpigotItemStack; import tech.mcprison.prison.spigot.commands.PrisonSpigotSellAllCommands; +import tech.mcprison.prison.spigot.compat.SpigotCompatibility; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.spiget.BluesSpigetSemVerComparator; import tech.mcprison.prison.util.BlockType; @@ -187,7 +188,7 @@ private boolean processAutoEvents( SpigotBlock spigotBlock, Player player, Mine // mine.getRemainingBlockCount() + " [" + block.toString() + "]" // ); - SpigotItemStack itemInHand = SpigotPrison.getInstance().getCompatibility().getPrisonItemInMainHand( player ); + SpigotItemStack itemInHand = SpigotCompatibility.getInstance().getPrisonItemInMainHand( player ); int count = applyAutoEvents( player, spigotBlock, mine, debugInfo ); @@ -211,7 +212,7 @@ private boolean processAutoEvents( SpigotBlock spigotBlock, Player player, Mine private int applyAutoEvents( Player player, SpigotBlock block, Mine mine, StringBuilder debugInfo ) { int count = 0; - SpigotItemStack itemInHand = SpigotPrison.getInstance().getCompatibility().getPrisonItemInMainHand( player ); + SpigotItemStack itemInHand = SpigotCompatibility.getInstance().getPrisonItemInMainHand( player ); boolean isLoreEnabled = isBoolean( AutoFeatures.isLoreEnabled ); @@ -368,7 +369,7 @@ private boolean applyAutoEvents( Player player, Mine mine, int totalCount = 0; - SpigotItemStack itemInHand = SpigotPrison.getInstance().getCompatibility() + SpigotItemStack itemInHand = SpigotCompatibility.getInstance() .getPrisonItemInMainHand( player ); debugInfo.append( "(applyAutoEvents multi-blocks: " + explodedBlocks.size() ); @@ -919,7 +920,7 @@ private void displayActionBarMessage(Player player, String message) { protected double doesItemHaveAutoFeatureLore( ItemLoreEnablers loreEnabler, Player player ) { double results = 0.0; - ItemStack itemInHand = SpigotPrison.getInstance().getCompatibility().getItemInMainHand( player ); + ItemStack itemInHand = SpigotCompatibility.getInstance().getItemInMainHand( player ); if ( itemInHand != null && itemInHand.getType() != Material.AIR && itemInHand.getItemMeta() != null ) { // (itemInHand.hasItemMeta()) { NOTE: hasItemMeta() always returns nulls diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/BackpacksListeners.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/BackpacksListeners.java index 727759784..38ead4741 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/BackpacksListeners.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/BackpacksListeners.java @@ -14,10 +14,11 @@ import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.SpigotUtil; import tech.mcprison.prison.spigot.compat.Compatibility; +import tech.mcprison.prison.spigot.compat.SpigotCompatibility; public class BackpacksListeners implements Listener { - Compatibility compat = SpigotPrison.getInstance().getCompatibility(); + Compatibility compat = SpigotCompatibility.getInstance(); @EventHandler public void onPlayerJoinBackpack(PlayerJoinEvent e){ diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/BackpacksUtil.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/BackpacksUtil.java index 156d9e3dc..c436bcf7c 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/BackpacksUtil.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/BackpacksUtil.java @@ -25,6 +25,7 @@ import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.SpigotUtil; import tech.mcprison.prison.spigot.compat.Compatibility; +import tech.mcprison.prison.spigot.compat.SpigotCompatibility; import tech.mcprison.prison.spigot.configs.BackpacksConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; @@ -40,7 +41,7 @@ public class BackpacksUtil { private FileConfiguration backpacksDataConfig = YamlConfiguration.loadConfiguration(backpacksFile); public static List openBackpacks = new ArrayList<>(); public static List backpackEdited = new ArrayList<>(); - private final Compatibility compat = SpigotPrison.getInstance().getCompatibility(); + private final Compatibility compat = SpigotCompatibility.getInstance(); private final int backpackDefaultSize = Integer.parseInt(backpacksConfig.getString("Options.BackPack_Default_Size")); /** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java index 339924aac..9ed810a9a 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java @@ -34,8 +34,8 @@ import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.internal.block.PrisonBlock.PrisonBlockType; import tech.mcprison.prison.output.Output; -import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.SpigotUtil; +import tech.mcprison.prison.spigot.compat.SpigotCompatibility; import tech.mcprison.prison.util.BlockType; import tech.mcprison.prison.util.Location; @@ -88,7 +88,7 @@ public String getBlockName() { } @Override public BlockType getType() { - return SpigotPrison.getInstance().getCompatibility().getBlockType( getWrapper() ); + return SpigotCompatibility.getInstance().getBlockType( getWrapper() ); // return SpigotUtil.materialToBlockType(bBlock.getType()); } @@ -110,7 +110,7 @@ public PrisonBlock getPrisonBlock() { } if ( results == null ) { - results = SpigotPrison.getInstance().getCompatibility().getPrisonBlock( getWrapper() ); + results = SpigotCompatibility.getInstance().getPrisonBlock( getWrapper() ); } if ( results.getLocation() == null && getLocation() != null ) { @@ -171,8 +171,8 @@ public void setPrisonBlock( PrisonBlock prisonBlock ) { { case minecraft: { - SpigotPrison.getInstance().getCompatibility(). - updateSpigotBlock( prisonBlock, getWrapper() ); + SpigotCompatibility.getInstance(). + updateSpigotBlock( prisonBlock, getWrapper() ); } @@ -203,7 +203,7 @@ public void setPrisonBlock( PrisonBlock prisonBlock ) { public void setBlockFace( BlockFace blockFace ) { - SpigotPrison.getInstance().getCompatibility() + SpigotCompatibility.getInstance() .setBlockFace( getWrapper(), blockFace ); } /** @@ -215,7 +215,7 @@ public void setBlockFace( BlockFace blockFace ) { @Override public void setType(BlockType blockType) { - SpigotPrison.getInstance().getCompatibility() + SpigotCompatibility.getInstance() .updateSpigotBlock( blockType, getWrapper() ); // if ( type != null && type != BlockType.IGNORE ) { diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotItemStack.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotItemStack.java index 54c02ce85..eece37be3 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotItemStack.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotItemStack.java @@ -11,7 +11,7 @@ import tech.mcprison.prison.Prison; import tech.mcprison.prison.internal.ItemStack; -import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.compat.SpigotCompatibility; import tech.mcprison.prison.util.BlockType; public class SpigotItemStack @@ -44,7 +44,7 @@ public SpigotItemStack( org.bukkit.inventory.ItemStack bukkitStack ) { // in the bukkitStack: int amount = bukkitStack.getAmount(); - BlockType type = SpigotPrison.getInstance().getCompatibility() + BlockType type = SpigotCompatibility.getInstance() .getBlockType( bukkitStack ); // BlockType type = materialToBlockType(bukkitStack.getType()); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayer.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayer.java index 73e62b68c..c46d9bbbb 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayer.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayer.java @@ -34,9 +34,9 @@ import tech.mcprison.prison.internal.inventory.Inventory; import tech.mcprison.prison.internal.scoreboard.Scoreboard; import tech.mcprison.prison.output.Output; -import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.SpigotUtil; import tech.mcprison.prison.spigot.block.SpigotBlock; +import tech.mcprison.prison.spigot.compat.SpigotCompatibility; import tech.mcprison.prison.spigot.compat.SpigotNMSPlayer; import tech.mcprison.prison.spigot.inventory.SpigotPlayerInventory; import tech.mcprison.prison.spigot.scoreboard.SpigotScoreboard; @@ -494,14 +494,14 @@ public double getMaxHealth() { double maxHealth = 0; if ( getWrapper() != null ) { - maxHealth = SpigotPrison.getInstance().getCompatibility() + maxHealth = SpigotCompatibility.getInstance() .getMaxHealth( getWrapper() ); } return maxHealth; } public void setMaxHealth( double maxHealth ) { if ( getWrapper() != null ) { - SpigotPrison.getInstance().getCompatibility() + SpigotCompatibility.getInstance() .setMaxHealth( getWrapper(), maxHealth ); } } @@ -605,7 +605,7 @@ public double getWalkSpeed() { @Override public void setTitle( String title, String subtitle, int fadeIn, int stay, int fadeOut ) { if ( getWrapper() != null) { - SpigotPrison.getInstance().getCompatibility() + SpigotCompatibility.getInstance() .sendTitle( getWrapper(), title, subtitle, fadeIn, stay, fadeOut ); } } @@ -613,7 +613,7 @@ public void setTitle( String title, String subtitle, int fadeIn, int stay, int f @Override public void setActionBar( String actionBar ) { if ( getWrapper() != null) { - SpigotPrison.getInstance().getCompatibility() + SpigotCompatibility.getInstance() .sendActionBar( getWrapper(), actionBar ); } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayerUtil.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayerUtil.java index fd9952514..8bdd8cf68 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayerUtil.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayerUtil.java @@ -7,9 +7,9 @@ import tech.mcprison.prison.Prison; import tech.mcprison.prison.internal.ItemStack; import tech.mcprison.prison.internal.PlayerUtil; -import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.block.SpigotItemStack; import tech.mcprison.prison.spigot.compat.Compatibility; +import tech.mcprison.prison.spigot.compat.SpigotCompatibility; public class SpigotPlayerUtil extends PlayerUtil @@ -167,7 +167,7 @@ public SpigotItemStack getItemInHand() { SpigotItemStack itemInHand = null; if ( isActive() && spigotPlayer.getWrapper() != null ) { - itemInHand = SpigotPrison.getInstance().getCompatibility() + itemInHand = SpigotCompatibility.getInstance() .getPrisonItemInMainHand( spigotPlayer.getWrapper() ); } return itemInHand; @@ -273,7 +273,7 @@ public int getItemInHandDurabilityUsed() { SpigotItemStack itemStack = getItemInHand(); if ( itemStack != null ) { - Compatibility compat = SpigotPrison.getInstance().getCompatibility(); + Compatibility compat = SpigotCompatibility.getInstance(); results = compat.getDurability( itemStack ); } @@ -287,7 +287,7 @@ public int getItemInHandDurabilityMax() { SpigotItemStack itemStack = getItemInHand(); if ( itemStack != null ) { - Compatibility compat = SpigotPrison.getInstance().getCompatibility(); + Compatibility compat = SpigotCompatibility.getInstance(); results = compat.getDurabilityMax( itemStack ); } @@ -301,7 +301,7 @@ public int getItemInHandDurabilityRemaining() { SpigotItemStack itemStack = getItemInHand(); if ( itemStack != null ) { - Compatibility compat = SpigotPrison.getInstance().getCompatibility(); + Compatibility compat = SpigotCompatibility.getInstance(); int durabilityUsed = compat.getDurability( itemStack ); int durabilityMax = compat.getDurabilityMax( itemStack ); results = durabilityMax - durabilityUsed; @@ -317,7 +317,7 @@ public double getItemInHandDurabilityPercent() { SpigotItemStack itemStack = getItemInHand(); if ( itemStack != null ) { - Compatibility compat = SpigotPrison.getInstance().getCompatibility(); + Compatibility compat = SpigotCompatibility.getInstance(); int durabilityUsed = compat.getDurability( itemStack ); int durabilityMax = compat.getDurabilityMax( itemStack ); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java index 867df1576..b255c6acb 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java @@ -44,6 +44,7 @@ import tech.mcprison.prison.spigot.backpacks.BackpacksUtil; import tech.mcprison.prison.spigot.commands.PrisonSpigotSellAllCommands; import tech.mcprison.prison.spigot.compat.Compatibility; +import tech.mcprison.prison.spigot.compat.SpigotCompatibility; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.autofeatures.SpigotAutoBlockGUI; import tech.mcprison.prison.spigot.gui.autofeatures.SpigotAutoFeaturesGUI; @@ -388,7 +389,7 @@ public void onClick(InventoryClickEvent e){ // GUIs must have the good conditions to work. if (guiConditions(e, p)) return; - Compatibility compat = SpigotPrison.getInstance().getCompatibility(); + Compatibility compat = SpigotCompatibility.getInstance(); String buttonNameMain; String[] parts; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/inventory/SpigotPlayerInventory.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/inventory/SpigotPlayerInventory.java index 1392dd121..840eab86b 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/inventory/SpigotPlayerInventory.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/inventory/SpigotPlayerInventory.java @@ -24,9 +24,9 @@ import tech.mcprison.prison.internal.ItemStack; import tech.mcprison.prison.internal.inventory.PlayerInventory; -import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.SpigotUtil; import tech.mcprison.prison.spigot.block.SpigotItemStack; +import tech.mcprison.prison.spigot.compat.SpigotCompatibility; /** * Created by DMP9 on 04/02/2017. @@ -102,7 +102,7 @@ public SpigotPlayerInventory(org.bukkit.inventory.PlayerInventory wrapper) { @Override public ItemStack getItemInLeftHand() { return SpigotUtil.bukkitItemStackToPrison( - SpigotPrison.getInstance().getCompatibility().getItemInOffHand( + SpigotCompatibility.getInstance().getItemInOffHand( ((org.bukkit.inventory.PlayerInventory) getWrapper()) ) ); @@ -114,7 +114,7 @@ public SpigotPlayerInventory(org.bukkit.inventory.PlayerInventory wrapper) { if ( stack instanceof SpigotItemStack ) { - SpigotPrison.getInstance().getCompatibility() + SpigotCompatibility.getInstance() .setItemStackInOffHand( this, ((SpigotItemStack) stack) ); } } @@ -123,7 +123,7 @@ public SpigotPlayerInventory(org.bukkit.inventory.PlayerInventory wrapper) { return SpigotUtil.bukkitItemStackToPrison( - SpigotPrison.getInstance().getCompatibility().getItemInMainHand( + SpigotCompatibility.getInstance().getItemInMainHand( ((org.bukkit.inventory.PlayerInventory) getWrapper()) )); } @@ -131,7 +131,7 @@ public SpigotPlayerInventory(org.bukkit.inventory.PlayerInventory wrapper) { if ( stack instanceof SpigotItemStack ) { - SpigotPrison.getInstance().getCompatibility() + SpigotCompatibility.getInstance() .setItemStackInMainHand( this, ((SpigotItemStack) stack) ); } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/slime/SlimeBlockFunEventListener.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/slime/SlimeBlockFunEventListener.java index 2ab8f14aa..d90b0dd46 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/slime/SlimeBlockFunEventListener.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/slime/SlimeBlockFunEventListener.java @@ -17,6 +17,7 @@ import org.bukkit.util.Vector; import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.compat.SpigotCompatibility; public class SlimeBlockFunEventListener implements Listener { @@ -81,7 +82,7 @@ else if ( velY > 0.2 ) { // || onBlock2.getType() == Material.SLIME_BLOCK ) { - ItemStack itemInHand = SpigotPrison.getInstance().getCompatibility().getItemInMainHand( player ); + ItemStack itemInHand = SpigotCompatibility.getInstance().getItemInMainHand( player ); double boost = getBoost( itemInHand ); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsRepair.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsRepair.java index ceaa8811a..270630590 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsRepair.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsRepair.java @@ -11,9 +11,9 @@ import tech.mcprison.prison.internal.CommandSender; import tech.mcprison.prison.internal.ItemStack; import tech.mcprison.prison.output.Output; -import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.block.SpigotItemStack; import tech.mcprison.prison.spigot.compat.Compatibility; +import tech.mcprison.prison.spigot.compat.SpigotCompatibility; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.inventory.SpigotPlayerInventory; @@ -257,7 +257,7 @@ private boolean repairItem( SpigotItemStack item, { boolean results = false; - Compatibility compat = SpigotPrison.getInstance().getCompatibility(); + Compatibility compat = SpigotCompatibility.getInstance(); if ( item != null && !item.isBlock() && !item.isAir() ) { From b255182fe18f9f8e2e78fd65e6b69bfad8c7d83c Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Tue, 24 Aug 2021 18:51:28 -0400 Subject: [PATCH 007/283] Setting up a new way to handle block updates in prison. Adding functions that are intended to be use while running in an async threads. --- .../spigot/compat/CompatibilityBlocks.java | 17 ++++- .../spigot/compat/CompatibilityCache.java | 10 +++ .../prison/spigot/compat/Spigot113Blocks.java | 51 +++++++++++++++ .../prison/spigot/compat/Spigot18Blocks.java | 62 +++++++++++++++++++ 4 files changed, 137 insertions(+), 3 deletions(-) diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/CompatibilityBlocks.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/CompatibilityBlocks.java index 1e52c4660..e83697e73 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/CompatibilityBlocks.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/CompatibilityBlocks.java @@ -23,15 +23,26 @@ public interface CompatibilityBlocks public XMaterial getXMaterial( BlockType blockType ); - public void updateSpigotBlock( BlockType blockType, Block spigotBlock ); + public BlockType getBlockType( ItemStack spigotStack ); - public void updateSpigotBlock( PrisonBlock prisonBlock, Block spigotBlock ); - public BlockType getBlockType( ItemStack spigotStack ); + + public void updateSpigotBlock( BlockType blockType, Block spigotBlock ); + + public void updateSpigotBlock( PrisonBlock prisonBlock, Block spigotBlock ); public void updateSpigotBlock( XMaterial xMat, Block spigotBlock ); + + public void updateSpigotBlockAsync( BlockType blockType, Block spigotBlock ); + + public void updateSpigotBlockAsync( PrisonBlock prisonBlock, Block spigotBlock ); + + public void updateSpigotBlockAsync( XMaterial xMat, Block spigotBlock ); + + + public BlockTestStats testCountAllBlockTypes(); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/CompatibilityCache.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/CompatibilityCache.java index fc10cebc5..76973803a 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/CompatibilityCache.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/CompatibilityCache.java @@ -9,6 +9,7 @@ import com.cryptomorin.xseries.XMaterial; import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.util.BlockType; /** @@ -30,6 +31,9 @@ public class CompatibilityCache { private Map xMaterialCache; + private final SpigotPrison plugin; + + public CompatibilityCache() { super(); @@ -37,6 +41,8 @@ public CompatibilityCache() { this.xMaterialCache = new TreeMap<>(); initializeForcedCache(); + + this.plugin = SpigotPrison.getInstance(); } /** @@ -144,5 +150,9 @@ public void putCachedXMaterial( BlockType blockType, byte data, XMaterial xMat ) xMaterialCache.put( key, xMat == null ? NULL_TOKEN : xMat ); } } + + public SpigotPrison getPlugin() { + return plugin; + } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113Blocks.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113Blocks.java index dec668754..f1428a125 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113Blocks.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113Blocks.java @@ -7,6 +7,7 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.Damageable; import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.scheduler.BukkitRunnable; import com.cryptomorin.xseries.XMaterial; @@ -210,6 +211,56 @@ public void updateSpigotBlock( XMaterial xMat, Block spigotBlock ) { } } + + @Override + public void updateSpigotBlockAsync( BlockType blockType, Block spigotBlock ) { + + if ( blockType != null && blockType != BlockType.IGNORE && spigotBlock != null ) { + + XMaterial xMat = getXMaterial( blockType ); + + updateSpigotBlockAsync( xMat, spigotBlock ); + } + } + + + @Override + public void updateSpigotBlockAsync( PrisonBlock prisonBlock, Block spigotBlock ) { + + if ( prisonBlock != null && + !prisonBlock.getBlockName().equalsIgnoreCase( InternalBlockTypes.IGNORE.name() ) && + spigotBlock != null ) { + + XMaterial xMat = getXMaterial( prisonBlock ); + + if ( xMat != null ) { + + updateSpigotBlockAsync( xMat, spigotBlock ); + } + } + } + + + @Override + public void updateSpigotBlockAsync( XMaterial xMat, Block spigotBlock ) { + + if ( xMat != null ) { + Material newType = xMat.parseMaterial(); + if ( newType != null ) { + + new BukkitRunnable() { + @Override + public void run() { + + // No physics update: + spigotBlock.setType( newType, false ); + } + }.runTaskLater( getPlugin(), 0 ); + + } + } + } + /** *

This function is supposed to find all possible blocks available * on the server. The number of available items, and blocks, will vary based diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18Blocks.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18Blocks.java index 0d5d9b90f..85c56c939 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18Blocks.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18Blocks.java @@ -4,6 +4,7 @@ import org.bukkit.block.Block; import org.bukkit.block.BlockState; import org.bukkit.inventory.ItemStack; +import org.bukkit.scheduler.BukkitRunnable; import com.cryptomorin.xseries.XMaterial; @@ -403,6 +404,67 @@ public void updateSpigotBlock( XMaterial xMat, Block spigotBlock ) { } + + + @Override + public void updateSpigotBlockAsync( BlockType blockType, Block spigotBlock ) { + + if ( blockType != null && blockType != BlockType.IGNORE && spigotBlock != null ) { + + XMaterial xMat = getXMaterial( blockType ); + + if ( xMat != null ) { + + updateSpigotBlockAsync( xMat, spigotBlock ); + } + } + } + + + @Override + public void updateSpigotBlockAsync( PrisonBlock prisonBlock, Block spigotBlock ) { + + if ( prisonBlock != null && + !prisonBlock.equals( PrisonBlock.IGNORE ) && + spigotBlock != null ) { + + XMaterial xMat = getXMaterial( prisonBlock ); + + if ( xMat != null ) { + + updateSpigotBlockAsync( xMat, spigotBlock ); + } + } + } + + + @SuppressWarnings( "deprecation" ) + @Override + public void updateSpigotBlockAsync( XMaterial xMat, Block spigotBlock ) { + + if ( xMat != null ) { + Material newType = xMat.parseMaterial(); + if ( newType != null ) { + + new BukkitRunnable() { + @Override + public void run() { + + BlockState bState = spigotBlock.getState(); + + // Set the block state with the new type and rawData: + bState.setType( newType ); + bState.setRawData( xMat.getData() ); + + // Force the update but don't apply the physics: + bState.update( true, false ); + } + }.runTaskLater( getPlugin(), 0 ); + + } + } + } + /** *

This function is supposed to find all possible blocks available From f8b9cc1e985055461300e0253cab3f2d851a70f0 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Tue, 24 Aug 2021 18:51:52 -0400 Subject: [PATCH 008/283] Transitioning over to the correct way to get the compatibility object. Just a few classes are using the old way, but they will be switched over when they are done with the edits. --- .../prison/spigot/block/OnBlockBreakEventCore.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index d6cf03fba..b73fad016 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -37,6 +37,7 @@ import tech.mcprison.prison.spigot.api.PrisonMinesBlockBreakEvent; import tech.mcprison.prison.spigot.autofeatures.AutoManagerFeatures; import tech.mcprison.prison.spigot.compat.Compatibility; +import tech.mcprison.prison.spigot.compat.SpigotCompatibility; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.integrations.IntegrationCrazyEnchantmentsPickaxes; import tech.mcprison.prison.spigot.utils.BlockUtils; @@ -1577,7 +1578,7 @@ public boolean doAction( SpigotBlock spigotBlock, Mine mine, Player player, Stri boolean cancel = false; debugInfo.append( "(doAction: starting EventCore) " ); - SpigotItemStack itemInHand = SpigotPrison.getInstance().getCompatibility().getPrisonItemInMainHand( player ); + SpigotItemStack itemInHand = SpigotCompatibility.getInstance().getPrisonItemInMainHand( player ); AutoManagerFeatures aMan = SpigotPrison.getInstance().getAutoFeatures(); @@ -1632,7 +1633,7 @@ public boolean doAction( Mine mine, Player player, List explodedBlo int totalCount = 0; - SpigotItemStack itemInHand = SpigotPrison.getInstance().getCompatibility().getPrisonItemInMainHand( player ); + SpigotItemStack itemInHand = SpigotCompatibility.getInstance().getPrisonItemInMainHand( player ); AutoManagerFeatures aMan = SpigotPrison.getInstance().getAutoFeatures(); @@ -2038,12 +2039,12 @@ private boolean isToolDisabled( Player player ) { if ( isBoolean( AutoFeatures.isPreventToolBreakage ) ) { SpigotItemStack itemInHand = - SpigotPrison.getInstance().getCompatibility().getPrisonItemInMainHand( player ); + SpigotCompatibility.getInstance().getPrisonItemInMainHand( player ); if ( itemInHand != null && !itemInHand.isAir() ) { int breakageThreshold = getInteger( AutoFeatures.preventToolBreakageThreshold ); - Compatibility compat = SpigotPrison.getInstance().getCompatibility(); + Compatibility compat = SpigotCompatibility.getInstance(); int maxDurability = compat.getDurabilityMax( itemInHand ); int durability = compat.getDurability( itemInHand ); @@ -2096,7 +2097,7 @@ protected void calculateAndApplyDurability(Player player, SpigotItemStack itemIn if ( itemInHand != null && !itemInHand.isAir() ) { - Compatibility compat = SpigotPrison.getInstance().getCompatibility(); + Compatibility compat = SpigotCompatibility.getInstance(); int maxDurability = compat.getDurabilityMax( itemInHand ); int durability = compat.getDurability( itemInHand ); From a291e295178d37d3e293c7a23c8040d58efae64b Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Tue, 24 Aug 2021 20:18:59 -0400 Subject: [PATCH 009/283] Tweaks to the event listener dumps for block breaks. Updated the notes about prison's listeners. PEExplosionEvent was setup with the wrong forClass name. --- docs/changelog_v3.3.x.md | 8 +++++ .../prison/spigot/SpigotPlatform.java | 6 +++- .../events/AutoManagerBlockBreakEvents.java | 1 + .../events/AutoManagerCrazyEnchants.java | 1 + .../events/AutoManagerPrisonEnchants.java | 29 ++++++++++--------- ...nagerPrisonsExplosiveBlockBreakEvents.java | 1 + .../events/AutoManagerTokenEnchant.java | 1 + .../events/AutoManagerZenchantments.java | 3 ++ 8 files changed, 35 insertions(+), 15 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 54829082d..347e77c3d 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,14 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-08-24 +* **Tweaks to the event listener dumps for block breaks.** +Updated the notes about prison's listeners. +PEExplosionEvent was setup with the wrong forClass name. + + +* **Setting up a new way to handle block updates in prison. Adding functions that are intended to be use while running in an async threads.** + + * **Transitioning over to the correct way to get the compatibility object.** Just a few classes are using the old way, but they will be switched over when they are done with the edits. diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java index c720f5478..7931cfac8 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java @@ -2032,7 +2032,9 @@ public String dumpEventListenersBlockBreakEvents() { sb.append( "&2. . Prison Internal BlockBreakEvents: " + "tech.mcprison.prison.spigot.SpigotListener\n" ); sb.append( "&2. . Auto Feature Core: Non-AutoManager: " + - "OnBlockBreakEventListeners$OnBlockBreakEventListener*\n" ); + "AutoManagerBlockBreakEvents$OnBlockBreakEventListenerNormal\n" ); + sb.append( "&2. . Auto Feature Core: AutoManager: " + + "AutoManagerBlockBreakEvents$AutoManagerBlockBreakEventListener\n" ); sb.append( "&2. . Prison MONITOR Events manages block counts, " + "Mine Sweeper, and zero block conditions.\n" ); sb.append( "&2. . AutoManager and enchantment event listeners are " + @@ -2040,9 +2042,11 @@ public String dumpEventListenersBlockBreakEvents() { sb.append( "\n" ); + // Pulsi_'s plugin: AutoManagerPrisonEnchants prisonEnchants = new AutoManagerPrisonEnchants(); prisonEnchants.dumpEventListeners( sb ); + // Prison's Explosion event. Used by mine bombs. AutoManagerPrisonsExplosiveBlockBreakEvents prisonExplosiveEnchants = new AutoManagerPrisonsExplosiveBlockBreakEvents(); prisonExplosiveEnchants.dumpEventListeners( sb ); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerBlockBreakEvents.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerBlockBreakEvents.java index 0c7588e98..6cfe0e235 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerBlockBreakEvents.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerBlockBreakEvents.java @@ -219,6 +219,7 @@ public void dumpEventListeners( StringBuilder sb ) { if ( eventDisplay != null ) { sb.append( eventDisplay.toStringBuilder() ); + sb.append( "\n" ); } } catch ( Exception e ) { diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerCrazyEnchants.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerCrazyEnchants.java index 720d6663c..2b988874d 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerCrazyEnchants.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerCrazyEnchants.java @@ -207,6 +207,7 @@ public void dumpEventListeners( StringBuilder sb ) { if ( eventDisplay != null ) { sb.append( eventDisplay.toStringBuilder() ); + sb.append( "\n" ); } } catch ( ClassNotFoundException e ) { diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonEnchants.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonEnchants.java index 39a3e6172..2a4704c6b 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonEnchants.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonEnchants.java @@ -34,7 +34,7 @@ public void registerEvents() { } - public class AutoManagerExplosiveEventListener + public class AutoManagerPEExplosiveEventListener extends AutoManagerBlockBreakEvents implements Listener { @@ -47,7 +47,7 @@ public void onPrisonEnchantsExplosiveEvent(PEExplosionEvent e) { } } - public class OnBlockBreakExplosiveEventListener + public class OnBlockBreakPEExplosiveEventListener extends OnBlockBreakEventListener implements Listener { @@ -57,7 +57,7 @@ public void onPrisonEnchantsExplosiveEvent(PEExplosionEvent e) { } } - public class OnBlockBreakExplosiveEventListenerMonitor + public class OnBlockBreakPEExplosiveEventListenerMonitor extends OnBlockBreakEventListener implements Listener { @@ -79,7 +79,7 @@ public void initialize() { try { Output.get().logInfo( "AutoManager: checking if loaded: PrisonEnchants" ); - Class.forName( "me.pulsi_.prisonenchants.enchantments.custom.explosive.PEExplosionEvent", false, + Class.forName( "me.pulsi_.prisonenchants.events.PEExplosionEvent", false, this.getClass().getClassLoader() ); Output.get().logInfo( "AutoManager: Trying to register PrisonEnchants" ); @@ -93,8 +93,8 @@ public void initialize() { EventPriority ePriority = EventPriority.valueOf( eventPriority.name().toUpperCase() ); - OnBlockBreakExplosiveEventListenerMonitor normalListenerMonitor = - new OnBlockBreakExplosiveEventListenerMonitor(); + OnBlockBreakPEExplosiveEventListenerMonitor normalListenerMonitor = + new OnBlockBreakPEExplosiveEventListenerMonitor(); SpigotPrison prison = SpigotPrison.getInstance(); @@ -106,13 +106,13 @@ public void initialize() { if ( isBoolean( AutoFeatures.isAutoFeaturesEnabled )) { - AutoManagerExplosiveEventListener autoManagerlListener = - new AutoManagerExplosiveEventListener(); + AutoManagerPEExplosiveEventListener autoManagerlListener = + new AutoManagerPEExplosiveEventListener(); pm.registerEvent(PEExplosionEvent.class, autoManagerlListener, ePriority, new EventExecutor() { public void execute(Listener l, Event e) { - ((AutoManagerExplosiveEventListener)l) + ((AutoManagerPEExplosiveEventListener)l) .onPrisonEnchantsExplosiveEvent((PEExplosionEvent)e); } }, @@ -120,13 +120,13 @@ public void execute(Listener l, Event e) { prison.getRegisteredBlockListeners().add( autoManagerlListener ); } - OnBlockBreakExplosiveEventListener normalListener = - new OnBlockBreakExplosiveEventListener(); + OnBlockBreakPEExplosiveEventListener normalListener = + new OnBlockBreakPEExplosiveEventListener(); pm.registerEvent(PEExplosionEvent.class, normalListener, ePriority, new EventExecutor() { public void execute(Listener l, Event e) { - ((OnBlockBreakExplosiveEventListener)l) + ((OnBlockBreakPEExplosiveEventListener)l) .onPrisonEnchantsExplosiveEvent((PEExplosionEvent)e); } }, @@ -137,7 +137,7 @@ public void execute(Listener l, Event e) { pm.registerEvent(PEExplosionEvent.class, normalListenerMonitor, EventPriority.MONITOR, new EventExecutor() { public void execute(Listener l, Event e) { - ((OnBlockBreakExplosiveEventListenerMonitor)l) + ((OnBlockBreakPEExplosiveEventListenerMonitor)l) .onPrisonEnchantsExplosiveEvent((PEExplosionEvent)e); } }, @@ -196,7 +196,7 @@ public void dumpEventListeners( StringBuilder sb ) { // Check to see if the class ExplosiveEvent even exists: try { - Class.forName( "me.pulsi_.prisonenchants.enchantments.custom.explosive.PEExplosionEvent", false, + Class.forName( "me.pulsi_.prisonenchants.events.PEExplosionEvent", false, this.getClass().getClassLoader() ); @@ -206,6 +206,7 @@ public void dumpEventListeners( StringBuilder sb ) { if ( eventDisplay != null ) { sb.append( eventDisplay.toStringBuilder() ); + sb.append( "\n" ); } } catch ( ClassNotFoundException e ) { diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonsExplosiveBlockBreakEvents.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonsExplosiveBlockBreakEvents.java index 3b1d4de72..e6b8026d0 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonsExplosiveBlockBreakEvents.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonsExplosiveBlockBreakEvents.java @@ -194,6 +194,7 @@ public void dumpEventListeners( StringBuilder sb ) { if ( eventDisplay != null ) { sb.append( eventDisplay.toStringBuilder() ); + sb.append( "\n" ); } } catch ( Exception e ) { diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerTokenEnchant.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerTokenEnchant.java index 608278a2e..4f07af864 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerTokenEnchant.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerTokenEnchant.java @@ -201,6 +201,7 @@ public void dumpEventListeners( StringBuilder sb ) { if ( eventDisplay != null ) { sb.append( eventDisplay.toStringBuilder() ); + sb.append( "\n" ); } } catch ( ClassNotFoundException e ) { diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerZenchantments.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerZenchantments.java index 1eb311a92..99ac0bb91 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerZenchantments.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerZenchantments.java @@ -214,6 +214,9 @@ public void dumpEventListeners( StringBuilder sb ) { if ( eventDisplay != null ) { sb.append( eventDisplay.toStringBuilder() ); + sb.append( "NOTE: Zenchantments uses the same HandlerList as BlockBreakEvent so " + + "listeners are combined due to this bug.\n" ); + sb.append( "\n" ); } } catch ( ClassNotFoundException e ) { From 0883c686e9012f90d4c241533f2ea720425f64ac Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Wed, 25 Aug 2021 01:54:04 -0400 Subject: [PATCH 010/283] Setup up the basics for async updates. In the code that does the update, it also now reads the block to ensure that the read and update is all done in the synch thread. Otherwise the old code would be risking chunk loading in an async thread. Using the Location and World to perform the async updates outside of needing access to the spigot module. --- docs/changelog_v3.3.x.md | 8 +- .../tech/mcprison/prison/internal/World.java | 14 ++- .../tech/mcprison/prison/util/Location.java | 5 + .../java/tech/mcprison/prison/TestWorld.java | 4 + .../mines/features/MineTargetBlockKey.java | 7 ++ .../mines/features/MineTargetPrisonBlock.java | 24 +++- .../prison/spigot/block/SpigotBlock.java | 6 +- .../spigot/compat/CompatibilityBlocks.java | 13 +- .../prison/spigot/compat/Spigot113Blocks.java | 100 ++++++++++----- .../prison/spigot/compat/Spigot18Blocks.java | 115 +++++++++++++----- .../prison/spigot/game/SpigotWorld.java | 21 ++++ 11 files changed, 239 insertions(+), 78 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 347e77c3d..4d4f3f74a 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,13 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.1 2021-08-24 +# 3.2.11-alpha.1 2021-08-25 + + +* **Setup up the basics for async updates.** +In the code that does the update, it also now reads the block to ensure that the read and update is all done in the synch thread. Otherwise the old code would be risking chunk loading in an async thread. +Using the Location and World to perform the async updates outside of needing access to the spigot module. +At this time, only `/mines set tracer` is using the new async reset. * **Tweaks to the event listener dumps for block breaks.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/World.java b/prison-core/src/main/java/tech/mcprison/prison/internal/World.java index 8f1b87117..d09226841 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/World.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/World.java @@ -37,7 +37,7 @@ public interface World { */ String getName(); - /**O + /** * Returns a list of all the players in this world. */ List getPlayers(); @@ -53,4 +53,16 @@ public interface World { public void setBlock( PrisonBlock block, int x, int y, int z ); + + /** + *

This function should be called from an async task, and it will + * drop down in to the synchronous thread to first get the block + * from the world, then it will change to the specified PrisonBlock type. + *

+ * + * @param prisonBlock + * @param location + */ + void setBlockAsync( PrisonBlock prisonBlock, Location location ); + } diff --git a/prison-core/src/main/java/tech/mcprison/prison/util/Location.java b/prison-core/src/main/java/tech/mcprison/prison/util/Location.java index 0eecfb64f..e098c825e 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/util/Location.java +++ b/prison-core/src/main/java/tech/mcprison/prison/util/Location.java @@ -21,6 +21,7 @@ import tech.mcprison.prison.Prison; import tech.mcprison.prison.internal.World; import tech.mcprison.prison.internal.block.Block; +import tech.mcprison.prison.internal.block.PrisonBlock; /** * Represents a location in a Minecraft world. @@ -136,6 +137,10 @@ public int getBlockZ() { public Block getBlockAt() { return world.getBlockAt(this); } + + public void setBlockAsync( PrisonBlock prisonBlock ) { + world.setBlockAsync( prisonBlock, this ); + } @Override public boolean equals(Object o) { if (this == o) { diff --git a/prison-core/src/test/java/tech/mcprison/prison/TestWorld.java b/prison-core/src/test/java/tech/mcprison/prison/TestWorld.java index a95546a19..b5e3a3651 100644 --- a/prison-core/src/test/java/tech/mcprison/prison/TestWorld.java +++ b/prison-core/src/test/java/tech/mcprison/prison/TestWorld.java @@ -52,4 +52,8 @@ public TestWorld(String name) { @Override public void setBlock( PrisonBlock block, int x, int y, int z ) { } + + @Override + public void setBlockAsync( PrisonBlock prisonBlock, Location location ) { + } } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTargetBlockKey.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTargetBlockKey.java index 9c8ce944c..28577dfff 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTargetBlockKey.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTargetBlockKey.java @@ -23,6 +23,13 @@ public MineTargetBlockKey( Location location ) { this( location.getWorld(), location.getBlockX(), location.getBlockY(), location.getBlockZ() ); } + + public Location getLocation() { + Location location = new Location( world, x, y, z ); + return location; + } + + @Override public String toString() { StringBuilder sb = new StringBuilder(); diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTargetPrisonBlock.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTargetPrisonBlock.java index 190ca4ee6..2afea0b8d 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTargetPrisonBlock.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTargetPrisonBlock.java @@ -2,6 +2,7 @@ import tech.mcprison.prison.internal.World; import tech.mcprison.prison.internal.block.PrisonBlockStatusData; +import tech.mcprison.prison.util.Location; public class MineTargetPrisonBlock implements Comparable @@ -11,21 +12,25 @@ public class MineTargetPrisonBlock private PrisonBlockStatusData prisonBlock; private boolean airBroke; + private boolean isEdge; - protected MineTargetPrisonBlock( World world, int x, int y, int z ) { + protected MineTargetPrisonBlock( World world, int x, int y, int z, boolean isEdge ) { this.blockKey = new MineTargetBlockKey( world, x, y, z ); } - public MineTargetPrisonBlock( PrisonBlockStatusData prisonBlock, World world, int x, int y, int z ) { - this( world, x, y, z ); + public MineTargetPrisonBlock( PrisonBlockStatusData prisonBlock, World world, + int x, int y, int z, boolean isEdge ) { + this( world, x, y, z, isEdge ); this.prisonBlock = prisonBlock; if ( prisonBlock == null || prisonBlock.isAir() ) { this.airBroke = true; } + + this.isEdge = isEdge; } @Override @@ -63,10 +68,21 @@ public boolean isAirBroke() { public void setAirBroke( boolean airBroke ) { this.airBroke = airBroke; } - + public boolean isEdge() { + return isEdge; + } + public void setEdge( boolean isEdge ) { + this.isEdge = isEdge; + } + @Override public int compareTo( MineTargetPrisonBlock block ) { return block.getBlockKey().compareTo( block.getBlockKey() ); } + + public Location getLocation() + { + return getBlockKey().getLocation(); + } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java index 9ed810a9a..8820bf778 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java @@ -170,11 +170,9 @@ public void setPrisonBlock( PrisonBlock prisonBlock ) { switch ( prisonBlock.getBlockType() ) { case minecraft: - { - SpigotCompatibility.getInstance(). - updateSpigotBlock( prisonBlock, getWrapper() ); - } + SpigotCompatibility.getInstance(). + updateSpigotBlock( prisonBlock, getWrapper() ); break; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/CompatibilityBlocks.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/CompatibilityBlocks.java index e83697e73..17393edfa 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/CompatibilityBlocks.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/CompatibilityBlocks.java @@ -9,6 +9,7 @@ import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.spigot.block.SpigotItemStack; import tech.mcprison.prison.util.BlockType; +import tech.mcprison.prison.util.Location; public interface CompatibilityBlocks extends CompatibilityPlayer { @@ -33,13 +34,15 @@ public interface CompatibilityBlocks public void updateSpigotBlock( XMaterial xMat, Block spigotBlock ); + + public void updateSpigotBlockAsync( PrisonBlock prisonBlock, Location location ); - public void updateSpigotBlockAsync( BlockType blockType, Block spigotBlock ); - - public void updateSpigotBlockAsync( PrisonBlock prisonBlock, Block spigotBlock ); - - public void updateSpigotBlockAsync( XMaterial xMat, Block spigotBlock ); +// public void updateSpigotBlockAsync( BlockType blockType, Block spigotBlock ); +// +// public void updateSpigotBlockAsync( PrisonBlock prisonBlock, Block spigotBlock ); +// +// public void updateSpigotBlockAsync( XMaterial xMat, Block spigotBlock ); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113Blocks.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113Blocks.java index f1428a125..768bdbf9c 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113Blocks.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113Blocks.java @@ -15,8 +15,10 @@ import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.internal.block.PrisonBlockTypes.InternalBlockTypes; import tech.mcprison.prison.output.Output; +import tech.mcprison.prison.spigot.block.SpigotBlock; import tech.mcprison.prison.spigot.block.SpigotItemStack; import tech.mcprison.prison.util.BlockType; +import tech.mcprison.prison.util.Location; public abstract class Spigot113Blocks extends Spigot110Player @@ -212,55 +214,91 @@ public void updateSpigotBlock( XMaterial xMat, Block spigotBlock ) { } - @Override - public void updateSpigotBlockAsync( BlockType blockType, Block spigotBlock ) { - - if ( blockType != null && blockType != BlockType.IGNORE && spigotBlock != null ) { - - XMaterial xMat = getXMaterial( blockType ); - - updateSpigotBlockAsync( xMat, spigotBlock ); - } - } - +// @Override +// public void updateSpigotBlockAsync( BlockType blockType, Block spigotBlock ) { +// +// if ( blockType != null && blockType != BlockType.IGNORE && spigotBlock != null ) { +// +// XMaterial xMat = getXMaterial( blockType ); +// +// updateSpigotBlockAsync( xMat, spigotBlock ); +// } +// } +// +// +// @Override +// public void updateSpigotBlockAsync( PrisonBlock prisonBlock, Block spigotBlock ) { +// +// if ( prisonBlock != null && +// !prisonBlock.getBlockName().equalsIgnoreCase( InternalBlockTypes.IGNORE.name() ) && +// spigotBlock != null ) { +// +// XMaterial xMat = getXMaterial( prisonBlock ); +// +// if ( xMat != null ) { +// +// updateSpigotBlockAsync( xMat, spigotBlock ); +// } +// } +// } +// +// +// @Override +// public void updateSpigotBlockAsync( XMaterial xMat, Block spigotBlock ) { +// +// if ( xMat != null ) { +// Material newType = xMat.parseMaterial(); +// if ( newType != null ) { +// +// new BukkitRunnable() { +// @Override +// public void run() { +// +// // No physics update: +// spigotBlock.setType( newType, false ); +// } +// }.runTaskLater( getPlugin(), 0 ); +// +// } +// } +// } + /** + *

This function both get's the block and then updates it within + * the same runnable transaction. This should eliminate the need to + * risk reading the block in an async thread, and improve performance. + *

+ * + * @param prisonBlock + * @param location + */ @Override - public void updateSpigotBlockAsync( PrisonBlock prisonBlock, Block spigotBlock ) { + public void updateSpigotBlockAsync( PrisonBlock prisonBlock, Location location ) { - if ( prisonBlock != null && - !prisonBlock.getBlockName().equalsIgnoreCase( InternalBlockTypes.IGNORE.name() ) && - spigotBlock != null ) { - - XMaterial xMat = getXMaterial( prisonBlock ); - - if ( xMat != null ) { - - updateSpigotBlockAsync( xMat, spigotBlock ); - } - } - } - - - @Override - public void updateSpigotBlockAsync( XMaterial xMat, Block spigotBlock ) { + XMaterial xMat = getXMaterial( prisonBlock ); - if ( xMat != null ) { + if ( xMat != null && location != null ) { Material newType = xMat.parseMaterial(); if ( newType != null ) { new BukkitRunnable() { @Override public void run() { - + // No physics update: - spigotBlock.setType( newType, false ); + ((SpigotBlock) location.getBlockAt()).getWrapper() + .setType( newType, false ); + } }.runTaskLater( getPlugin(), 0 ); } + } } + + /** *

This function is supposed to find all possible blocks available * on the server. The number of available items, and blocks, will vary based diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18Blocks.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18Blocks.java index 85c56c939..c30a58e86 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18Blocks.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18Blocks.java @@ -12,8 +12,10 @@ import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.block.SpigotBlock; import tech.mcprison.prison.spigot.block.SpigotItemStack; import tech.mcprison.prison.util.BlockType; +import tech.mcprison.prison.util.Location; public abstract class Spigot18Blocks extends Spigot18Player @@ -406,50 +408,97 @@ public void updateSpigotBlock( XMaterial xMat, Block spigotBlock ) { - @Override - public void updateSpigotBlockAsync( BlockType blockType, Block spigotBlock ) { - - if ( blockType != null && blockType != BlockType.IGNORE && spigotBlock != null ) { - - XMaterial xMat = getXMaterial( blockType ); - - if ( xMat != null ) { - - updateSpigotBlockAsync( xMat, spigotBlock ); - } - } - } +// @Override +// public void updateSpigotBlockAsync( BlockType blockType, Block spigotBlock ) { +// +// if ( blockType != null && blockType != BlockType.IGNORE && spigotBlock != null ) { +// +// XMaterial xMat = getXMaterial( blockType ); +// +// if ( xMat != null ) { +// +// updateSpigotBlockAsync( xMat, spigotBlock ); +// } +// } +// } +// +// +// @Override +// public void updateSpigotBlockAsync( PrisonBlock prisonBlock, Block spigotBlock ) { +// +// if ( prisonBlock != null && +// !prisonBlock.equals( PrisonBlock.IGNORE ) && +// spigotBlock != null ) { +// +// XMaterial xMat = getXMaterial( prisonBlock ); +// +// if ( xMat != null ) { +// +// updateSpigotBlockAsync( xMat, spigotBlock ); +// } +// } +// } +// +// +// @SuppressWarnings( "deprecation" ) +// @Override +// public void updateSpigotBlockAsync( XMaterial xMat, Block spigotBlock ) { +// +// if ( xMat != null ) { +// Material newType = xMat.parseMaterial(); +// if ( newType != null ) { +// +// new BukkitRunnable() { +// @Override +// public void run() { +// +// BlockState bState = spigotBlock.getState(); +// +// // Set the block state with the new type and rawData: +// bState.setType( newType ); +// bState.setRawData( xMat.getData() ); +// +// // Force the update but don't apply the physics: +// bState.update( true, false ); +// } +// }.runTaskLater( getPlugin(), 0 ); +// +// } +// } +// } + /** + *

This function both get's the block and then updates it within + * the same runnable transaction. This should eliminate the need to + * risk reading the block in an async thread, and improve performance. + *

+ * + * @param prisonBlock + * @param location + */ @Override - public void updateSpigotBlockAsync( PrisonBlock prisonBlock, Block spigotBlock ) { + public void updateSpigotBlockAsync( PrisonBlock prisonBlock, Location location ) { - if ( prisonBlock != null && - !prisonBlock.equals( PrisonBlock.IGNORE ) && - spigotBlock != null ) { - - XMaterial xMat = getXMaterial( prisonBlock ); - - if ( xMat != null ) { - - updateSpigotBlockAsync( xMat, spigotBlock ); - } - } - } - - - @SuppressWarnings( "deprecation" ) - @Override - public void updateSpigotBlockAsync( XMaterial xMat, Block spigotBlock ) { + XMaterial xMat = getXMaterial( prisonBlock ); - if ( xMat != null ) { + if ( xMat != null && location != null ) { Material newType = xMat.parseMaterial(); if ( newType != null ) { new BukkitRunnable() { + @SuppressWarnings( "deprecation" ) @Override public void run() { + + // No physics update: + Block spigotBlock = ((SpigotBlock) location.getBlockAt()).getWrapper(); + + // For 1.13.x and higher: + // spigotblock.setType( newType, false ); + + // No physics update: BlockState bState = spigotBlock.getState(); // Set the block state with the new type and rawData: @@ -458,10 +507,12 @@ public void run() { // Force the update but don't apply the physics: bState.update( true, false ); + } }.runTaskLater( getPlugin(), 0 ); } + } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotWorld.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotWorld.java index 95d06bcdf..7317dc335 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotWorld.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotWorld.java @@ -56,6 +56,12 @@ public SpigotWorld(org.bukkit.World bukkitWorld) { .collect(Collectors.toList()); } + /** + *

This does get the actual from the world, but it only reads, and does not + * update. I cannot say this is safe to run asynchronously, but so far I have + * not see any related problems when it is. + * + */ @Override public Block getBlockAt(Location location) { return new SpigotBlock( @@ -71,6 +77,21 @@ public void setBlock( PrisonBlock block, int x, int y, int z ) { SpigotCompatibility.getInstance().updateSpigotBlock( block, bukkitBlock ); } + + + /** + *

This function should be called from an async task, and it will + * drop down in to the synchronous thread to first get the block + * from the world, then it will change to the specified PrisonBlock type. + *

+ * + * @param prisonBlock + * @param location + */ + public void setBlockAsync( PrisonBlock prisonBlock, Location location ) { + + SpigotCompatibility.getInstance().updateSpigotBlockAsync( prisonBlock, location ); + } public org.bukkit.World getWrapper() { return bukkitWorld; From 523a07dd910e71050d2ec771d5c4bb69d883c751 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Wed, 25 Aug 2021 01:59:39 -0400 Subject: [PATCH 011/283] Changed prison's TPS calculation to be able to enable a high-res setting when the `/mines stats` is enabled. The one problem with enabling high resolution mode is that it could show an unrealistic low TPS during a reset. The /lag command shows a much higher TPS value. --- docs/changelog_v3.3.x.md | 4 ++++ .../tech/mcprison/prison/util/PrisonTPS.java | 17 ++++++++++++++++- .../prison/mines/commands/MinesCommands.java | 9 ++++++++- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 4d4f3f74a..9ea260dd6 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-08-25 +* **Changed prison's TPS calculation to be able to enable a high-res setting when the `/mines stats` is enabled.** +The one problem with enabling high resolution mode is that it could show an unrealistic low TPS during a reset. The /lag command shows a much higher TPS value. + + * **Setup up the basics for async updates.** In the code that does the update, it also now reads the block to ensure that the read and update is all done in the synch thread. Otherwise the old code would be risking chunk loading in an async thread. Using the Location and World to perform the async updates outside of needing access to the spigot module. diff --git a/prison-core/src/main/java/tech/mcprison/prison/util/PrisonTPS.java b/prison-core/src/main/java/tech/mcprison/prison/util/PrisonTPS.java index dc358a843..1dc046c4b 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/util/PrisonTPS.java +++ b/prison-core/src/main/java/tech/mcprison/prison/util/PrisonTPS.java @@ -167,6 +167,10 @@ public class PrisonTPS */ public static final double SUBMIT_TICKS_INTERVAL = 10; + // When enabled for highResolution the resolution will be set to submit_ticks_interval == 1, + // false will be the value of SUBMIT_TICKS_INTERVAL: + public boolean highResolution = false; + public static final double TARGET_TPS_AVERAGE_DURATION_IN_TICKS = 20; public static final double TPS_AVERAGE_READINGS_TO_INCLUDE = TARGET_TPS_AVERAGE_DURATION_IN_TICKS / SUBMIT_TICKS_INTERVAL; @@ -198,7 +202,8 @@ public class PrisonTPS public void submitAsyncTPSTask() { lastPollNano = System.nanoTime(); - PrisonTaskSubmitter.runTaskTimerAsync( this, 0, (int) SUBMIT_TICKS_INTERVAL ); + int submitInterval = isHighResolution() ? 1 : (int) SUBMIT_TICKS_INTERVAL; + PrisonTaskSubmitter.runTaskTimerAsync( this, 0, submitInterval ); } @@ -248,6 +253,16 @@ else if ( tps > tpsMax ) { lastPollNano = timeStartNano; } + + + public boolean isHighResolution() { + return highResolution; + } + public void setHighResolution( boolean highResolution ) { + this.highResolution = highResolution; + } + + /** *

Note that the individual TPS entries have already been * averaged based upon the value of SUBMIT_TICKS_INTERVAL, which diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java index 286e2bc29..43ce0640e 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java @@ -2860,7 +2860,10 @@ private void teleportPlayer( Player player, Mine mine, String target ) { } - @Command(identifier = "mines stats", permissions = "mines.stats", description = "Toggle stats on all mines.") + @Command(identifier = "mines stats", permissions = "mines.stats", + description = "Toggle stats on and off for all mine resets. When enabled, " + + "Prison's mine TPS calculations will be set to high-resolution mode " + + "(1 tick vs. 10 ticks).") public void mineStats(CommandSender sender) { PrisonMines pMines = PrisonMines.getInstance(); @@ -2869,6 +2872,10 @@ public void mineStats(CommandSender sender) { // toggle the stats: mMan.setMineStats( !mMan.isMineStats() ); + // When mine stats are enabled, then it will also enable the high resolution + // tracking of the Prison TPS: + Prison.get().getPrisonTPS().setHighResolution( mMan.isMineStats() ); + if ( mMan.isMineStats() ) { sender.sendMessage( "&3Mine Stats are now enabled. Use &7/mines list&3 to view stats on last mine reset. "); From 11a19ac6b2b28d5f3bfcfb98162aafd20b7ed237 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Wed, 25 Aug 2021 02:04:30 -0400 Subject: [PATCH 012/283] Enable the async mine resets, but only for tracers right now using an async task. Tracers have proven to have a profound improvement in speed. --- .../prison/internal/block/PrisonBlock.java | 2 + .../internal/block/PrisonBlockTypes.java | 1 + .../mcprison/prison/mines/data/MineReset.java | 73 ++++++-- .../mines/features/MineTracerBuilder.java | 171 ++++++++++-------- .../mines/tasks/MinePagedResetAsyncTask.java | 159 ++++++++++++++++ 5 files changed, 315 insertions(+), 91 deletions(-) create mode 100644 prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/block/PrisonBlock.java b/prison-core/src/main/java/tech/mcprison/prison/internal/block/PrisonBlock.java index 28aac3252..512d5b1f1 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/block/PrisonBlock.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/block/PrisonBlock.java @@ -18,6 +18,7 @@ public class PrisonBlock public static PrisonBlock AIR; public static PrisonBlock GLASS; + public static PrisonBlock PINK_STAINED_GLASS; public static PrisonBlock IGNORE; public static PrisonBlock NULL_BLOCK; @@ -38,6 +39,7 @@ public class PrisonBlock static { AIR = new PrisonBlock( InternalBlockTypes.AIR.name(), false ); GLASS = new PrisonBlock( InternalBlockTypes.GLASS.name(), true ); + PINK_STAINED_GLASS = new PrisonBlock( InternalBlockTypes.PINK_STAINED_GLASS.name(), true ); IGNORE = new PrisonBlock( InternalBlockTypes.IGNORE.name(), false ); NULL_BLOCK = new PrisonBlock( InternalBlockTypes.NULL_BLOCK.name(), false ); } diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/block/PrisonBlockTypes.java b/prison-core/src/main/java/tech/mcprison/prison/internal/block/PrisonBlockTypes.java index b89393abb..5f593abf2 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/block/PrisonBlockTypes.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/block/PrisonBlockTypes.java @@ -20,6 +20,7 @@ public class PrisonBlockTypes { public enum InternalBlockTypes { AIR, GLASS, + PINK_STAINED_GLASS, IGNORE, NULL_BLOCK } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java index 541d3e6fb..f298dd5f5 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java @@ -353,6 +353,9 @@ public String statsMessage() { sb.append( statsMessageMineSweeper() ); + sb.append( " TPS: " ) + .append( Prison.get().getPrisonTPS().getAverageTPSFormatted() ); + return sb.toString(); } @@ -535,13 +538,33 @@ protected void generateBlockListAsync() { int airCount = 0; int currentLevel = 0; + + int yMin = getBounds().getyBlockMin(); + int yMax = getBounds().getyBlockMax(); + + int xMin = getBounds().getxBlockMin(); + int xMax = getBounds().getxBlockMax(); + + int zMin = getBounds().getzBlockMin(); + int zMax = getBounds().getzBlockMax(); + + // The reset takes place first with the top-most layer since most mines may have // the player enter from the top, and the reset will appear to be more "instant". - for (int y = getBounds().getyBlockMax(); y >= getBounds().getyBlockMin(); y--) { + for (int y = yMax; y >= yMin; y--) { currentLevel++; // One based: First layer is currentLevel == 1 - for (int x = getBounds().getxBlockMin(); x <= getBounds().getxBlockMax(); x++) { - for (int z = getBounds().getzBlockMin(); z <= getBounds().getzBlockMax(); z++) { + for (int x = xMin; x <= xMax; x++) { + for (int z = zMin; z <= zMax; z++) { + + boolean xEdge = x == xMin || x == xMax; + boolean yEdge = y == yMin || y == yMax; + boolean zEdge = z == zMin || z == zMax; + + boolean isEdge = xEdge && yEdge || xEdge && zEdge || + yEdge && zEdge; + + // MineTargetBlock mtb = null; if ( isUseNewBlockModel() ) { @@ -554,7 +577,7 @@ protected void generateBlockListAsync() { // Increment the mine's block count. This block is one of the control blocks: incrementResetBlockCount( prisonBlock ); - addMineTargetPrisonBlock( prisonBlock, x, y, z ); + addMineTargetPrisonBlock( prisonBlock, x, y, z, isEdge ); // mtb = new MineTargetPrisonBlock( prisonBlock, x, y, z); if ( prisonBlock.equals( PrisonBlock.AIR ) ) { @@ -570,7 +593,7 @@ protected void generateBlockListAsync() { // Increment the mine's block count. This block is one of the control blocks: incrementResetBlockCount( tBlock ); - addMineTargetPrisonBlock( tBlock, x, y, z ); + addMineTargetPrisonBlock( tBlock, x, y, z, isEdge ); // mtb = new MineTargetBlock( tBlock.getType(), x, y, z); if ( tBlock.equals( BlockOld.AIR ) ) { @@ -925,7 +948,8 @@ private void resetAsynchonouslyUpdate( boolean paged ) { // Only print these details if stats is enabled: Output.get().logInfo( "MineReset.resetAsynchonouslyUpdate() :" + " page " + getResetPage() + - " blocks = " + blocksPlaced + " elapsed = " + elapsed ); + " blocks = " + blocksPlaced + " elapsed = " + elapsed + + " ms TPS: " + Prison.get().getPrisonTPS().getAverageTPSFormatted() ); } setResetPosition( i ); @@ -1031,22 +1055,45 @@ else if ( !isUseNewBlockModel() && int airCount = 0; int errorCount = 0; + + + + int yMin = getBounds().getyBlockMin(); + int yMax = getBounds().getyBlockMax(); + + int xMin = getBounds().getxBlockMin(); + int xMax = getBounds().getxBlockMax(); + + int zMin = getBounds().getzBlockMin(); + int zMax = getBounds().getzBlockMax(); + + + StringBuilder sb = new StringBuilder(); - for (int y = getBounds().getyBlockMax(); y >= getBounds().getyBlockMin(); y--) { - for (int x = getBounds().getxBlockMin(); x <= getBounds().getxBlockMax(); x++) { - for (int z = getBounds().getzBlockMin(); z <= getBounds().getzBlockMax(); z++) { + for (int y = yMax; y >= yMin; y--) { + for (int x = xMin; x <= xMax; x++) { + for (int z = zMin; z <= zMax; z++) { try { Location targetBlock = new Location(world, x, y, z); Block tBlock = targetBlock.getBlockAt(); + + boolean xEdge = x == xMin || x == xMax; + boolean yEdge = y == yMin || y == yMax; + boolean zEdge = z == zMin || z == zMax; + + boolean isEdge = xEdge && yEdge || xEdge && zEdge || + yEdge && zEdge; + + if ( isUseNewBlockModel() ) { PrisonBlock pBlock = tBlock.getPrisonBlock(); // Increment the mine's block count. This block is one of the control blocks: - addMineTargetPrisonBlock( incrementResetBlockCount( pBlock ), x, y, z ); + addMineTargetPrisonBlock( incrementResetBlockCount( pBlock ), x, y, z, isEdge ); if ( pBlock == null || @@ -1059,7 +1106,7 @@ else if ( !isUseNewBlockModel() && BlockOld oBlock = new BlockOld( tBlock.getType() ); // Increment the mine's block count. This block is one of the control blocks: - addMineTargetPrisonBlock( incrementResetBlockCount( oBlock ), x, y, z ); + addMineTargetPrisonBlock( incrementResetBlockCount( oBlock ), x, y, z, isEdge ); if ( tBlock.getType() == BlockType.AIR ) { @@ -1560,9 +1607,9 @@ public void setCurrentJob( MineJob currentJob ) - private void addMineTargetPrisonBlock( PrisonBlockStatusData block, int x, int y, int z ) { + private void addMineTargetPrisonBlock( PrisonBlockStatusData block, int x, int y, int z, boolean isEdge ) { - MineTargetPrisonBlock mtpb = new MineTargetPrisonBlock( block, getWorld().get(), x, y, z ); + MineTargetPrisonBlock mtpb = new MineTargetPrisonBlock( block, getWorld().get(), x, y, z, isEdge ); getMineTargetPrisonBlocks().add( mtpb ); getMineTargetPrisonBlocksMap().put( mtpb.getBlockKey(), mtpb ); diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTracerBuilder.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTracerBuilder.java index 2a8b766b4..41eecab60 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTracerBuilder.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTracerBuilder.java @@ -1,13 +1,9 @@ package tech.mcprison.prison.mines.features; -import java.util.Optional; - -import tech.mcprison.prison.internal.World; -import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.mines.data.Mine; +import tech.mcprison.prison.mines.tasks.MinePagedResetAsyncTask; +import tech.mcprison.prison.mines.tasks.MinePagedResetAsyncTask.MineResetType; import tech.mcprison.prison.output.Output; -import tech.mcprison.prison.util.BlockType; -import tech.mcprison.prison.util.Location; public class MineTracerBuilder { @@ -48,84 +44,103 @@ public static TracerType fromString( String type ) { return results; } } - + public void clearMine( Mine mine, boolean tracer ) { if ( mine == null ) { - Output.get().logError(" #### NPE ###"); + Output.get().logError(" #### Null MINE? ###"); } - try { - - if ( mine.isVirtual() ) { - // Mine is virtual and cannot be reset. Just skip this with no error messages. - return; - } - - - // Output.get().logInfo( "MineRest.resetSynchonouslyInternal() " + getName() ); - Optional worldOptional = mine.getWorld(); - World world = worldOptional.get(); - - - PrisonBlock blockAirPB = new PrisonBlock( "AIR" ); - BlockType blockAirBT = BlockType.AIR; - - PrisonBlock blockRedPB = new PrisonBlock( "PINK_STAINED_GLASS" ); - BlockType blockRedBT = BlockType.PINK_STAINED_GLASS; - -// PrisonBlock blockRedstonePB = new PrisonBlock( "REDSTONE_BLOCK" ); -// BlockType blockRedstoneBT = BlockType.REDSTONE_BLOCK; - - - - // Reset the block break count before resetting the blocks: -// setBlockBreakCount( 0 ); -// Random random = new Random(); - - int yMin = mine.getBounds().getyBlockMin(); - int yMax = mine.getBounds().getyBlockMax(); - - int xMin = mine.getBounds().getxBlockMin(); - int xMax = mine.getBounds().getxBlockMax(); - - int zMin = mine.getBounds().getzBlockMin(); - int zMax = mine.getBounds().getzBlockMax(); - - for (int y = yMax; y >= yMin; y--) { -// for (int y = getBounds().getyBlockMin(); y <= getBounds().getyBlockMax(); y++) { - for (int x = xMin; x <= xMax; x++) { - for (int z = zMin; z <= zMax; z++) { - Location targetBlock = new Location(world, x, y, z); - - boolean xEdge = x == xMin || x == xMax; - boolean yEdge = y == yMin || y == yMax; - boolean zEdge = z == zMin || z == zMax; - - boolean isEdge = xEdge && yEdge || xEdge && zEdge || - yEdge && zEdge; - - if ( mine.isUseNewBlockModel() ) { - - targetBlock.getBlockAt().setPrisonBlock( - tracer && isEdge ? blockRedPB : blockAirPB ); - } - else { - - targetBlock.getBlockAt().setType( - tracer && isEdge ? blockRedBT : blockAirBT ); - } - } - } - } - - - } - catch (Exception e) { - Output.get().logError("&cFailed to clear mine " + mine.getName() + - " Error: [" + e.getMessage() + "]", e); - } + if ( mine.isVirtual() ) { + // Mine is virtual and cannot be reset. Just skip this with no error messages. + return; + } + + MineResetType resetType = tracer ? MineResetType.tracer : MineResetType.clear; + + MinePagedResetAsyncTask resetTask = new MinePagedResetAsyncTask( mine, resetType ); + resetTask.submitTask(); } +// public void clearMine( Mine mine, boolean tracer ) { +// +// if ( mine == null ) { +// Output.get().logError(" #### Null MINE? ###"); +// } +// try { +// +// if ( mine.isVirtual() ) { +// // Mine is virtual and cannot be reset. Just skip this with no error messages. +// return; +// } +// +// +// // Output.get().logInfo( "MineRest.resetSynchonouslyInternal() " + getName() ); +// +// Optional worldOptional = mine.getWorld(); +// World world = worldOptional.get(); +// +// +// PrisonBlock blockAirPB = new PrisonBlock( "AIR" ); +//// BlockType blockAirBT = BlockType.AIR; +// +// PrisonBlock blockRedPB = new PrisonBlock( "PINK_STAINED_GLASS" ); +//// BlockType blockRedBT = BlockType.PINK_STAINED_GLASS; +// +//// PrisonBlock blockRedstonePB = new PrisonBlock( "REDSTONE_BLOCK" ); +//// BlockType blockRedstoneBT = BlockType.REDSTONE_BLOCK; +// +// +// +// +// +// // Reset the block break count before resetting the blocks: +//// setBlockBreakCount( 0 ); +//// Random random = new Random(); +// +// int yMin = mine.getBounds().getyBlockMin(); +// int yMax = mine.getBounds().getyBlockMax(); +// +// int xMin = mine.getBounds().getxBlockMin(); +// int xMax = mine.getBounds().getxBlockMax(); +// +// int zMin = mine.getBounds().getzBlockMin(); +// int zMax = mine.getBounds().getzBlockMax(); +// +// for (int y = yMax; y >= yMin; y--) { +//// for (int y = getBounds().getyBlockMin(); y <= getBounds().getyBlockMax(); y++) { +// for (int x = xMin; x <= xMax; x++) { +// for (int z = zMin; z <= zMax; z++) { +// Location targetBlock = new Location(world, x, y, z); +// +// boolean xEdge = x == xMin || x == xMax; +// boolean yEdge = y == yMin || y == yMax; +// boolean zEdge = z == zMin || z == zMax; +// +// boolean isEdge = xEdge && yEdge || xEdge && zEdge || +// yEdge && zEdge; +// +// if ( mine.isUseNewBlockModel() ) { +// +// targetBlock.getBlockAt().setPrisonBlock( +// tracer && isEdge ? blockRedPB : blockAirPB ); +// } +//// else { +//// +//// targetBlock.getBlockAt().setType( +//// tracer && isEdge ? blockRedBT : blockAirBT ); +//// } +// } +// } +// } +// +// +// } +// catch (Exception e) { +// Output.get().logError("&cFailed to clear mine " + mine.getName() + +// " Error: [" + e.getMessage() + "]", e); +// } +// } + } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java new file mode 100644 index 000000000..60b691073 --- /dev/null +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java @@ -0,0 +1,159 @@ +package tech.mcprison.prison.mines.tasks; + +import java.util.List; + +import tech.mcprison.prison.Prison; +import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.mines.PrisonMines; +import tech.mcprison.prison.mines.data.Mine; +import tech.mcprison.prison.mines.features.MineTargetPrisonBlock; +import tech.mcprison.prison.output.Output; +import tech.mcprison.prison.tasks.PrisonRunnable; +import tech.mcprison.prison.tasks.PrisonTaskSubmitter; +import tech.mcprison.prison.util.Location; + +public class MinePagedResetAsyncTask + implements PrisonRunnable +{ + private Mine mine; + private final MineResetType resetType; + + private int position = 0; + + private int chunk = 5000; + + private int page = 0; + private int totalPages = 0; + private int subPage = 0; + private int subPagesInAPage = 5; + private int pagePosition = 0; + + + private long timeStart = 0; + private long timePage = 0; + + + + public enum MineResetType { + normal, + clear, + tracer; + } + + + public MinePagedResetAsyncTask( Mine mine, MineResetType resetType ) { + super(); + + this.mine = mine; + this.resetType = resetType; + + this.timeStart = System.currentTimeMillis(); + this.timePage = timeStart; + + this.totalPages = mine.getMineTargetPrisonBlocks().size() / (chunk * subPagesInAPage) + 1; + } + + + public void submitTask() { + long delay = 0; + + + if ( subPage++ % subPagesInAPage == 0 ) { + page++; + + delay = 1; + + if ( PrisonMines.getInstance().getMineManager().isMineStats() ) { + + logStats(); + } + + } + + PrisonTaskSubmitter.runTaskLaterAsync( this, delay ); + } + + + private void logStats() + { + long timeCurrent = System.currentTimeMillis(); + long timeElapsedTotal = timeCurrent - timeStart; + long timeElapsedPage = timeCurrent - timePage; + timePage = timeCurrent; + + + int blocksPlaced = position - pagePosition; + pagePosition = position; + + + // Only print these details if stats is enabled: + Output.get().logInfo( "MinePagedResetAsyncTask : " + resetType.name() + + " : page " + page + " of " + totalPages + " : " + + " blocks = " + blocksPlaced + " elapsed = " + timeElapsedPage + + " ms TotalElapsed = " + timeElapsedTotal + " ms TPS " + + Prison.get().getPrisonTPS().getAverageTPSFormatted() ); + } + + @Override + public void run() { + + List targetBlocks = mine.getMineTargetPrisonBlocks(); + + int chunkEnd = position + chunk; + + for ( int i = position; i < chunkEnd && i < targetBlocks.size(); i++ ) { + MineTargetPrisonBlock tBlock = targetBlocks.get( i ); + + final PrisonBlock pBlock = getPrisonBlock( tBlock ); + + if ( pBlock != null ) { + + Location location = tBlock.getLocation(); + + location.setBlockAsync( pBlock ); + } + + position++; + } + + // Keep resubmitting this task until it is completed: + if ( position < targetBlocks.size() ) { + submitTask(); + } + else { + + // Finished running the task: + logStats(); + } + + } + + + private PrisonBlock getPrisonBlock( MineTargetPrisonBlock tBlock ) { + final PrisonBlock pBlock; + + if ( resetType == MineResetType.tracer && tBlock.isEdge() ) + { + pBlock = PrisonBlock.PINK_STAINED_GLASS; + } + else if ( resetType == MineResetType.clear || + resetType == MineResetType.tracer ) + { + pBlock = PrisonBlock.AIR; + } + else if ( tBlock.getPrisonBlock() != null && + tBlock.getPrisonBlock() instanceof PrisonBlock ) + { + + // MineResetType.normal + pBlock = (PrisonBlock) tBlock.getPrisonBlock(); + } + else + { + pBlock = null; + } + + return pBlock; + } + +} From 790720b90439f5499b962db5a8bd3d8ebc301760 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Wed, 25 Aug 2021 04:24:18 -0400 Subject: [PATCH 013/283] More work on the async resets. --- .../mcprison/prison/mines/PrisonMines.java | 4 +- .../prison/mines/commands/MinesCommands.java | 4 +- .../mcprison/prison/mines/data/MineReset.java | 554 +++++++++++------- .../data/MineResetAsyncResubmitTask.java | 57 +- .../prison/mines/data/MineScheduler.java | 42 +- .../prison/mines/managers/MineManager.java | 4 +- .../mines/tasks/MinePagedResetAsyncTask.java | 54 +- 7 files changed, 443 insertions(+), 276 deletions(-) diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/PrisonMines.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/PrisonMines.java index 4146ca9b7..525e46a92 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/PrisonMines.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/PrisonMines.java @@ -32,7 +32,7 @@ import tech.mcprison.prison.mines.commands.MinesCommands; import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.mines.data.MineScheduler.MineResetActions; -import tech.mcprison.prison.mines.data.MineScheduler.MineResetType; +import tech.mcprison.prison.mines.data.MineScheduler.MineResetScheduleType; import tech.mcprison.prison.mines.data.MinesConfig; import tech.mcprison.prison.mines.data.PrisonSortableResults; import tech.mcprison.prison.mines.managers.MineManager; @@ -280,7 +280,7 @@ public Mine findMineLocation( Location blockLocation ) { * @param resetType * @param resetActions */ - public void resetAllMines( MineResetType resetType, List resetActions ) { + public void resetAllMines( MineResetScheduleType resetType, List resetActions ) { getMineManager().resetAllMines( resetType, resetActions ); } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java index 43ce0640e..eb768b057 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java @@ -42,7 +42,7 @@ import tech.mcprison.prison.mines.data.MineData; import tech.mcprison.prison.mines.data.MineData.MineNotificationMode; import tech.mcprison.prison.mines.data.MineScheduler.MineResetActions; -import tech.mcprison.prison.mines.data.MineScheduler.MineResetType; +import tech.mcprison.prison.mines.data.MineScheduler.MineResetScheduleType; import tech.mcprison.prison.mines.data.PrisonSortableResults; import tech.mcprison.prison.mines.features.MineBlockEvent; import tech.mcprison.prison.mines.features.MineBlockEvent.BlockEventType; @@ -1211,7 +1211,7 @@ public void resetCommand(CommandSender sender, // make sure not null and set to lower case: options = ( options == null ? "" : options.trim().toLowerCase()); - MineResetType resetType = MineResetType.FORCED; + MineResetScheduleType resetType = MineResetScheduleType.FORCED; List resetActions = new ArrayList<>(); diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java index f298dd5f5..0c0d40de2 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java @@ -19,6 +19,8 @@ import tech.mcprison.prison.mines.events.MineResetEvent; import tech.mcprison.prison.mines.features.MineLinerBuilder; import tech.mcprison.prison.mines.features.MineLinerBuilder.LinerPatterns; +import tech.mcprison.prison.mines.tasks.MinePagedResetAsyncTask; +import tech.mcprison.prison.mines.tasks.MinePagedResetAsyncTask.MineResetType; import tech.mcprison.prison.mines.features.MineMover; import tech.mcprison.prison.mines.features.MineTargetBlockKey; import tech.mcprison.prison.mines.features.MineTargetPrisonBlock; @@ -257,7 +259,10 @@ private void resetSynchonouslyInternal() { } } - resetAsynchonouslyUpdate( false ); + + MinePagedResetAsyncTask resetTask = new MinePagedResetAsyncTask( (Mine) this, MineResetType.normal ); + resetTask.submitTaskAsync(); +// resetAsynchonouslyUpdate( false ); @@ -501,7 +506,7 @@ public int getPlayerCount() { *

* */ - protected void generateBlockListAsync() { + public void generateBlockListAsync() { if ( isVirtual() || isDeleted() ) { // ignore and generate no error messages: @@ -680,6 +685,12 @@ private void trackConstraints( int currentLevel, List con } /** + * + *

Update 2021-08-25 : This function should only be called once now. The main + * work on performing the actual resets is now performed within the task + * MinePagedResetAsyncTask. This is now to be ran asynchronously. + *

+ * *

Yeah I know, it has async in the name of the function, but it still can only * be ran synchronously. The async part implies this is the reset "part" for the * async workflow. @@ -690,7 +701,7 @@ private void trackConstraints( int currentLevel, List con *

* */ - protected void resetAsynchonously() { + protected void xresetAsynchonously() { boolean canceled = false; // Output.get().logInfo( "MineRest.resetAsynchonously() " + getName() ); @@ -707,116 +718,216 @@ protected void resetAsynchonously() { if ( !canceled ) { - // First time through... reset the block break count and run the before reset commands: - if ( getResetPosition() == 0 ) { - - // Reset the block break count before resetting the blocks: - // Set it to the original air count, if subtracted from total block count - // in the mine, then the result will be blocks remaining. - setBlockBreakCount( getAirCountOriginal() ); - - - if ( !getCurrentJob().getResetActions().contains( MineResetActions.NO_COMMANDS )) { - - // Before reset commands: - if ( getResetCommands() != null && getResetCommands().size() > 0 ) { - - for (String command : getResetCommands() ) { -// String formatted = cmd.replace("{player}", prisonPlayer.getName()) -// .replace("{player_uid}", player.uid.toString()); - if ( command.startsWith( "before: " )) { - String cmd = command.replace( "before: ", "" ); - - PrisonCommandTask cmdTask = new PrisonCommandTask( "MineReset: Before:" ); - cmdTask.submitCommandTask( cmd ); - - // PrisonAPI.dispatchCommand(cmd); - } - } - } - } - - } - - resetAsynchonouslyUpdate( true ); +// // First time through... reset the block break count and run the before reset commands: +// if ( getResetPosition() == 0 ) { +// +// // Reset the block break count before resetting the blocks: +// // Set it to the original air count, if subtracted from total block count +// // in the mine, then the result will be blocks remaining. +// setBlockBreakCount( getAirCountOriginal() ); +// +// +// if ( !getCurrentJob().getResetActions().contains( MineResetActions.NO_COMMANDS )) { +// +// // Before reset commands: +// if ( getResetCommands() != null && getResetCommands().size() > 0 ) { +// +// for (String command : getResetCommands() ) { +//// String formatted = cmd.replace("{player}", prisonPlayer.getName()) +//// .replace("{player_uid}", player.uid.toString()); +// if ( command.startsWith( "before: " )) { +// String cmd = command.replace( "before: ", "" ); +// +// PrisonCommandTask cmdTask = new PrisonCommandTask( "MineReset: Before:" ); +// cmdTask.submitCommandTask( cmd ); +// +// // PrisonAPI.dispatchCommand(cmd); +// } +// } +// } +// } +// +// } + + asynchronouslyResetSetup(); + + MinePagedResetAsyncTask resetTask = new MinePagedResetAsyncTask( (Mine) this, MineResetType.normal ); + resetTask.submitTaskAsync(); - if ( getResetPosition() == getMineTargetPrisonBlocks().size() ) { - // Done resetting the mine... wrap up: - - - // If a player falls back in to the mine before it is fully done being reset, - // such as could happen if there is lag or a lot going on within the server, - // this will TP anyone out who would otherwise suffocate. I hope! lol - teleportAllPlayersOut(); -// setStatsTeleport2TimeMS( -// teleportAllPlayersOut( getBounds().getyBlockMax() ) ); - - // Reset the paging for the next reset: - setResetPage( 0 ); - - incrementResetCount(); - - if ( !getCurrentJob().getResetActions().contains( MineResetActions.NO_COMMANDS )) { - - // After reset commands: - if ( getResetCommands() != null && getResetCommands().size() > 0 ) { - - for (String command : getResetCommands() ) { -// String formatted = cmd.replace("{player}", prisonPlayer.getName()) -// .replace("{player_uid}", player.uid.toString()); - if ( command.startsWith( "after: " )) { - String cmd = command.replace( "after: ", "" ); - - PrisonCommandTask cmdTask = new PrisonCommandTask( "MineReset: After:" ); - cmdTask.submitCommandTask( cmd ); - - // PrisonAPI.dispatchCommand(cmd); - } - } - } - } - - - // Broadcast message to all players within a certain radius of this mine: - broadcastResetMessageToAllPlayersWithRadius(); -// broadcastResetMessageToAllPlayersWithRadius( MINE_RESET__BROADCAST_RADIUS_BLOCKS ); - - - submitTeleportGlassBlockRemoval(); - - - // Tie to the command stats mode so it logs it if stats are enabled: - if ( PrisonMines.getInstance().getMineManager().isMineStats() || - getCurrentJob().getResetActions().contains( MineResetActions.DETAILS ) ) { - DecimalFormat dFmt = new DecimalFormat("#,##0"); - Output.get().logInfo("&cMine reset: &7" + getTag() + - "&c Blocks: &7" + dFmt.format( getBounds().getTotalBlockCount() ) + - statsMessage() ); - } - - // If part of a chained_resets, then kick off the next reset: - if ( getCurrentJob().getResetActions().contains( MineResetActions.CHAINED_RESETS )) { - - PrisonMines pMines = PrisonMines.getInstance(); - pMines.resetAllMinesNext(); - } - - - } else { - - // Need to continue to reset the mine. Resubmit it to run again. - MineResetAsyncResubmitTask mrAsyncRT = new MineResetAsyncResubmitTask( this, null, - getCurrentJob().getResetActions() ); - - // Must run synchronously!! - submitSyncTask( mrAsyncRT ); - } + asynchronouslyResetFinalize(); + + +// resetAsynchonouslyUpdate( true ); + +// if ( getResetPosition() == getMineTargetPrisonBlocks().size() ) { +// // Done resetting the mine... wrap up: +// +// +// // If a player falls back in to the mine before it is fully done being reset, +// // such as could happen if there is lag or a lot going on within the server, +// // this will TP anyone out who would otherwise suffocate. I hope! lol +// teleportAllPlayersOut(); +//// setStatsTeleport2TimeMS( +//// teleportAllPlayersOut( getBounds().getyBlockMax() ) ); +// +// // Reset the paging for the next reset: +// setResetPage( 0 ); +// +// incrementResetCount(); +// +// if ( !getCurrentJob().getResetActions().contains( MineResetActions.NO_COMMANDS )) { +// +// // After reset commands: +// if ( getResetCommands() != null && getResetCommands().size() > 0 ) { +// +// for (String command : getResetCommands() ) { +//// String formatted = cmd.replace("{player}", prisonPlayer.getName()) +//// .replace("{player_uid}", player.uid.toString()); +// if ( command.startsWith( "after: " )) { +// String cmd = command.replace( "after: ", "" ); +// +// PrisonCommandTask cmdTask = new PrisonCommandTask( "MineReset: After:" ); +// cmdTask.submitCommandTask( cmd ); +// +// // PrisonAPI.dispatchCommand(cmd); +// } +// } +// } +// } +// +// +// // Broadcast message to all players within a certain radius of this mine: +// broadcastResetMessageToAllPlayersWithRadius(); +//// broadcastResetMessageToAllPlayersWithRadius( MINE_RESET__BROADCAST_RADIUS_BLOCKS ); +// +// +// submitTeleportGlassBlockRemoval(); +// +// +// // Tie to the command stats mode so it logs it if stats are enabled: +// if ( PrisonMines.getInstance().getMineManager().isMineStats() || +// getCurrentJob().getResetActions().contains( MineResetActions.DETAILS ) ) { +// DecimalFormat dFmt = new DecimalFormat("#,##0"); +// Output.get().logInfo("&cMine reset: &7" + getTag() + +// "&c Blocks: &7" + dFmt.format( getBounds().getTotalBlockCount() ) + +// statsMessage() ); +// } +// +// // If part of a chained_resets, then kick off the next reset: +// if ( getCurrentJob().getResetActions().contains( MineResetActions.CHAINED_RESETS )) { +// +// PrisonMines pMines = PrisonMines.getInstance(); +// pMines.resetAllMinesNext(); +// } +// +// +// } + +// NOTE: Only run this ONCE now... MinePagedResetAsyncTask handles the paging now +// else { +// +// // Need to continue to reset the mine. Resubmit it to run again. +// MineResetAsyncResubmitTask mrAsyncRT = new MineResetAsyncResubmitTask( this, null, +// getCurrentJob().getResetActions() ); +// +// // Must run synchronously!! +// submitSyncTask( mrAsyncRT ); +// } } } + + public void asynchronouslyResetSetup() { + + // Reset the block break count before resetting the blocks: + // Set it to the original air count, if subtracted from total block count + // in the mine, then the result will be blocks remaining. + setBlockBreakCount( getAirCountOriginal() ); + + + if ( !getCurrentJob().getResetActions().contains( MineResetActions.NO_COMMANDS )) { + + // Before reset commands: + if ( getResetCommands() != null && getResetCommands().size() > 0 ) { + + for (String command : getResetCommands() ) { +// String formatted = cmd.replace("{player}", prisonPlayer.getName()) +// .replace("{player_uid}", player.uid.toString()); + if ( command.startsWith( "before: " )) { + String cmd = command.replace( "before: ", "" ); + + PrisonCommandTask cmdTask = new PrisonCommandTask( "MineReset: Before:" ); + cmdTask.submitCommandTask( cmd ); + + // PrisonAPI.dispatchCommand(cmd); + } + } + } + } + } - private boolean resetAsynchonouslyInitiate() { + public void asynchronouslyResetFinalize() { + // If a player falls back in to the mine before it is fully done being reset, + // such as could happen if there is lag or a lot going on within the server, + // this will TP anyone out who would otherwise suffocate. I hope! lol + teleportAllPlayersOut(); +// setStatsTeleport2TimeMS( +// teleportAllPlayersOut( getBounds().getyBlockMax() ) ); + + // Reset the paging for the next reset: + setResetPage( 0 ); + + incrementResetCount(); + + if ( !getCurrentJob().getResetActions().contains( MineResetActions.NO_COMMANDS )) { + + // After reset commands: + if ( getResetCommands() != null && getResetCommands().size() > 0 ) { + + for (String command : getResetCommands() ) { +// String formatted = cmd.replace("{player}", prisonPlayer.getName()) +// .replace("{player_uid}", player.uid.toString()); + if ( command.startsWith( "after: " )) { + String cmd = command.replace( "after: ", "" ); + + PrisonCommandTask cmdTask = new PrisonCommandTask( "MineReset: After:" ); + cmdTask.submitCommandTask( cmd ); + + // PrisonAPI.dispatchCommand(cmd); + } + } + } + } + + + // Broadcast message to all players within a certain radius of this mine: + broadcastResetMessageToAllPlayersWithRadius(); +// broadcastResetMessageToAllPlayersWithRadius( MINE_RESET__BROADCAST_RADIUS_BLOCKS ); + + + submitTeleportGlassBlockRemoval(); + + + // Tie to the command stats mode so it logs it if stats are enabled: + if ( PrisonMines.getInstance().getMineManager().isMineStats() || + getCurrentJob().getResetActions().contains( MineResetActions.DETAILS ) ) { + DecimalFormat dFmt = new DecimalFormat("#,##0"); + Output.get().logInfo("&cMine reset: &7" + getTag() + + "&c Blocks: &7" + dFmt.format( getBounds().getTotalBlockCount() ) + + statsMessage() ); + } + + // If part of a chained_resets, then kick off the next reset: + if ( getCurrentJob().getResetActions().contains( MineResetActions.CHAINED_RESETS )) { + + PrisonMines pMines = PrisonMines.getInstance(); + pMines.resetAllMinesNext(); + } + + } + + public boolean resetAsynchonouslyInitiate() { boolean canceled = false; if ( isVirtual()) { @@ -860,113 +971,113 @@ private boolean resetAsynchonouslyInitiate() { } - /** - *

This is the synchronous part of the job that actually updates the blocks. - * It will only replace what it can within the given allocated milliseconds, - * then it will terminate and allow this process to re-run, picking up where it - * left off. - *

- * - *

Paging is what this is doing. Running, and doing what it can within it's - * limited amount of time, then yielding to any other task, then resuming later. - * This is a way of running a massive synchronous task, without hogging all the - * resources and killing the TPS. - *

- * - *

NOTE: The values for MINE_RESET__PAGE_TIMEOUT_CHECK__BLOCK_COUNT and for - * MINE_RESET__MAX_PAGE_ELASPSED_TIME_MS are set to arbitrary values and may not - * be the correct values. They may be too large and may have to be adjusted to - * smaller values to better tune the process. - *

- * - */ - private void resetAsynchonouslyUpdate( boolean paged ) { - if ( isVirtual() ) { - // ignore: - } - else - if ( !isEnabled() ) { - Output.get().logError( - String.format( "MineReset: resetAsynchonouslyUpdate failure: Mine is not enabled. " + - "Ensure world exists. mine= %s ", - getName() )); - } - else { - World world = getBounds().getCenter().getWorld(); - - - long start = System.currentTimeMillis(); - -// boolean isFillMode = PrisonMines.getInstance().getConfig().fillMode; - - int blocksPlaced = 0; - long elapsed = 0; - - int i = getResetPosition(); - for ( ; i < getMineTargetPrisonBlocks().size(); i++ ) - { - MineTargetPrisonBlock target = getMineTargetPrisonBlocks().get(i); - - Location targetBlock = new Location(world, - target.getBlockKey().getX(), target.getBlockKey().getY(), - target.getBlockKey().getZ()); - -// if (!isFillMode || isFillMode && targetBlock.getBlockAt().isEmpty()) { -// } - if ( isUseNewBlockModel() ) { - - targetBlock.getBlockAt().setPrisonBlock( (PrisonBlock) target.getPrisonBlock() ); - } - else { - - targetBlock.getBlockAt().setType( ((BlockOld) target.getPrisonBlock()).getType() ); - } - - /** - * If paged is enabled... - * - * About every 250 blocks, or so, check to see if the current wall time - * spent is greater than - * the threshold. If it is greater, then end the update and let it resubmit. - * It does not matter how many blocks were actually updated during this "page", - * but what it is more important is the actual elapsed time. This is to allow other - * processes to get processing time and to eliminate possible lagging. - */ - if ( paged && i % getResetPageTimeoutCheckBlockCount() == 0 ) { - elapsed = System.currentTimeMillis() - start; - if ( elapsed > getResetPageMaxPageElapsedTimeMs() ) { - - break; - } - } - } - - blocksPlaced = i - getResetPosition(); - - if ( PrisonMines.getInstance().getMineManager().isMineStats() ) { - - // Only print these details if stats is enabled: - Output.get().logInfo( "MineReset.resetAsynchonouslyUpdate() :" + - " page " + getResetPage() + - " blocks = " + blocksPlaced + " elapsed = " + elapsed + - " ms TPS: " + Prison.get().getPrisonTPS().getAverageTPSFormatted() ); - } - - setResetPosition( i ); - - setResetPage( getResetPage() + 1 ); - - long time = System.currentTimeMillis() - start; - setStatsBlockUpdateTimeMS( time + getStatsBlockUpdateTimeMS() ); - setStatsResetTimeMS( time + getStatsResetTimeMS() ); - - - setStatsResetPages( getStatsResetPages() + 1 ); - setStatsResetPageBlocks( getStatsResetPageBlocks() + blocksPlaced ); - setStatsResetPageMs( getStatsResetPageMs() + time ); - } - - } +// /** +// *

This is the synchronous part of the job that actually updates the blocks. +// * It will only replace what it can within the given allocated milliseconds, +// * then it will terminate and allow this process to re-run, picking up where it +// * left off. +// *

+// * +// *

Paging is what this is doing. Running, and doing what it can within it's +// * limited amount of time, then yielding to any other task, then resuming later. +// * This is a way of running a massive synchronous task, without hogging all the +// * resources and killing the TPS. +// *

+// * +// *

NOTE: The values for MINE_RESET__PAGE_TIMEOUT_CHECK__BLOCK_COUNT and for +// * MINE_RESET__MAX_PAGE_ELASPSED_TIME_MS are set to arbitrary values and may not +// * be the correct values. They may be too large and may have to be adjusted to +// * smaller values to better tune the process. +// *

+// * +// */ +// private void resetAsynchonouslyUpdate( boolean paged ) { +// if ( isVirtual() ) { +// // ignore: +// } +// else +// if ( !isEnabled() ) { +// Output.get().logError( +// String.format( "MineReset: resetAsynchonouslyUpdate failure: Mine is not enabled. " + +// "Ensure world exists. mine= %s ", +// getName() )); +// } +// else { +// World world = getBounds().getCenter().getWorld(); +// +// +// long start = System.currentTimeMillis(); +// +//// boolean isFillMode = PrisonMines.getInstance().getConfig().fillMode; +// +// int blocksPlaced = 0; +// long elapsed = 0; +// +// int i = getResetPosition(); +// for ( ; i < getMineTargetPrisonBlocks().size(); i++ ) +// { +// MineTargetPrisonBlock target = getMineTargetPrisonBlocks().get(i); +// +// Location targetBlock = new Location(world, +// target.getBlockKey().getX(), target.getBlockKey().getY(), +// target.getBlockKey().getZ()); +// +//// if (!isFillMode || isFillMode && targetBlock.getBlockAt().isEmpty()) { +//// } +// if ( isUseNewBlockModel() ) { +// +// targetBlock.getBlockAt().setPrisonBlock( (PrisonBlock) target.getPrisonBlock() ); +// } +// else { +// +// targetBlock.getBlockAt().setType( ((BlockOld) target.getPrisonBlock()).getType() ); +// } +// +// /** +// * If paged is enabled... +// * +// * About every 250 blocks, or so, check to see if the current wall time +// * spent is greater than +// * the threshold. If it is greater, then end the update and let it resubmit. +// * It does not matter how many blocks were actually updated during this "page", +// * but what it is more important is the actual elapsed time. This is to allow other +// * processes to get processing time and to eliminate possible lagging. +// */ +// if ( paged && i % getResetPageTimeoutCheckBlockCount() == 0 ) { +// elapsed = System.currentTimeMillis() - start; +// if ( elapsed > getResetPageMaxPageElapsedTimeMs() ) { +// +// break; +// } +// } +// } +// +// blocksPlaced = i - getResetPosition(); +// +// if ( PrisonMines.getInstance().getMineManager().isMineStats() ) { +// +// // Only print these details if stats is enabled: +// Output.get().logInfo( "MineReset.resetAsynchonouslyUpdate() :" + +// " page " + getResetPage() + +// " blocks = " + blocksPlaced + " elapsed = " + elapsed + +// " ms TPS: " + Prison.get().getPrisonTPS().getAverageTPSFormatted() ); +// } +// +// setResetPosition( i ); +// +// setResetPage( getResetPage() + 1 ); +// +// long time = System.currentTimeMillis() - start; +// setStatsBlockUpdateTimeMS( time + getStatsBlockUpdateTimeMS() ); +// setStatsResetTimeMS( time + getStatsResetTimeMS() ); +// +// +// setStatsResetPages( getStatsResetPages() + 1 ); +// setStatsResetPageBlocks( getStatsResetPageBlocks() + blocksPlaced ); +// setStatsResetPageMs( getStatsResetPageMs() + time ); +// } +// +// } @@ -1331,15 +1442,18 @@ else if ( getPercentRemainingBlockCount() > getSkipResetPercent() ) { // Mine reset here: // Async if possible... - resetAsynchonously(); - } - - public void refreshMineAsyncResubmitTask() { + MinePagedResetAsyncTask resetTask = new MinePagedResetAsyncTask( (Mine) this, MineResetType.normal ); + resetTask.submitTaskAsync(); - // Mine reset here: - resetAsynchonously(); +// resetAsynchonously(); } +// public void refreshMineAsyncResubmitTask() { +// +// // Mine reset here: +// resetAsynchonously(); +// } + private PrisonBlock randomlySelectPrisonBlock( Random random, int currentLevel ) { diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineResetAsyncResubmitTask.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineResetAsyncResubmitTask.java index cff8db601..1ca335e47 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineResetAsyncResubmitTask.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineResetAsyncResubmitTask.java @@ -1,38 +1,33 @@ package tech.mcprison.prison.mines.data; -import java.util.List; - -import tech.mcprison.prison.mines.data.MineScheduler.MineResetActions; -import tech.mcprison.prison.tasks.PrisonRunnable; - public class MineResetAsyncResubmitTask - implements PrisonRunnable +// implements PrisonRunnable { - private MineReset mine; - private PrisonRunnable callbackAsync; - - private List resetActions; - - public MineResetAsyncResubmitTask(MineReset mine, PrisonRunnable callbackAsync, - List resetActions ) { - - this.mine = mine; - this.callbackAsync = callbackAsync; - - this.resetActions = resetActions; - } - - @Override - public void run() { - - this.mine.getCurrentJob().setResetActions( resetActions ); - - this.mine.refreshMineAsyncResubmitTask(); - - if ( this.callbackAsync != null ) { - this.mine.submitAsyncTask( callbackAsync ); - } - } +// private MineReset mine; +// private PrisonRunnable callbackAsync; +// +// private List resetActions; +// +// public MineResetAsyncResubmitTask(MineReset mine, PrisonRunnable callbackAsync, +// List resetActions ) { +// +// this.mine = mine; +// this.callbackAsync = callbackAsync; +// +// this.resetActions = resetActions; +// } +// +// @Override +// public void run() { +// +// this.mine.getCurrentJob().setResetActions( resetActions ); +// +// this.mine.refreshMineAsyncResubmitTask(); +// +// if ( this.callbackAsync != null ) { +// this.mine.submitAsyncTask( callbackAsync ); +// } +// } } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineScheduler.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineScheduler.java index 1cea8ac3c..d6b0f9665 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineScheduler.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineScheduler.java @@ -16,6 +16,8 @@ import tech.mcprison.prison.mines.PrisonMines; import tech.mcprison.prison.mines.features.MineBlockEvent; import tech.mcprison.prison.mines.features.MineBlockEvent.BlockEventType; +import tech.mcprison.prison.mines.tasks.MinePagedResetAsyncTask; +import tech.mcprison.prison.mines.tasks.MinePagedResetAsyncTask.MineResetType; import tech.mcprison.prison.mines.features.MineTargetPrisonBlock; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.tasks.PrisonCommandTask; @@ -93,7 +95,7 @@ public JobType getJobType() } } - public enum MineResetType { + public enum MineResetScheduleType { NORMAL, FORCED; } @@ -123,7 +125,7 @@ public class MineJob private MineJobAction action; private double delayActionSec; private double resetInSec; - private MineResetType resetType; + private MineResetScheduleType resetType; private List resetActions; public MineJob( MineJobAction action, double delayActionSec, double resetInSec ) @@ -134,12 +136,12 @@ public MineJob( MineJobAction action, double delayActionSec, double resetInSec ) this.delayActionSec = delayActionSec; this.resetInSec = resetInSec; - this.resetType = MineResetType.NORMAL; + this.resetType = MineResetScheduleType.NORMAL; this.resetActions = new ArrayList<>(); } - public MineJob( MineJobAction action, double delayActionSec, double resetInSec, MineResetType resetType ) + public MineJob( MineJobAction action, double delayActionSec, double resetInSec, MineResetScheduleType resetType ) { this( action, delayActionSec, resetInSec ); @@ -186,10 +188,10 @@ public void setResetInSec( double resetInSec ) { this.resetInSec = resetInSec; } - public MineResetType getResetType() { + public MineResetScheduleType getResetType() { return resetType; } - public void setResetType( MineResetType resetType ) { + public void setResetType( MineResetScheduleType resetType ) { this.resetType = resetType; } @@ -325,7 +327,7 @@ public void run() //checkWorld(); boolean forced = getCurrentJob() != null && - getCurrentJob().getResetType() == MineResetType.FORCED; + getCurrentJob().getResetType() == MineResetScheduleType.FORCED; boolean skip = !forced && isSkipResetEnabled() && @@ -363,7 +365,12 @@ public void run() case RESET_ASYNC: if ( !skip ) { - resetAsynchonously(); + + MinePagedResetAsyncTask resetTask = + new MinePagedResetAsyncTask( (Mine) this, MineResetType.paged ); + resetTask.submitTaskAsync(); + +// resetAsynchonously(); } else { incrementSkipResetBypassCount(); } @@ -373,7 +380,12 @@ public void run() case RESET_SYNC: // synchronous reset. Will be phased out in the future? if ( !skip ) { - resetSynchonously(); + + MinePagedResetAsyncTask resetTask = + new MinePagedResetAsyncTask( (Mine) this, MineResetType.normal ); + resetTask.submitTaskAsync(); + +// resetSynchonously(); } else { incrementSkipResetBypassCount(); } @@ -689,7 +701,7 @@ public boolean checkZeroBlockReset() { )) { // submit a manual reset since the mine is empty: - manualReset( MineResetType.NORMAL, getZeroBlockResetDelaySec() ); + manualReset( MineResetScheduleType.NORMAL, getZeroBlockResetDelaySec() ); reset = true; } return reset; @@ -701,21 +713,21 @@ public boolean checkZeroBlockReset() { * */ public void manualReset() { - manualReset( MineResetType.FORCED ); + manualReset( MineResetScheduleType.FORCED ); } - public void manualReset( MineResetType resetType ) { + public void manualReset( MineResetScheduleType resetType ) { if ( !isVirtual() ) { manualReset( resetType, 0 ); } } - private void manualReset( MineResetType resetType, double delayActionSec ) { + private void manualReset( MineResetScheduleType resetType, double delayActionSec ) { List resetActions = new ArrayList<>(); manualReset( resetType, delayActionSec, resetActions ); } - public void manualReset( MineResetType resetType, List resetActions ) { + public void manualReset( MineResetScheduleType resetType, List resetActions ) { manualReset( resetType, 0, resetActions ); } @@ -732,7 +744,7 @@ public void manualReset( MineResetType resetType, List resetAc * @param delayActionSec Delay in seconds before resetting mine. * */ - private void manualReset( MineResetType resetType, double delayActionSec, + private void manualReset( MineResetScheduleType resetType, double delayActionSec, List resetActions ) { if ( isVirtual() ) { diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/managers/MineManager.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/managers/MineManager.java index 2db6049c3..a3db791ac 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/managers/MineManager.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/managers/MineManager.java @@ -33,7 +33,7 @@ import tech.mcprison.prison.mines.PrisonMines; import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.mines.data.MineScheduler.MineResetActions; -import tech.mcprison.prison.mines.data.MineScheduler.MineResetType; +import tech.mcprison.prison.mines.data.MineScheduler.MineResetScheduleType; import tech.mcprison.prison.mines.data.PrisonSortableResults; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.placeholders.ManagerPlaceholders; @@ -482,7 +482,7 @@ public void setMineStats( boolean mineStats ) * @param resetType * @param resetActions */ - public void resetAllMines( MineResetType resetType, List resetActions ) { + public void resetAllMines( MineResetScheduleType resetType, List resetActions ) { cancelResetAllMines(); diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java index 60b691073..231facdf7 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java @@ -36,6 +36,7 @@ public class MinePagedResetAsyncTask public enum MineResetType { normal, + paged, clear, tracer; } @@ -54,7 +55,17 @@ public MinePagedResetAsyncTask( Mine mine, MineResetType resetType ) { } - public void submitTask() { + public void submitTaskSync() { + submitTaskAsync(); + } + public void submitTaskAsync() { + + // Prevent the task from being submitted if it is a virtual mine: + if ( mine.isVirtual() ) { + return; + } + + long delay = 0; @@ -86,7 +97,21 @@ private void logStats() pagePosition = position; - // Only print these details if stats is enabled: + mine.setResetPosition( position ); + + mine.setResetPage( page ); + +// long time = System.currentTimeMillis() - start; + mine.setStatsBlockUpdateTimeMS( timeElapsedPage + mine.getStatsBlockUpdateTimeMS() ); + mine.setStatsResetTimeMS( timeElapsedPage + mine.getStatsResetTimeMS() ); + + + mine.setStatsResetPages( page ); + mine.setStatsResetPageBlocks( mine.getStatsResetPageBlocks() + blocksPlaced ); + mine.setStatsResetPageMs( mine.getStatsResetPageMs() + timeElapsedPage ); + + + // Only print these details if stats are enabled: Output.get().logInfo( "MinePagedResetAsyncTask : " + resetType.name() + " : page " + page + " of " + totalPages + " : " + " blocks = " + blocksPlaced + " elapsed = " + timeElapsedPage + @@ -97,6 +122,25 @@ private void logStats() @Override public void run() { + // The first time running this, need to setup the block list if a reset: + if ( subPage == 1 ) { + if ( resetType == MineResetType.normal || resetType == MineResetType.paged ) { + mine.generateBlockListAsync(); + + // resetAsynchonouslyInitiate() will confirm if the reset should happened + // and will raise Prison's mine reset event. + // A return value of true means cancel the reset: + if ( mine.resetAsynchonouslyInitiate() ) { + return; + } + + } + + mine.asynchronouslyResetSetup(); + + + } + List targetBlocks = mine.getMineTargetPrisonBlocks(); int chunkEnd = position + chunk; @@ -118,11 +162,13 @@ public void run() { // Keep resubmitting this task until it is completed: if ( position < targetBlocks.size() ) { - submitTask(); + submitTaskSync(); } else { // Finished running the task: + mine.asynchronouslyResetFinalize(); + logStats(); } @@ -145,7 +191,7 @@ else if ( tBlock.getPrisonBlock() != null && tBlock.getPrisonBlock() instanceof PrisonBlock ) { - // MineResetType.normal + // MineResetType.normal and MineResetType.paged pBlock = (PrisonBlock) tBlock.getPrisonBlock(); } else From 2a06e5b2370713bbcafb32004680afecef98bb4e Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Wed, 25 Aug 2021 04:24:44 -0400 Subject: [PATCH 014/283] More work on the async resets. --- .../tech/mcprison/prison/mines/features/MineTracerBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTracerBuilder.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTracerBuilder.java index 41eecab60..d5ec44c0e 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTracerBuilder.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTracerBuilder.java @@ -59,7 +59,7 @@ public void clearMine( Mine mine, boolean tracer ) { MineResetType resetType = tracer ? MineResetType.tracer : MineResetType.clear; MinePagedResetAsyncTask resetTask = new MinePagedResetAsyncTask( mine, resetType ); - resetTask.submitTask(); + resetTask.submitTaskAsync(); } // public void clearMine( Mine mine, boolean tracer ) { From 3d5b380b9b3c7254f01a27f089ec44a4cc21e965 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 27 Aug 2021 11:56:15 -0400 Subject: [PATCH 015/283] eliminate the block access in this class since it handles everything in the submitted task. This was causing an error when it was being ran in an async thread. When the task is submitted, it is ran synchoronously so it works correctly. --- docs/changelog_v3.3.x.md | 4 ++ .../mcprison/prison/mines/data/MineTasks.java | 37 +++++++++++-------- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 9ea260dd6..55bb54a4d 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-08-25 +* **eliminate the block access in this class since it handles everything in the submitted task.** +This was causing an error when it was being ran in an async thread. When the task is submitted, it is ran synchoronously so it works correctly. + + * **Changed prison's TPS calculation to be able to enable a high-res setting when the `/mines stats` is enabled.** The one problem with enabling high resolution mode is that it could show an unrealistic low TPS during a reset. The /lag command shows a much higher TPS value. diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineTasks.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineTasks.java index eada36bf0..ad0703801 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineTasks.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineTasks.java @@ -5,7 +5,6 @@ import tech.mcprison.prison.Prison; import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.internal.World; -import tech.mcprison.prison.internal.block.Block; import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.mines.PrisonMines; import tech.mcprison.prison.mines.data.MineScheduler.MineJob; @@ -184,20 +183,28 @@ public void submitTeleportGlassBlockRemoval() { int newY = tpTargetLocation.getBlockY() - 1; glassBlockLocation.setY( newY ); - Block block = glassBlockLocation.getBlockAt(); - if ( block != null ) { - PrisonBlock prisonBlock = block.getPrisonBlock(); - - if ( prisonBlock != null && prisonBlock.equals( PrisonBlock.GLASS ) ) { - // The glass block is under the player's feet so submit to remove it: - - MineChangeBlockTask changeBlockTask = - new MineChangeBlockTask( glassBlockLocation, PrisonBlock.AIR ); - - int delayInTicks = 10; - PrisonTaskSubmitter.runTaskLater( changeBlockTask, delayInTicks ); - } - } + + MineChangeBlockTask changeBlockTask = + new MineChangeBlockTask( glassBlockLocation, PrisonBlock.AIR ); + + int delayInTicks = 10; + PrisonTaskSubmitter.runTaskLater( changeBlockTask, delayInTicks ); + + +// Block block = glassBlockLocation.getBlockAt(); +// if ( block != null ) { +// PrisonBlock prisonBlock = block.getPrisonBlock(); +// +// if ( prisonBlock != null && prisonBlock.equals( PrisonBlock.GLASS ) ) { +// // The glass block is under the player's feet so submit to remove it: +// +// MineChangeBlockTask changeBlockTask = +// new MineChangeBlockTask( glassBlockLocation, PrisonBlock.AIR ); +// +// int delayInTicks = 10; +// PrisonTaskSubmitter.runTaskLater( changeBlockTask, delayInTicks ); +// } +// } } From 433c6513e60a53d31b3ea88f99c4f3ce82120741 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 27 Aug 2021 12:03:30 -0400 Subject: [PATCH 016/283] some internal changes to improve the resets --- .../mines/tasks/MineChangeBlockTask.java | 10 ++- .../mines/tasks/MinePagedResetAsyncTask.java | 76 +++++++++++-------- 2 files changed, 50 insertions(+), 36 deletions(-) diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MineChangeBlockTask.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MineChangeBlockTask.java index c3899fcad..629e71773 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MineChangeBlockTask.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MineChangeBlockTask.java @@ -10,20 +10,24 @@ public class MineChangeBlockTask private Location location; private PrisonBlock targetBlock; + private Location topOfMineLocation; + public MineChangeBlockTask( Location location, PrisonBlock targetBlock ) { super(); this.location = location; this.targetBlock = targetBlock; + + this.topOfMineLocation = new Location( getLocation() ); + this.topOfMineLocation.setY( topOfMineLocation.getBlockY() - 1 ); + } @Override public void run() { - Location topOfMineLocation = new Location( getLocation() ); - topOfMineLocation.setY( topOfMineLocation.getBlockY() - 1 ); - if ( topOfMineLocation.getBlockAt().isEmpty() ) { + // When there is no block under the glass block, spawn in a // glass block so the player won't fall to their death. // This block will be within the mine, so it will be replaced diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java index 231facdf7..9a8e5b3ea 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java @@ -20,12 +20,13 @@ public class MinePagedResetAsyncTask private int position = 0; - private int chunk = 5000; + private int pageSize = 2000; private int page = 0; + private int totalPages = 0; - private int subPage = 0; - private int subPagesInAPage = 5; +// private int subPage = 0; + private int pagesPerReport = 20; private int pagePosition = 0; @@ -51,7 +52,7 @@ public MinePagedResetAsyncTask( Mine mine, MineResetType resetType ) { this.timeStart = System.currentTimeMillis(); this.timePage = timeStart; - this.totalPages = mine.getMineTargetPrisonBlocks().size() / (chunk * subPagesInAPage) + 1; + this.totalPages = (mine.getMineTargetPrisonBlocks().size() / pageSize) + 1; } @@ -66,21 +67,15 @@ public void submitTaskAsync() { } - long delay = 0; - - - if ( subPage++ % subPagesInAPage == 0 ) { - page++; - - delay = 1; + if ( position > 0 && page++ % pagesPerReport == 0 ) { if ( PrisonMines.getInstance().getMineManager().isMineStats() ) { logStats(); } - } + long delay = 0; PrisonTaskSubmitter.runTaskLaterAsync( this, delay ); } @@ -112,7 +107,9 @@ private void logStats() // Only print these details if stats are enabled: - Output.get().logInfo( "MinePagedResetAsyncTask : " + resetType.name() + + Output.get().logInfo( "MinePagedResetAsyncTask : " + + mine.getName() + " " + + resetType.name() + " : page " + page + " of " + totalPages + " : " + " blocks = " + blocksPlaced + " elapsed = " + timeElapsedPage + " ms TotalElapsed = " + timeElapsedTotal + " ms TPS " + @@ -123,29 +120,19 @@ private void logStats() public void run() { // The first time running this, need to setup the block list if a reset: - if ( subPage == 1 ) { - if ( resetType == MineResetType.normal || resetType == MineResetType.paged ) { - mine.generateBlockListAsync(); - - // resetAsynchonouslyInitiate() will confirm if the reset should happened - // and will raise Prison's mine reset event. - // A return value of true means cancel the reset: - if ( mine.resetAsynchonouslyInitiate() ) { - return; - } - + if ( position == 0 ) { + if ( runSetupCancelReset() ) { + // If the reset should be canceled then just return, and that will + // terminate the reset. There is nothing else that needs to be done. + return; } - - mine.asynchronouslyResetSetup(); - - } List targetBlocks = mine.getMineTargetPrisonBlocks(); - int chunkEnd = position + chunk; + int pageEndPosition = position + pageSize; - for ( int i = position; i < chunkEnd && i < targetBlocks.size(); i++ ) { + for ( int i = position; i < pageEndPosition && i < targetBlocks.size(); i++ ) { MineTargetPrisonBlock tBlock = targetBlocks.get( i ); final PrisonBlock pBlock = getPrisonBlock( tBlock ); @@ -166,14 +153,37 @@ public void run() { } else { - // Finished running the task: - mine.asynchronouslyResetFinalize(); + // Finished running the task and let it end: + runShutdown(); + } + + } + + + /** + *

This is ran before the initial actual processing is performed. + * This calls the functions to + */ + private boolean runSetupCancelReset() { + if ( resetType == MineResetType.normal || resetType == MineResetType.paged ) { + mine.generateBlockListAsync(); + + // resetAsynchonouslyInitiate() will confirm if the reset should happened + // and will raise Prison's mine reset event. + // A return value of true means cancel the reset: + return mine.resetAsynchonouslyInitiate(); - logStats(); } + mine.asynchronouslyResetSetup(); + return false; } + + private void runShutdown() { + logStats(); + mine.asynchronouslyResetFinalize(); + } private PrisonBlock getPrisonBlock( MineTargetPrisonBlock tBlock ) { final PrisonBlock pBlock; From c29e04e98794dcfcd1e3f6db158c19b8f1b9e55a Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 27 Aug 2021 12:54:27 -0400 Subject: [PATCH 017/283] Fixed a problem with placeholders when using the search feature, but not supplying a player's name. --- docs/changelog_v3.3.x.md | 8 +++++++- .../tech/mcprison/prison/mines/managers/MineManager.java | 7 ++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 55bb54a4d..817d95c3d 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,13 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.1 2021-08-25 +# 3.2.11-alpha.1 2021-08-27 + + +* **Fixed a problem with placeholders when using the search feature, but not supplying a player's name.** + + +* **some internal changes to improve the resets** * **eliminate the block access in this class since it handles everything in the submitted task.** diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/managers/MineManager.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/managers/MineManager.java index a3db791ac..712f59ec7 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/managers/MineManager.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/managers/MineManager.java @@ -1205,7 +1205,7 @@ private String getTranslateMinesPlaceHolder( Player player, PlaceHolderKey place case prison_pbt: case prison_player_blocks_total: - if ( !mine.isVirtual() ) + if ( !mine.isVirtual() && player != null ) { long blocksTotal = PlayerCache.getInstance().getPlayerBlocksTotal( player ); @@ -1224,7 +1224,7 @@ private String getTranslateMinesPlaceHolder( Player player, PlaceHolderKey place case prison_pbtm: case prison_player_blocks_total_minename: - if ( !mine.isVirtual() ) + if ( !mine.isVirtual() && player != null ) { long blocksTotalByMine = PlayerCache.getInstance() .getPlayerBlocksTotalByMine( player, mine.getName() ); @@ -1463,7 +1463,8 @@ else if ( p.getName().equalsIgnoreCase( playerName ) ) { if ( player == null ) { for ( Player p : Prison.get().getPlatform().getOfflinePlayers() ) { - if ( p.getUUID().compareTo( playerUuid ) == 0 ) { + if ( playerUuid != null && p.getUUID() != null && + p.getUUID().compareTo( playerUuid ) == 0 ) { player = p; break; } From d9380ec325a4adf50f6b858aa9d08dc06d1cd043 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 27 Aug 2021 22:04:06 -0400 Subject: [PATCH 018/283] Fixed an auto features config setting for prison's ExplosiveBockBreakvents priority; it was missing the word priority. Reworked some of the details on autofeatures as displayed through /prison version to update them to better reflect the correct settings and dependencies. --- docs/changelog_v3.3.x.md | 4 + .../autofeatures/AutoFeaturesFileConfig.java | 2 +- .../prison/spigot/SpigotPlatform.java | 85 +++++++++++++------ ...nagerPrisonsExplosiveBlockBreakEvents.java | 2 +- 4 files changed, 67 insertions(+), 26 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 817d95c3d..e189eb7cd 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-08-27 +* **Fixed an auto features config setting for prison's ExplosiveBockBreakvents priority; it was missing the word priority.** +Reworked some of the details on autofeatures as displayed through /prison version to update them to better reflect the correct settings and dependencies. + + * **Fixed a problem with placeholders when using the search feature, but not supplying a player's name.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java index d605b0091..f319e0477 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java +++ b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java @@ -64,7 +64,7 @@ public enum AutoFeatures { PrisonEnchantsExplosiveEventPriority(blockBreakEvents, "DISABLED"), isProcessPrisons_ExplosiveBlockBreakEvents(blockBreakEvents, false), - ProcessPrisons_ExplosiveBlockBreakEvents(blockBreakEvents, "DISABLED"), + ProcessPrisons_ExplosiveBlockBreakEventsPriority(blockBreakEvents, "DISABLED"), blockBreakEvents__ReadMe(blockBreakEvents, diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java index 7931cfac8..994e61fae 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java @@ -1856,13 +1856,31 @@ public List getActiveFeatures() { String bbePriority = afw.getMessage( AutoFeatures.blockBreakEventPriority ); BlockBreakPriority blockBreakPriority = BlockBreakPriority.fromString( bbePriority ); - results.add( String.format(". Block Break Event Priority:&b %s", + results.add( String.format(". '&7org.bukkit.BlockBreakEvent&3' Priority:&b %s", blockBreakPriority.name() ) ); + String pebbePriority = afw.getMessage( AutoFeatures.ProcessPrisons_ExplosiveBlockBreakEventsPriority ); + boolean isPebbeEnabled = afw.isBoolean( AutoFeatures.isProcessPrisons_ExplosiveBlockBreakEvents ); + BlockBreakPriority pebbeEventPriority = BlockBreakPriority.fromString( pebbePriority ); + results.add( String.format("%s. Prison's own '&7ExplosiveBlockBreakEvent&3' Priority:&b %s %s", + (isPebbeEnabled ? "" : "+" ), + pebbeEventPriority.name(), + (isPebbeEnabled ? "&2Enabled" : "&cDisabled") + ) ); + + String peeePriority = afw.getMessage( AutoFeatures.PrisonEnchantsExplosiveEventPriority ); + boolean isPeeeEnabled = afw.isBoolean( AutoFeatures.isProcessPrisonEnchantsExplosiveEvents ); + BlockBreakPriority peeeEventPriority = BlockBreakPriority.fromString( peeePriority ); + results.add( String.format("%s. Pulsi_'s PrisonEnchants '&7PEExplosiveEvent&3' Priority:&b %s %s", + (isPeeeEnabled ? "" : "+" ), + peeeEventPriority.name(), + (isPeeeEnabled ? "&2Enabled" : "&cDisabled") + ) ); + String tebePriority = afw.getMessage( AutoFeatures.TokenEnchantBlockExplodeEventPriority ); boolean isTebeEnabled = afw.isBoolean( AutoFeatures.isProcessTokensEnchantExplosiveEvents ); BlockBreakPriority tebEventPriority = BlockBreakPriority.fromString( tebePriority ); - results.add( String.format("%s. Token Enchant BlockExplodeEvent Priority:&b %s %s", + results.add( String.format("%s. TokenEnchant '&7BlockExplodeEvent&3' Priority:&b %s %s", (isTebeEnabled ? "" : "+" ), tebEventPriority.name(), (isTebeEnabled ? "&2Enabled" : "&cDisabled") @@ -1871,7 +1889,7 @@ public List getActiveFeatures() { String cebuePriority = afw.getMessage( AutoFeatures.CrazyEnchantsBlastUseEventPriority ); boolean isCebueEnabled = afw.isBoolean( AutoFeatures.isProcessCrazyEnchantsBlockExplodeEvents ); BlockBreakPriority cebuEventPriority = BlockBreakPriority.fromString( cebuePriority ); - results.add( String.format("%s. Crazy Enchant BlastUseEvent Priority:&b %s %s", + results.add( String.format("%s. CrazyEnchant '&7BlastUseEvent&3' Priority:&b %s %s", (isCebueEnabled ? "" : "+" ), cebuEventPriority.name(), (isCebueEnabled ? "&2Enabled" : "&cDisabled") @@ -1880,45 +1898,53 @@ public List getActiveFeatures() { String zbsePriority = afw.getMessage( AutoFeatures.ZenchantmentsBlockShredEventPriority ); boolean isZbseEnabled = afw.isBoolean( AutoFeatures.isProcessZenchantsBlockExplodeEvents ); BlockBreakPriority zbsEventPriority = BlockBreakPriority.fromString( zbsePriority ); - results.add( String.format("%s. Zenchantments BlockShredEvent Priority:&b %s %s", + results.add( String.format("%s. Zenchantments '&7BlockShredEvent&3' Priority:&b %s %s", (isZbseEnabled ? "" : "+" ), zbsEventPriority.name(), (isZbseEnabled ? "&2Enabled" : "&cDisabled") ) ); - String peeePriority = afw.getMessage( AutoFeatures.PrisonEnchantsExplosiveEventPriority ); - boolean isPeeeeEnabled = afw.isBoolean( AutoFeatures.isProcessPrisonEnchantsExplosiveEvents ); - BlockBreakPriority peeEventPriority = BlockBreakPriority.fromString( peeePriority ); - results.add( String.format("%s. PrisonEnchants BlockExplodeEvent Priority:&b %s %s", - (isPeeeeEnabled ? "" : "+" ), - peeEventPriority.name(), - (isPeeeeEnabled ? "&2Enabled" : "&cDisabled") - ) ); +// String peeePriority = afw.getMessage( AutoFeatures.PrisonEnchantsExplosiveEventPriority ); +// boolean isPeeeeEnabled = afw.isBoolean( AutoFeatures.isProcessPrisonEnchantsExplosiveEvents ); +// BlockBreakPriority peeEventPriority = BlockBreakPriority.fromString( peeePriority ); +// results.add( String.format("%s. PrisonEnchants BlockExplodeEvent Priority:&b %s %s", +// (isPeeeeEnabled ? "" : "+" ), +// peeEventPriority.name(), +// (isPeeeeEnabled ? "&2Enabled" : "&cDisabled") +// ) ); +// +// results.add( " " ); - results.add( " " ); + + boolean isAutoFeaturesEnabled = afw.isBoolean( AutoFeatures.isAutoFeaturesEnabled ); + if ( !isAutoFeaturesEnabled ) { + results.add( ". AutoFeatures are disabled:" ); + } boolean isAutoPickup = afw.isBoolean( AutoFeatures.autoPickupEnabled ); - results.add( String.format(". Auto Pickup:&b %s", isAutoPickup ) ); + results.add( String.format(". Auto Pickup:&b %s", (!isAutoFeaturesEnabled ? "disabled" : + isAutoPickup )) ); + + results.add( String.format(". Auto Smelt:&b %s", (!isAutoFeaturesEnabled ? "disabled" : + afw.isBoolean( AutoFeatures.autoSmeltEnabled ))) ); - results.add( String.format(". Auto Smelt:&b %s", (!isAutoPickup ? "disabled" : - afw.isBoolean( AutoFeatures.autoSmeltEnabled ))) ); - results.add( String.format(". Auto Block:&b %s", (!isAutoPickup ? "disabled" : - afw.isBoolean( AutoFeatures.autoBlockEnabled ))) ); + results.add( String.format(". Auto Block:&b %s", (!isAutoFeaturesEnabled ? "disabled" : + afw.isBoolean( AutoFeatures.autoBlockEnabled ))) ); results.add( String.format("%s. Handle Normal Drops:&b %s %s", - (isAutoPickup ? "+" : ""), + (isAutoFeaturesEnabled ? "+" : ""), (afw.isBoolean( AutoFeatures.handleNormalDropsEvents ) ? "&2Enabled" : "&cDisabled" ), - (isAutoPickup ? "&d[disabled by Exended Bukkit Fortune]" : "") ) ); + (isAutoFeaturesEnabled ? "&d[Overridden by AutoPickup]" : "") ) ); results.add( String.format("%s. Normal Drop Smelt:&b %s", - (isAutoPickup ? "+" : ""), + (isAutoFeaturesEnabled ? "+" : ""), (afw.isBoolean( AutoFeatures.normalDropSmelt ) ? "&2Enabled" : "&cDisabled" ), - (isAutoPickup ? "&d[disabled by Exended Bukkit Fortune]" : "") ) ); + (isAutoFeaturesEnabled ? "&d[Overridden by AutoPickup]" : "") ) ); results.add( String.format("%s. Normal Drop Block:&b %s", - (isAutoPickup ? "+" : ""), + (isAutoFeaturesEnabled ? "+" : ""), (afw.isBoolean( AutoFeatures.normalDropBlock ) ? "&2Enabled" : "&cDisabled" ), - (isAutoPickup ? "&d[disabled by Exended Bukkit Fortune]" : "") ) ); + (isAutoFeaturesEnabled ? "&d[Overridden by AutoPickup]" : "") ) ); @@ -1969,6 +1995,17 @@ public List getActiveFeatures() { (isXpEnabled ? "" : "+"), afw.isBoolean( AutoFeatures.givePlayerXPAsOrbDrops )) ); + boolean isFoodExhustionEnabled = afw.isBoolean( AutoFeatures.isCalculateFoodExhustion ); + results.add( String.format("%s. Calculate Food Exhustion:&b %s", + (isFoodExhustionEnabled ? "" : "+"), + isFoodExhustionEnabled ) ); + + boolean isCalcAdditionalItemsEnabled = afw.isBoolean( AutoFeatures.isCalculateDropAdditionsEnabled ); + results.add( String.format("%s. Calculate Additional Items in Drop:&b %s (like flint in gravel)", + (isCalcAdditionalItemsEnabled ? "" : "+"), + isCalcAdditionalItemsEnabled ) ); + + diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonsExplosiveBlockBreakEvents.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonsExplosiveBlockBreakEvents.java index e6b8026d0..e630a7778 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonsExplosiveBlockBreakEvents.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonsExplosiveBlockBreakEvents.java @@ -81,7 +81,7 @@ public void initialize() { Output.get().logInfo( "AutoManager: Trying to register ExplosiveBlockBreakEvent Listener" ); - String eP = getMessage( AutoFeatures.ProcessPrisons_ExplosiveBlockBreakEvents ); + String eP = getMessage( AutoFeatures.ProcessPrisons_ExplosiveBlockBreakEventsPriority ); BlockBreakPriority eventPriority = BlockBreakPriority.fromString( eP ); if ( eventPriority != BlockBreakPriority.DISABLED ) { From 3f7ba8b4b711626988630c4606b00b4c3f1e8e7a Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sat, 28 Aug 2021 00:27:55 -0400 Subject: [PATCH 019/283] For the command /ranks autoConfigure made some adjustments to the block lists being used so the top mines have more valuable ores and blocks. There was a shortage and the wrong blocks were being used. --- docs/changelog_v3.3.x.md | 5 ++- .../prison/spigot/SpigotPlatform.java | 37 +++++++++++++------ 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index e189eb7cd..d57ffb791 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,10 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.1 2021-08-27 +# 3.2.11-alpha.1 2021-08-28 + + +* **For the command /ranks autoConfigure made some adjustments to the block lists being used so the top mines have more valuable ores and blocks. There was a shortage and the wrong blocks were being used. * **Fixed an auto features config setting for prison's ExplosiveBockBreakvents priority; it was missing the word priority.** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java index 994e61fae..e33f11467 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java @@ -1641,33 +1641,48 @@ public List buildBlockListXMaterial() { blockList.add( new SellAllBlockData( XMaterial.ANDESITE, 5, true) ); blockList.add( new SellAllBlockData( XMaterial.DIORITE, 6, true) ); blockList.add( new SellAllBlockData( XMaterial.COAL_ORE, 13, true) ); + blockList.add( new SellAllBlockData( XMaterial.GRANITE, 8, true) ); - blockList.add( new SellAllBlockData( XMaterial.STONE, 9, true) ); blockList.add( new SellAllBlockData( XMaterial.IRON_ORE, 18, true) ); blockList.add( new SellAllBlockData( XMaterial.POLISHED_ANDESITE, 7, true) ); + blockList.add( new SellAllBlockData( XMaterial.GOLD_ORE, 45, true) ); blockList.add( new SellAllBlockData( XMaterial.MOSSY_COBBLESTONE, 29, true) ); - blockList.add( new SellAllBlockData( XMaterial.COAL_BLOCK, 135, true) ); - blockList.add( new SellAllBlockData( XMaterial.IRON_BLOCK, 190, true) ); + + + blockList.add( new SellAllBlockData( XMaterial.NETHER_QUARTZ_ORE, 34, true) ); blockList.add( new SellAllBlockData( XMaterial.LAPIS_ORE, 100, true) ); + + + blockList.add( new SellAllBlockData( XMaterial.END_STONE, 14, true ) ); + blockList.add( new SellAllBlockData( XMaterial.IRON_BLOCK, 190, true) ); + blockList.add( new SellAllBlockData( XMaterial.REDSTONE_ORE, 45, true) ); blockList.add( new SellAllBlockData( XMaterial.DIAMOND_ORE, 200, true) ); + blockList.add( new SellAllBlockData( XMaterial.QUARTZ_BLOCK, 136, true) ); blockList.add( new SellAllBlockData( XMaterial.EMERALD_ORE, 250, true) ); + blockList.add( new SellAllBlockData( XMaterial.GOLD_BLOCK, 450, true) ); + blockList.add( new SellAllBlockData( XMaterial.PRISMARINE, 52, true ) ); + + blockList.add( new SellAllBlockData( XMaterial.LAPIS_BLOCK, 950, true) ); blockList.add( new SellAllBlockData( XMaterial.REDSTONE_BLOCK, 405, true) ); + + blockList.add( new SellAllBlockData( XMaterial.OBSIDIAN, 450, true ) ); + blockList.add( new SellAllBlockData( XMaterial.DIAMOND_BLOCK, 2000, true) ); + blockList.add( new SellAllBlockData( XMaterial.DARK_PRISMARINE, 54, true ) ); blockList.add( new SellAllBlockData( XMaterial.EMERALD_BLOCK, 2250, true) ); // blockList.add( XMaterial.SLIME_BLOCK.name() ); - blockList.add( new SellAllBlockData( XMaterial.OBSIDIAN, 450 ) ); @@ -1693,9 +1708,7 @@ public List buildBlockListXMaterial() { - blockList.add( new SellAllBlockData( XMaterial.NETHER_QUARTZ_ORE, 34, true) ); blockList.add( new SellAllBlockData( XMaterial.QUARTZ, 34 ) ); - blockList.add( new SellAllBlockData( XMaterial.QUARTZ_BLOCK, 136, true) ); blockList.add( new SellAllBlockData( XMaterial.QUARTZ_SLAB, 68, true) ); blockList.add( new SellAllBlockData( XMaterial.CHISELED_QUARTZ_BLOCK, 136 ) ); @@ -1714,7 +1727,6 @@ public List buildBlockListXMaterial() { blockList.add( new SellAllBlockData( XMaterial.CRACKED_STONE_BRICKS, 14 ) ); blockList.add( new SellAllBlockData( XMaterial.EMERALD, 14 ) ); - blockList.add( new SellAllBlockData( XMaterial.END_STONE, 14 ) ); blockList.add( new SellAllBlockData( XMaterial.END_STONE_BRICKS, 14 ) ); @@ -1726,12 +1738,10 @@ public List buildBlockListXMaterial() { blockList.add( new SellAllBlockData( XMaterial.PRISMARINE_SHARD, 13 ) ); - blockList.add( new SellAllBlockData( XMaterial.PRISMARINE, 52 ) ); blockList.add( new SellAllBlockData( XMaterial.PRISMARINE_BRICKS, 52 ) ); blockList.add( new SellAllBlockData( XMaterial.PRISMARINE_BRICK_SLAB, 52 ) ); blockList.add( new SellAllBlockData( XMaterial.PRISMARINE_CRYSTALS, 37 ) ); - blockList.add( new SellAllBlockData( XMaterial.DARK_PRISMARINE, 52 ) ); blockList.add( new SellAllBlockData( XMaterial.DARK_PRISMARINE_SLAB, 52 ) ); blockList.add( new SellAllBlockData( XMaterial.PURPUR_BLOCK, 14 ) ); @@ -1821,9 +1831,12 @@ protected List buildBlockListBlockType() { blockList.add( BlockType.MOSSY_COBBLESTONE.name() ); blockList.add( BlockType.COAL_BLOCK.name() ); blockList.add( BlockType.NETHER_QUARTZ_ORE.name() ); + blockList.add( BlockType.LAPIS_ORE.name() ); + + + blockList.add( BlockType.END_STONE.name() ); blockList.add( BlockType.IRON_BLOCK.name() ); - blockList.add( BlockType.LAPIS_ORE.name() ); blockList.add( BlockType.REDSTONE_ORE.name() ); blockList.add( BlockType.DIAMOND_ORE.name() ); @@ -1831,11 +1844,13 @@ protected List buildBlockListBlockType() { blockList.add( BlockType.EMERALD_ORE.name() ); blockList.add( BlockType.GOLD_BLOCK.name() ); + blockList.add( BlockType.PRISMARINE.name() ); blockList.add( BlockType.LAPIS_BLOCK.name() ); blockList.add( BlockType.REDSTONE_BLOCK.name() ); -// blockList.add( BlockType.SLIME_BLOCK.name() ); + blockList.add( BlockType.OBSIDIAN.name() ); blockList.add( BlockType.DIAMOND_BLOCK.name() ); + blockList.add( BlockType.DARK_PRISMARINE.name() ); blockList.add( BlockType.EMERALD_BLOCK.name() ); return blockList; From 05508d89183297ed60618d0876d50f5117cbb567 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sat, 28 Aug 2021 00:34:16 -0400 Subject: [PATCH 020/283] Adjustments to Prison's TPS calculations. They were only taking the average of just two readings which was resulting in very unstable TPS values. Now 10 are being used. Enabled a new feature where the resolution can be changed from normal (a reading every tick) to high resolution (one reading every 2 ticks). When the resolution changes, the task will auto terminate and resubmit with the new settings. --- docs/changelog_v3.3.x.md | 5 +++ .../tech/mcprison/prison/util/PrisonTPS.java | 40 ++++++++++++++++++- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index d57ffb791..72bb30de7 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,11 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-08-28 +* **Adjustments to Prison's TPS calculations.** +They were only taking the average of just two readings which was resulting in very unstable TPS values. Now 10 are being used. +Enabled a new feature where the resolution can be changed from normal (a reading every tick) to high resolution (one reading every 2 ticks). When the resolution changes, the task will auto terminate and resubmit with the new settings. + + * **For the command /ranks autoConfigure made some adjustments to the block lists being used so the top mines have more valuable ores and blocks. There was a shortage and the wrong blocks were being used. diff --git a/prison-core/src/main/java/tech/mcprison/prison/util/PrisonTPS.java b/prison-core/src/main/java/tech/mcprison/prison/util/PrisonTPS.java index 1dc046c4b..84e4326e9 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/util/PrisonTPS.java +++ b/prison-core/src/main/java/tech/mcprison/prison/util/PrisonTPS.java @@ -166,12 +166,18 @@ public class PrisonTPS * processing overhead. */ public static final double SUBMIT_TICKS_INTERVAL = 10; + public static final double SUBMIT_TICKS_INTERVAL_HIGH_RESOLUTION = 2; // When enabled for highResolution the resolution will be set to submit_ticks_interval == 1, // false will be the value of SUBMIT_TICKS_INTERVAL: public boolean highResolution = false; - public static final double TARGET_TPS_AVERAGE_DURATION_IN_TICKS = 20; + + // TPS_AVERAGE_READINGS_TO_INCLUDE needs to include more than just a few TPS + // points to prevent wild fluxuations. With interval at 10 and a total + // duration of 120 ticks, then the readings will be 12 data points. Less will + // reflect variations faster, more will smooth out the bumps and dips. + public static final double TARGET_TPS_AVERAGE_DURATION_IN_TICKS = 120; public static final double TPS_AVERAGE_READINGS_TO_INCLUDE = TARGET_TPS_AVERAGE_DURATION_IN_TICKS / SUBMIT_TICKS_INTERVAL; @@ -199,11 +205,30 @@ public class PrisonTPS public static final Object tpsLock = new Object(); + // When submitted, taskId identifies the job. A value of -1 indicates the job + // failed to be submitted, or is not valid. + private int taskId = -1; + public void submitAsyncTPSTask() { lastPollNano = System.nanoTime(); + if ( taskId > -1 ) { + PrisonTaskSubmitter.cancelTask( taskId ); + + // reset the key values: + tpsHistory.clear();; + tpsMin = 20.0d; + tpsMax = 20.0d; + tpsSamples = 0; + + lastPollNano = System.nanoTime(); + + } + int submitInterval = isHighResolution() ? 1 : (int) SUBMIT_TICKS_INTERVAL; - PrisonTaskSubmitter.runTaskTimerAsync( this, 0, submitInterval ); + int taskId = PrisonTaskSubmitter.runTaskTimerAsync( this, 0, submitInterval ); + + this.taskId = taskId; } @@ -258,8 +283,19 @@ else if ( tps > tpsMax ) { public boolean isHighResolution() { return highResolution; } + + /** + *

If changing the resolution, then resubmit this task so + * it will have the low resolution (10 ticks) or high resolution + * (1 tick). + *

+ * + * @param highResolution + */ public void setHighResolution( boolean highResolution ) { this.highResolution = highResolution; + + submitAsyncTPSTask(); } From eb4cde4933d314f9b0be5c82853cc1845f302d16 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sat, 28 Aug 2021 00:39:47 -0400 Subject: [PATCH 021/283] There was an odd situation where the player was null, when usually they never can be, so this helps prevent possible errors. The null was caused by an issue with a placeholder? Don't really remember. --- docs/changelog_v3.3.x.md | 4 ++++ .../src/main/java/tech/mcprison/prison/cache/PlayerCache.java | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 72bb30de7..711572384 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-08-28 +* **There was an odd situation where the player was null, when usually they never can be, so this helps prevent possible errors.** +The null was caused by an issue with a placeholder? Don't really remember. + + * **Adjustments to Prison's TPS calculations.** They were only taking the average of just two readings which was resulting in very unstable TPS values. Now 10 are being used. Enabled a new feature where the resolution can be changed from normal (a reading every tick) to high resolution (one reading every 2 ticks). When the resolution changes, the task will auto terminate and resubmit with the new settings. diff --git a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCache.java b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCache.java index c4d5f554a..eaca6f85a 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCache.java +++ b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCache.java @@ -222,7 +222,8 @@ private PlayerCachePlayerData getPlayer( Player player ) { getStats().incrementGetPlayers(); - String playerUuid = player.getUUID().toString(); + String playerUuid = player == null || player.getUUID() == null ? null : + player.getUUID().toString(); if ( !getPlayers().containsKey( playerUuid ) ) { // Load the player's existing balance: From 42ada82ee95f658b2d8920a4fa98deefe089a2bc Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sat, 28 Aug 2021 12:40:18 -0400 Subject: [PATCH 022/283] Checking to ensure the locations are not null when loading. There was a failure with bad data on the files system that was resulting in trying to resolve nulls to a location, which obviously cannot happen. --- docs/changelog_v3.3.x.md | 4 +++ .../tech/mcprison/prison/mines/data/Mine.java | 31 +++++++++++++++++-- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 711572384..d10903785 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-08-28 +* **Checking to ensure the locations are not null when loading.** +There was a failure with bad data on the files system that was resulting in trying to resolve nulls to a location, which obviously cannot happen. + + * **There was an odd situation where the player was null, when usually they never can be, so this helps prevent possible errors.** The null was caused by an issue with a placeholder? Don't really remember. diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/Mine.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/Mine.java index f47a39c58..e08391ed0 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/Mine.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/Mine.java @@ -675,13 +675,38 @@ public String toString() { } private Location getLocation(Document doc, World world, String x, String y, String z) { - return new Location(world, (double) doc.get(x), (double) doc.get(y), (double) doc.get(z)); + Location results = null; + + if ( world != null ) { + + Object xD = doc.get(x); + Object yD = doc.get(y); + Object zD = doc.get(z); + + if ( xD != null && yD != null && zD != null ) { + + results = new Location(world, (double) xD, (double) yD, (double) zD ); + } + + } + return results; } private Location getLocation(Document doc, World world, String x, String y, String z, String pitch, String yaw) { Location loc = getLocation(doc, world, x, y, z); - loc.setPitch( ((Double) doc.get(pitch)).floatValue() ); - loc.setYaw( ((Double) doc.get(yaw)).floatValue() ); + + Object pitchD = doc.get(pitch); + Object yawD = doc.get(yaw); + + if ( pitchD != null ) { + + loc.setPitch( ((Double) pitchD ).floatValue() ); + } + + if ( yawD != null ) { + + loc.setYaw( ((Double) yawD ).floatValue() ); + } return loc; } From 36e68ac5508deedb30cf0a9fa742001faa1e7487 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sat, 28 Aug 2021 19:48:17 -0400 Subject: [PATCH 023/283] If the Mine's saved file data is corrupted (manually edited with incorrect data), this will prevent the mine from being loaded and will now generate an error message indicating which mine has a problem loading. It will print out the invalid data, and it will default to a value of 0.00001. --- docs/changelog_v3.3.x.md | 7 +++ .../tech/mcprison/prison/mines/data/Mine.java | 2 +- .../prison/mines/features/MineBlockEvent.java | 49 ++++++++++++++++--- 3 files changed, 51 insertions(+), 7 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index d10903785..0ee38377b 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,13 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-08-28 +* **If the Mine's saved file data is corrupted (manually edited with incorrect data), this will prevent the mine from being loaded and will now generate an error message indicating which mine has a problem loading. It will print out the invalid data, and it will default to a value of 0.00001. The function has been updated to "properly" use the localized format, so if it saves in a non US way, then it should now be able to read it back in and parse it correctly. + + +* **If the Mine's saved file data is corrupted (manually edited with incorrect data),** +this will prevent the mine from being loaded and will now generate an error message indicating which mine has a problem loading. It will print out the invalid data, and it will default to a value of 0.00001. + + * **Checking to ensure the locations are not null when loading.** There was a failure with bad data on the files system that was resulting in trying to resolve nulls to a location, which obviously cannot happen. diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/Mine.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/Mine.java index e08391ed0..890810210 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/Mine.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/Mine.java @@ -511,7 +511,7 @@ else if ( prisonBlock != null && validateBlockNames.contains( prisonBlock.getBlo List mineBlockEvents = (List) document.get("mineBlockEvents"); if ( mineBlockEvents != null ) { for ( String blockEvent : mineBlockEvents ) { - getBlockEvents().add( MineBlockEvent.fromSaveString( blockEvent ) ); + getBlockEvents().add( MineBlockEvent.fromSaveString( blockEvent, this.getName() ) ); } } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineBlockEvent.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineBlockEvent.java index ea8cc5778..2af3b66d9 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineBlockEvent.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineBlockEvent.java @@ -1,12 +1,16 @@ package tech.mcprison.prison.mines.features; import java.text.DecimalFormat; +import java.text.NumberFormat; +import java.text.ParseException; +import java.util.Locale; import java.util.Set; import java.util.TreeSet; import tech.mcprison.prison.Prison; import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.internal.block.PrisonBlockTypes; +import tech.mcprison.prison.output.Output; import tech.mcprison.prison.tasks.PrisonCommandTask.TaskMode; public class MineBlockEvent { @@ -137,8 +141,17 @@ public MineBlockEvent( double chance, String permission, public String toSaveString() { - DecimalFormat dFmt = new DecimalFormat("0.00000"); - return dFmt.format( getChance() ) + "|" + + + NumberFormat nFmt = DecimalFormat.getInstance( Locale.US ); + if ( nFmt instanceof DecimalFormat ) { + DecimalFormat df = (DecimalFormat) nFmt; + df.applyLocalizedPattern( "0.00000" ); + } + nFmt.format( getChance() ); + +// DecimalFormat dFmt = new DecimalFormat("0.00000"); + + return nFmt.format( getChance() ) + "|" + (getPermission() == null || getPermission().trim().length() == 0 ? "none" : getPermission()) + "|" + getCommand() + "|" + getTaskMode().name() + "|" + getEventType().name() + "|" + @@ -147,12 +160,12 @@ public String toSaveString() { } - public static MineBlockEvent fromSaveString( String blockEventString ) { + public static MineBlockEvent fromSaveString( String blockEventString, String mineName ) { MineBlockEvent results = null; if ( blockEventString != null && !blockEventString.startsWith( "ver" ) ) { - results = fromStringV1( blockEventString ); + results = fromStringV1( blockEventString, mineName ); } // if ( chancePermCommand != null && chancePermCommand.trim().length() > 0 ) { @@ -191,13 +204,37 @@ public static MineBlockEvent fromSaveString( String blockEventString ) { } - private static MineBlockEvent fromStringV1( String chancePermCommand ) { + private static MineBlockEvent fromStringV1( String chancePermCommand, String mineName ) { MineBlockEvent results = null; if ( chancePermCommand != null && chancePermCommand.trim().length() > 0 ) { String[] cpc = chancePermCommand.split( "\\|" ); - double chance = cpc.length >= 1 ? Double.parseDouble( cpc[0] ) : 0d; + + double chance = 0.00001; + try { + String dbl = cpc.length >= 1 ? cpc[0] : "0"; + + NumberFormat nFmt = DecimalFormat.getInstance( Locale.US ); + if ( nFmt instanceof DecimalFormat ) { + DecimalFormat df = (DecimalFormat) nFmt; + df.applyLocalizedPattern( "0.00000" ); + } + Number nDbl = nFmt.parse( dbl ); + if ( nDbl != null ) { + chance = nDbl.doubleValue(); + } + +// chance = cpc.length >= 1 ? Double.parseDouble( cpc[0] ) : 0d; + } + catch ( ParseException | NumberFormatException e ) { + Output.get().logError( "Failure parsing a mine " + mineName + + "'s blockEven percent chance. " + + "It is not a double number. Please use the command " + + "'/mines blockEvent add help' when creating blockEvents instead of " + + "manually editing the files. The incorrect value was [" + cpc[0] + + "]. Using a value of [0.00001] instead."); + } String permission = cpc.length >= 2 ? cpc[1] : ""; if ( permission == null || "none".equalsIgnoreCase( permission) ) { From 8cc193af392a3d7281c1d773b7bc1bb0853e559d Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sat, 28 Aug 2021 21:11:00 -0400 Subject: [PATCH 024/283] Added the ability to identify if a block is able to be affected by gravity. Also the mine has a global setting to identify quickly if any block is gravity affected. This will be used to alter the mine reset strategy to improve performance so as to hopefully eliminate long resets due to extensive lag from falling blocks. The idea is to get all the other blocks in to place before placing the falling blocks to ensure they are less likely to fall. --- .../internal/block/PrisonBlockStatusData.java | 79 ++++++++++++++++++- .../mines/commands/MinesBlockCommands.java | 26 ++++++ .../tech/mcprison/prison/mines/data/Mine.java | 28 ++++--- .../mcprison/prison/mines/data/MineData.java | 40 ++++++++++ 4 files changed, 162 insertions(+), 11 deletions(-) diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/block/PrisonBlockStatusData.java b/prison-core/src/main/java/tech/mcprison/prison/internal/block/PrisonBlockStatusData.java index 31b10143d..12998768e 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/block/PrisonBlockStatusData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/block/PrisonBlockStatusData.java @@ -33,6 +33,9 @@ public abstract class PrisonBlockStatusData { private int rangeBlockCountHighLimit; + private boolean gravity = false; + + public PrisonBlockStatusData( String blockName, double chance, long blockCountTotal ) { super(); @@ -57,8 +60,11 @@ public PrisonBlockStatusData( String blockName, double chance, long blockCountTo this.rangeBlockCountLowLimit = -1; this.rangeBlockCountHighLimit = -1; + + this.gravity = checkGravityAffects( blockName ); } - + + public void resetAfterSave() { blockCountUnsaved = 0; } @@ -91,7 +97,11 @@ public static PrisonBlock parseFromSaveFileFormat( String blockString ) { String[] split = blockString.split("-"); if ( split != null && split.length > 0 ) { + // The blockName is the first element. Use that to setup the PrisonBlock that + // will be used if the other stats that are available. String blockTypeName = split[0]; + + // The new way to get the PrisonBlocks: // The blocks return are cloned so they have their own instance: results = Prison.get().getPlatform().getPrisonBlock( blockTypeName ); @@ -115,6 +125,8 @@ public static PrisonBlock parseFromSaveFileFormat( String blockString ) { public void parseFromSaveFileFormatStats( String blockString ) { + + if ( blockString != null ) { String[] split = blockString.split("-"); @@ -289,6 +301,64 @@ public void addStats( PrisonBlockStatusData block ) { } + + /** + *

If a block is affected by gravity, which means the block can fall, then + * this function will return a value of true. + *

+ * + *

The items that are most likely to appear in the mine should + * be at the top to allow the minimization of what is required to be + * checked. + *

+ * + * https://minecraft.fandom.com/wiki/Falling_Block + * + * @param blockName + * @return + */ + private boolean checkGravityAffects( String blockName ) + { + boolean results = false; + + switch ( blockName ) + { + case "sand": + case "red_sand": + case "gravel": + + case "white_concrete_powder": + case "orange_concrete_powder": + case "magenta_concrete_powder": + case "light_blue_concrete_powder": + case "yellow_concrete_powder": + case "lime_concrete_powder": + case "pink_concrete_powder": + case "gray_concrete_powder": + case "light_gray_concrete_powder": + case "cyan_concrete_powder": + case "purple_concrete_powder": + case "blue_concrete_powder": + case "brown_concrete_powder": + case "green_concrete_powder": + case "red_concrete_powder": + case "black_concrete_powder": + + case "anvil": + case "chipped_anvil": + case "damaged_anvil": + + case "scaffolding": + case "pointed_dripstone": + case "dragon_egg": + { + results = true; + } + } + return results; + } + + @Override public String toString() { StringBuilder sb = new StringBuilder(); @@ -400,4 +470,11 @@ public void setRangeBlockCountHighLimit( int rangeBlockCountHighLimit ) { this.rangeBlockCountHighLimit = rangeBlockCountHighLimit; } + public boolean isGravity() { + return gravity; + } + public void setGravity( boolean gravity ) { + this.gravity = gravity; + } + } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesBlockCommands.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesBlockCommands.java index 2f978af11..1a473f3bd 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesBlockCommands.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesBlockCommands.java @@ -129,6 +129,9 @@ else if ( chance <= 0 ) { percentTotal.getOldBlock().setChance( chance ); } + // Check if one of the blocks is effected by gravity, and if so, set that indicator. + m.checkGravityAffectedBlocks(); + pMines.getMineManager().saveMine( m ); pMines.getMinesMessages().getLocalizable("block_added") @@ -150,6 +153,11 @@ private void updateMinePrisonBlock( CommandSender sender, Mine m, PrisonBlock pr sender.sendMessage( "The percent chance must have a value greater than zero." ); } else { + + // Check if one of the blocks is effected by gravity, and if so, set that indicator. + m.checkGravityAffectedBlocks(); + + // Delete the block since it exists and the chance was set to zero: deleteBlock( sender, pMines, m, existingPrisonBlock ); } @@ -178,6 +186,9 @@ private void updateMinePrisonBlock( CommandSender sender, Mine m, PrisonBlock pr existingPrisonBlock.setChance( chance ); } + // Check if one of the blocks is effected by gravity, and if so, set that indicator. + m.checkGravityAffectedBlocks(); + pMines.getMineManager().saveMine( m ); pMines.getMinesMessages().getLocalizable("block_set") @@ -186,6 +197,9 @@ private void updateMinePrisonBlock( CommandSender sender, Mine m, PrisonBlock pr else { prisonBlock.setChance( chance ); m.addPrisonBlock( prisonBlock ); + + // Check if one of the blocks is effected by gravity, and if so, set that indicator. + m.checkGravityAffectedBlocks(); pMines.getMineManager().saveMine( m ); @@ -478,6 +492,10 @@ public void setBlockCommand(CommandSender sender, percentTotal.getOldBlock().setChance( chance ); + // Check if one of the blocks is effected by gravity, and if so, set that indicator. + m.checkGravityAffectedBlocks(); + + pMines.getMineManager().saveMine( m ); pMines.getMinesMessages().getLocalizable("block_set") @@ -637,6 +655,10 @@ public void delBlockCommand(CommandSender sender, */ private void deleteBlock( CommandSender sender, PrisonMines pMines, Mine m, PrisonBlock prisonBlock ) { if ( m.removePrisonBlock( prisonBlock ) ) { + + // Check if one of the blocks is effected by gravity, and if so, set that indicator. + m.checkGravityAffectedBlocks(); + pMines.getMineManager().saveMine( m ); pMines.getMinesMessages().getLocalizable("block_deleted"). @@ -661,6 +683,10 @@ private void deleteBlock( CommandSender sender, PrisonMines pMines, Mine m, Bloc } } if ( m.getBlocks().remove( rBlock )) { + + // Check if one of the blocks is effected by gravity, and if so, set that indicator. + m.checkGravityAffectedBlocks(); + pMines.getMineManager().saveMine( m ); pMines.getMinesMessages().getLocalizable("block_deleted") diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/Mine.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/Mine.java index 890810210..eb1719565 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/Mine.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/Mine.java @@ -417,23 +417,27 @@ else if (validateBlockNames.contains( blockTypeName ) ) { PrisonBlock prisonBlock = PrisonBlockStatusData.parseFromSaveFileFormat( docBlock ); - - if ( prisonBlock != null && !validateBlockNames.contains( prisonBlock.getBlockName() )) { + if ( prisonBlock != null ) { - if ( prisonBlock.isLegacyBlock() ) { + if ( !validateBlockNames.contains( prisonBlock.getBlockName() )) { + + if ( prisonBlock.isLegacyBlock() ) { + dirty = true; + } + addPrisonBlock( prisonBlock ); + + validateBlockNames.add( prisonBlock.getBlockName() ); + } + else if ( validateBlockNames.contains( prisonBlock.getBlockName() ) ) { + // Detected and fixed a duplication so mark as dirty so fixed block list is saved: dirty = true; + inconsistancy = true; } - addPrisonBlock( prisonBlock ); - validateBlockNames.add( prisonBlock.getBlockName() ); - } - else if ( prisonBlock != null && validateBlockNames.contains( prisonBlock.getBlockName() ) ) { - // Detected and fixed a duplication so mark as dirty so fixed block list is saved: - dirty = true; - inconsistancy = true; } + // String[] split = docBlock.split("-"); // String blockTypeName = split[0]; // double chance = split.length > 1 ? Double.parseDouble(split[1]) : 0; @@ -476,6 +480,10 @@ else if ( prisonBlock != null && validateBlockNames.contains( prisonBlock.getBlo } } } + + + // Check if one of the blocks is effected by gravity, and if so, set that indicator. + checkGravityAffectedBlocks(); if ( isUseNewBlockModel() && diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java index a45907205..6d11ff8f4 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java @@ -105,6 +105,20 @@ public abstract class MineData private TreeMap blockStats; + /** + *

If any of the mine's blocks are effected by gravity, then this field + * will indicate that this mine has at least one. This field prevents the + * need to always check all the blocks. Special processing needs to be performed + * when resetting a mine with these blocks, since a non-gravity affected + * block must be placed first, prior to placing a gravity block. Or just leave + * it as is, even if it's air. Then on a second pass, place the gravity + * affected block. Technique may vary and could be controlled by settings. + *

+ */ + private transient boolean hasGravityAffectedBlocks = false; + + private transient PrisonBlock tempGravityBlock = null; + private int blockBreakCount = 0; private long totalBlocksMined = 0; @@ -1270,6 +1284,32 @@ public void setMineSweeperBlocksChanged( long mineSweeperBlocksChanged ) { this.mineSweeperBlocksChanged = mineSweeperBlocksChanged; } + public void checkGravityAffectedBlocks() { + setHasGravityAffectedBlocks( false ); + + for ( PrisonBlock pBlock : getPrisonBlocks() ) { + + if ( pBlock.isGravity() ) { + setHasGravityAffectedBlocks( true ); + break; + } + } + } + + public boolean isHasGravityAffectedBlocks() { + return hasGravityAffectedBlocks; + } + public void setHasGravityAffectedBlocks( boolean hasGravityAffectedBlocks ) { + this.hasGravityAffectedBlocks = hasGravityAffectedBlocks; + } + + public PrisonBlock getTempGravityBlock() { + return tempGravityBlock; + } + public void setTempGravityBlock( PrisonBlock tempGravityBlock ) { + this.tempGravityBlock = tempGravityBlock; + } + public boolean isDeleted() { return isDeleted; } From 2958ae7e05aa101456051c6fbb4a45fa1a8fb7bb Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sat, 28 Aug 2021 21:20:06 -0400 Subject: [PATCH 025/283] Clarify some of the messages related to listing of the block events. --- docs/changelog_v3.3.x.md | 7 +++++++ .../autofeatures/events/AutoManagerPrisonEnchants.java | 10 +++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 0ee38377b..707fd5127 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,13 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-08-28 +* **Clarify some of the messages related to listing of the block events.** + + +* **Added the ability to identify if a block is able to be affected by gravity. Also the mine has a global setting to identify quickly if any block is gravity affected.** +This will be used to alter the mine reset strategy to improve performance so as to hopefully eliminate long resets due to extensive lag from falling blocks. The idea is to get all the other blocks in to place before placing the falling blocks to ensure they are less likely to fall. + + * **If the Mine's saved file data is corrupted (manually edited with incorrect data), this will prevent the mine from being loaded and will now generate an error message indicating which mine has a problem loading. It will print out the invalid data, and it will default to a value of 0.00001. The function has been updated to "properly" use the localized format, so if it saves in a non US way, then it should now be able to read it back in and parse it correctly. diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonEnchants.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonEnchants.java index 2a4704c6b..4f0a2f493 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonEnchants.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonEnchants.java @@ -77,12 +77,12 @@ public void initialize() { // Check to see if the class ExplosiveEvent even exists: try { - Output.get().logInfo( "AutoManager: checking if loaded: PrisonEnchants" ); + Output.get().logInfo( "AutoManager: checking if loaded: Pulsi_'s PrisonEnchants" ); Class.forName( "me.pulsi_.prisonenchants.events.PEExplosionEvent", false, this.getClass().getClassLoader() ); - Output.get().logInfo( "AutoManager: Trying to register PrisonEnchants" ); + Output.get().logInfo( "AutoManager: Trying to register Pulsi_'s PrisonEnchants" ); String eP = getMessage( AutoFeatures.PrisonEnchantsExplosiveEventPriority ); @@ -150,10 +150,10 @@ public void execute(Listener l, Event e) { } catch ( ClassNotFoundException e ) { // PrisonEnchants is not loaded... so ignore. - Output.get().logInfo( "AutoManager: PrisonEnchants is not loaded" ); + Output.get().logInfo( "AutoManager: Pulsi_'s PrisonEnchants is not loaded" ); } catch ( Exception e ) { - Output.get().logInfo( "AutoManager: PrisonEnchants failed to load. [%s]", e.getMessage() ); + Output.get().logInfo( "AutoManager: Pulsi_'s PrisonEnchants failed to load. [%s]", e.getMessage() ); } } @@ -201,7 +201,7 @@ public void dumpEventListeners( StringBuilder sb ) { ChatDisplay eventDisplay = Prison.get().getPlatform().dumpEventListenersChatDisplay( - "PEExplosionEvent", + "Pulsi_'s PEExplosionEvent", new SpigotHandlerList( PEExplosionEvent.getHandlerList()) ); if ( eventDisplay != null ) { From ec9c22d24071b49a197c0fa64126183126a804e9 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 29 Aug 2021 14:20:23 -0400 Subject: [PATCH 026/283] Updates to async block updates. Included changes to hook up the CustomItems to work with the async updates. --- docs/changelog_v3.3.x.md | 6 +- .../integration/CustomBlockIntegration.java | 5 +- .../mines/tasks/MinePagedResetAsyncTask.java | 17 ++--- .../prison/spigot/compat/Spigot113Blocks.java | 6 +- .../spigot/customblock/CustomItems.java | 7 +++ .../customblock/CustomItemsWrapper.java | 62 ++++++++++++++++++- .../prison/spigot/game/SpigotWorld.java | 33 ++++++++-- 7 files changed, 118 insertions(+), 18 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 707fd5127..3a065d93d 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,11 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.1 2021-08-28 +# 3.2.11-alpha.1 2021-08-29 + + +* **Updates to async block updates.** +Included changes to hook up the CustomItems to work with the async updates. * **Clarify some of the messages related to listing of the block events.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/integration/CustomBlockIntegration.java b/prison-core/src/main/java/tech/mcprison/prison/integration/CustomBlockIntegration.java index 591c13599..e9b118296 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/integration/CustomBlockIntegration.java +++ b/prison-core/src/main/java/tech/mcprison/prison/integration/CustomBlockIntegration.java @@ -5,6 +5,7 @@ import tech.mcprison.prison.internal.block.Block; import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.internal.block.PrisonBlock.PrisonBlockType; +import tech.mcprison.prison.util.Location; public abstract class CustomBlockIntegration extends IntegrationCore { @@ -44,7 +45,9 @@ public CustomBlockIntegration( String keyName, String providerName, public abstract PrisonBlock getCustomBlock( Block block ); public abstract Block setCustomBlockId( Block block, String customId, boolean doBlockUpdate ); - + + public abstract void setCustomBlockIdAsync( PrisonBlock prisonBlock, Location location ); + public abstract List getCustomBlockList(); diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java index 9a8e5b3ea..aa4accb1d 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java @@ -107,13 +107,16 @@ private void logStats() // Only print these details if stats are enabled: - Output.get().logInfo( "MinePagedResetAsyncTask : " + - mine.getName() + " " + - resetType.name() + - " : page " + page + " of " + totalPages + " : " + - " blocks = " + blocksPlaced + " elapsed = " + timeElapsedPage + - " ms TotalElapsed = " + timeElapsedTotal + " ms TPS " + - Prison.get().getPrisonTPS().getAverageTPSFormatted() ); + if ( PrisonMines.getInstance().getMineManager().isMineStats() ) { + + Output.get().logInfo( "MinePagedResetAsyncTask : " + + mine.getName() + " " + + resetType.name() + + " : page " + page + " of " + totalPages + " : " + + " blocks = " + blocksPlaced + " elapsed = " + timeElapsedPage + + " ms TotalElapsed = " + timeElapsedTotal + " ms TPS " + + Prison.get().getPrisonTPS().getAverageTPSFormatted() ); + } } @Override diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113Blocks.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113Blocks.java index 768bdbf9c..f04001871 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113Blocks.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113Blocks.java @@ -286,8 +286,10 @@ public void updateSpigotBlockAsync( PrisonBlock prisonBlock, Location location ) public void run() { // No physics update: - ((SpigotBlock) location.getBlockAt()).getWrapper() - .setType( newType, false ); + Block spigotBlock = ((SpigotBlock) location.getBlockAt()).getWrapper(); + + // For 1.13.x and higher: + spigotBlock.setType( newType, false ); } }.runTaskLater( getPlugin(), 0 ); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/CustomItems.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/CustomItems.java index edb653cf6..06dfe5cad 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/CustomItems.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/CustomItems.java @@ -12,6 +12,7 @@ import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.spiget.BluesSpigetSemVerComparator; +import tech.mcprison.prison.util.Location; /** * Custom Items 3.7.11 — New API features @@ -114,6 +115,12 @@ public Block setCustomBlockId( Block block, String customId, boolean doBlockUpda return customItemsWrapper.setCustomBlockId( block, customId, doBlockUpdate ); } + + @Override + public void setCustomBlockIdAsync( PrisonBlock prisonBlock, Location location ) { + customItemsWrapper.setCustomBlockIdAsync( prisonBlock, location ); + } + @Override public List getCustomBlockList() { diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/CustomItemsWrapper.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/CustomItemsWrapper.java index 7e714dd5b..bf6e03584 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/CustomItemsWrapper.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/CustomItemsWrapper.java @@ -2,15 +2,23 @@ import java.util.List; +import org.bukkit.scheduler.BukkitRunnable; + import com.jojodmo.customitems.api.CustomItemsAPI; import tech.mcprison.prison.internal.block.Block; +import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.block.SpigotBlock; +import tech.mcprison.prison.util.Location; public class CustomItemsWrapper { + + + private final SpigotPrison plugin; public CustomItemsWrapper() { - + this.plugin = SpigotPrison.getInstance(); } public String getCustomBlockId( Block block ) { @@ -20,14 +28,64 @@ public String getCustomBlockId( Block block ) { return null; } + /** + *

This should only be called when running in the bukkit synchronous thread. + *

+ * + * @param block + * @param customId + * @param doBlockUpdate + * @return + */ public Block setCustomBlockId( Block block, String customId, boolean doBlockUpdate ) { org.bukkit.block.Block spigotBlock = ((SpigotBlock) block).getWrapper(); - org.bukkit.block.Block resultBlock = CustomItemsAPI.setCustomItemIDAtBlock( spigotBlock, customId, doBlockUpdate ); + + // So to prevent this from causing lag, we will only get back the block with no updates + // This will allow this function to exit: + org.bukkit.block.Block resultBlock = + CustomItemsAPI.setCustomItemIDAtBlock( spigotBlock, customId, doBlockUpdate ); + return new SpigotBlock( resultBlock ); } + + + /** + *

This should only be ran through an asynchronous thread since it will submit a task + * on the bukkit synchronous thread to perform the actual update. This does not need to + * return a block. + *

+ * + * @param prisonBlock + * @param location + * @param doBlockUpdate + * @return + */ + public void setCustomBlockIdAsync( PrisonBlock prisonBlock, Location location ) + { + + new BukkitRunnable() { + @Override + public void run() { + + // No physics update: + org.bukkit.block.Block spigotBlock = ((SpigotBlock) location.getBlockAt()).getWrapper(); + //org.bukkit.block.Block spigotBlock = ((SpigotBlock) prisonBlock).getWrapper(); + + // Request the block change, but we don't need the results so ignore it +// org.bukkit.block.Block resultBlock = + CustomItemsAPI.setCustomItemIDAtBlock( spigotBlock, prisonBlock.getBlockName(), true ); + + } + }.runTaskLater( getPlugin(), 0 ); + + } public List getCustomBlockList() { return CustomItemsAPI.listBlockCustomItemIDs(); } + + public SpigotPrison getPlugin() { + return plugin; + } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotWorld.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotWorld.java index 7317dc335..b6f6f1f92 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotWorld.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotWorld.java @@ -18,7 +18,14 @@ package tech.mcprison.prison.spigot.game; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; + import org.bukkit.Bukkit; + +import tech.mcprison.prison.PrisonAPI; +import tech.mcprison.prison.integration.CustomBlockIntegration; import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.internal.World; import tech.mcprison.prison.internal.block.Block; @@ -28,10 +35,6 @@ import tech.mcprison.prison.spigot.compat.SpigotCompatibility; import tech.mcprison.prison.util.Location; -import java.util.List; -import java.util.function.Function; -import java.util.stream.Collectors; - /** * @author Faizaan A. Datoo */ @@ -90,7 +93,27 @@ public void setBlock( PrisonBlock block, int x, int y, int z ) { */ public void setBlockAsync( PrisonBlock prisonBlock, Location location ) { - SpigotCompatibility.getInstance().updateSpigotBlockAsync( prisonBlock, location ); + switch ( prisonBlock.getBlockType() ) + { + case minecraft: + + SpigotCompatibility.getInstance().updateSpigotBlockAsync( prisonBlock, location ); + + break; + + case CustomItems: + { + CustomBlockIntegration customItemsIntegration = + PrisonAPI.getIntegrationManager().getCustomBlockIntegration( prisonBlock.getBlockType() ); + + customItemsIntegration.setCustomBlockIdAsync( prisonBlock, location ); + } + + break; + + default: + break; + } } public org.bukkit.World getWrapper() { From ce76bf0787f23dc1ff896ed41c1c6d6330f6fb77 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 29 Aug 2021 22:35:50 -0400 Subject: [PATCH 027/283] Updates to the PrisonEnchant's API. Minor adjustments to work with the new API from PrisonEnchants. --- docs/changelog_v3.3.x.md | 4 ++++ prison-spigot/lib/PrisonEnchants-API-1.0.jar | Bin 2688 -> 1479 bytes .../lib/old/PrisonEnchants-API-1.0.jar | Bin 0 -> 2688 bytes .../spigot/block/OnBlockBreakEventCore.java | 7 ++++--- 4 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 prison-spigot/lib/old/PrisonEnchants-API-1.0.jar diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 3a065d93d..b23788654 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-08-29 +* **Updates to the PrisonEnchant's API.** +Minor adjustments to work with the new API from PrisonEnchants. + + * **Updates to async block updates.** Included changes to hook up the CustomItems to work with the async updates. diff --git a/prison-spigot/lib/PrisonEnchants-API-1.0.jar b/prison-spigot/lib/PrisonEnchants-API-1.0.jar index 839d83d28770b4387aa889d074886462d223107c..a5fc3fe07cbd936f49983d376ea8384faad09f01 100644 GIT binary patch delta 1007 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 Uf`fC1!^t`t*Z_b6(9YBU07Ii);{X5v literal 0 HcmV?d00001 diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index b73fad016..619e67005 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -1353,17 +1353,18 @@ protected void genericExplosiveEvent( PEExplosionEvent e, boolean monitor, boole // Need to wrap in a Prison block so it can be used with the mines: - SpigotBlock sBlock = new SpigotBlock(e.getBlock()); + SpigotBlock sBlock = new SpigotBlock(e.getBlockBroken()); SpigotPlayer sPlayer = new SpigotPlayer(e.getPlayer()); BlockEventType eventType = BlockEventType.PEExplosive; - String triggered = e.getTriggeredBy(); + String triggered = null; // e.getTriggeredBy(); - PrisonMinesBlockBreakEvent pmEvent = new PrisonMinesBlockBreakEvent( e.getBlock(), e.getPlayer(), + PrisonMinesBlockBreakEvent pmEvent = new PrisonMinesBlockBreakEvent( e.getBlockBroken(), e.getPlayer(), sBlock, sPlayer, monitor, blockEventsOnly, eventType, triggered ); pmEvent.setUnprocessedRawBlocks( e.getExplodedBlocks() ); + if ( !validateEvent( pmEvent, debugInfo ) ) { // The event has not passed validation. All logging and Errors have been recorded From fec7aaf89c0621b6dcc084f2ad6360236b8ee25e Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Mon, 30 Aug 2021 00:12:23 -0400 Subject: [PATCH 028/283] Some fixes for teleporting and the removal of the teleport glass block. --- docs/changelog_v3.3.x.md | 3 ++ .../mcprison/prison/mines/data/MineReset.java | 39 +++++++++++-------- .../mcprison/prison/mines/data/MineTasks.java | 32 +++++++++------ .../prison/mines/data/MinesConfig.java | 8 ++-- .../mines/tasks/MineChangeBlockTask.java | 35 +++++++++-------- .../prison/mines/tasks/MineTeleportTask.java | 35 +++++++++++++++++ 6 files changed, 103 insertions(+), 49 deletions(-) create mode 100644 prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MineTeleportTask.java diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index b23788654..d90130c48 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-08-29 +* **Some fixes for teleporting and the removal of the teleport glass block.** + + * **Updates to the PrisonEnchant's API.** Minor adjustments to work with the new API from PrisonEnchants. diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java index 0c0d40de2..7867757c4 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java @@ -19,12 +19,13 @@ import tech.mcprison.prison.mines.events.MineResetEvent; import tech.mcprison.prison.mines.features.MineLinerBuilder; import tech.mcprison.prison.mines.features.MineLinerBuilder.LinerPatterns; -import tech.mcprison.prison.mines.tasks.MinePagedResetAsyncTask; -import tech.mcprison.prison.mines.tasks.MinePagedResetAsyncTask.MineResetType; import tech.mcprison.prison.mines.features.MineMover; import tech.mcprison.prison.mines.features.MineTargetBlockKey; import tech.mcprison.prison.mines.features.MineTargetPrisonBlock; import tech.mcprison.prison.mines.features.MineTracerBuilder; +import tech.mcprison.prison.mines.tasks.MinePagedResetAsyncTask; +import tech.mcprison.prison.mines.tasks.MinePagedResetAsyncTask.MineResetType; +import tech.mcprison.prison.mines.tasks.MineTeleportTask; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.tasks.PrisonCommandTask; import tech.mcprison.prison.tasks.PrisonRunnable; @@ -871,7 +872,11 @@ public void asynchronouslyResetFinalize() { // If a player falls back in to the mine before it is fully done being reset, // such as could happen if there is lag or a lot going on within the server, // this will TP anyone out who would otherwise suffocate. I hope! lol - teleportAllPlayersOut(); + + MineTeleportTask teleportTask = new MineTeleportTask( (Mine) this ); + teleportTask.submitTaskSync(); + +// teleportAllPlayersOut(); // setStatsTeleport2TimeMS( // teleportAllPlayersOut( getBounds().getyBlockMax() ) ); @@ -942,7 +947,7 @@ public boolean resetAsynchonouslyInitiate() { canceled = true; } else { - long start = System.currentTimeMillis(); +// long start = System.currentTimeMillis(); // The all-important event MineResetEvent event = new MineResetEvent(this); @@ -951,20 +956,22 @@ public boolean resetAsynchonouslyInitiate() { canceled = event.isCanceled(); if (!canceled) { - try { - teleportAllPlayersOut(); -// setStatsTeleport1TimeMS( -// teleportAllPlayersOut( getBounds().getyBlockMax() ) ); - - } catch (Exception e) { - Output.get().logError("&cMineReset: Failed to TP players out of mine. mine= " + - getName(), e); - canceled = true; - } + MineTeleportTask teleportTask = new MineTeleportTask( (Mine) this ); + teleportTask.submitTaskSync(); +// try { +// teleportAllPlayersOut(); +//// setStatsTeleport1TimeMS( +//// teleportAllPlayersOut( getBounds().getyBlockMax() ) ); +// +// } catch (Exception e) { +// Output.get().logError("&cMineReset: Failed to TP players out of mine. mine= " + +// getName(), e); +// canceled = true; +// } } - long stop = System.currentTimeMillis(); - setStatsResetTimeMS( stop - start ); +// long stop = System.currentTimeMillis(); +// setStatsResetTimeMS( stop - start ); } return canceled; diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineTasks.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineTasks.java index ad0703801..4fb84298d 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineTasks.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineTasks.java @@ -9,6 +9,7 @@ import tech.mcprison.prison.mines.PrisonMines; import tech.mcprison.prison.mines.data.MineScheduler.MineJob; import tech.mcprison.prison.mines.tasks.MineChangeBlockTask; +import tech.mcprison.prison.output.Output; import tech.mcprison.prison.tasks.PrisonRunnable; import tech.mcprison.prison.tasks.PrisonTaskSubmitter; import tech.mcprison.prison.util.Location; @@ -80,7 +81,7 @@ public void submitSyncTask( PrisonRunnable callbackSync ) { * @param targetY */ @Override - protected long teleportAllPlayersOut() { + public long teleportAllPlayersOut() { long start = System.currentTimeMillis(); if ( isVirtual() ) { @@ -89,17 +90,23 @@ protected long teleportAllPlayersOut() { World world = getBounds().getCenter().getWorld(); - if ( isEnabled() && world != null ) { - List players = (world.getPlayers() != null ? world.getPlayers() : - Prison.get().getPlatform().getOnlinePlayers()); - for (Player player : players) { - if ( getBounds().withinIncludeTopBottomOfMine(player.getLocation()) ) { - - teleportPlayerOut(player); + try { + if ( isEnabled() && world != null ) { + List players = (world.getPlayers() != null ? world.getPlayers() : + Prison.get().getPlatform().getOnlinePlayers()); + for (Player player : players) { + if ( getBounds().withinIncludeTopBottomOfMine(player.getLocation()) ) { + + teleportPlayerOut(player); + } } } + } - + catch (Exception e) { + Output.get().logError("&cMineReset: Failed to TP players out of mine. mine= " + + getName(), e); + } return System.currentTimeMillis() - start; } @@ -176,8 +183,8 @@ public Location teleportPlayerOut(Player player, String targetLocation) { @Override public void submitTeleportGlassBlockRemoval() { - Location altTp = alternativeTpLocation(); - Location tpTargetLocation = isHasSpawn() ? getSpawn() : altTp; +// Location altTp = alternativeTpLocation(); + Location tpTargetLocation = isHasSpawn() ? getSpawn() : alternativeTpLocation(); Location glassBlockLocation = new Location( tpTargetLocation ); int newY = tpTargetLocation.getBlockY() - 1; @@ -185,7 +192,8 @@ public void submitTeleportGlassBlockRemoval() { MineChangeBlockTask changeBlockTask = - new MineChangeBlockTask( glassBlockLocation, PrisonBlock.AIR ); + new MineChangeBlockTask( glassBlockLocation, + PrisonBlock.AIR, PrisonBlock.GLASS ); int delayInTicks = 10; PrisonTaskSubmitter.runTaskLater( changeBlockTask, delayInTicks ); diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MinesConfig.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MinesConfig.java index 1f10b04a5..008da7dda 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MinesConfig.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MinesConfig.java @@ -47,10 +47,10 @@ public class MinesConfig implements FileIOData { // */ // public boolean multiworld = false; - /** - * True if only blocks that are air should be replaced. False otherwise - */ - public boolean fillMode = false; +// /** +// * True if only blocks that are air should be replaced. False otherwise +// */ +// public boolean fillMode = false; /** * The duration between mine resets in seconds. diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MineChangeBlockTask.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MineChangeBlockTask.java index 629e71773..8d4067692 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MineChangeBlockTask.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MineChangeBlockTask.java @@ -9,15 +9,19 @@ public class MineChangeBlockTask { private Location location; private PrisonBlock targetBlock; + private PrisonBlock checkBlock; private Location topOfMineLocation; - public MineChangeBlockTask( Location location, PrisonBlock targetBlock ) { + public MineChangeBlockTask( Location location, + PrisonBlock targetBlock, PrisonBlock checkBlock ) { super(); this.location = location; this.targetBlock = targetBlock; + this.checkBlock = checkBlock; + this.topOfMineLocation = new Location( getLocation() ); this.topOfMineLocation.setY( topOfMineLocation.getBlockY() - 1 ); @@ -26,31 +30,28 @@ public MineChangeBlockTask( Location location, PrisonBlock targetBlock ) { @Override public void run() { - if ( topOfMineLocation.getBlockAt().isEmpty() ) { - - // When there is no block under the glass block, spawn in a - // glass block so the player won't fall to their death. - // This block will be within the mine, so it will be replaced - // when the mine resets, or the players can break it too. - - topOfMineLocation.getBlockAt().setPrisonBlock( PrisonBlock.GLASS ); - } - - getLocation().getBlockAt().setPrisonBlock( getTargetBlock() ); + // Replace the targetBlock if there is no checkBlock. If there is a checkBlock, + // then make sure the block that will be replaced is that type of a block. + if ( checkBlock == null || + !topOfMineLocation.getBlockAt().isEmpty() && + getLocation().getBlockAt().getPrisonBlock().equals( getCheckBlock() ) ) { + + getLocation().getBlockAt().setPrisonBlock( getTargetBlock() ); + } } public Location getLocation() { return location; } - public void setLocation( Location location ) { - this.location = location; - } public PrisonBlock getTargetBlock() { return targetBlock; } - public void setTargetBlock( PrisonBlock targetBlock ) { - this.targetBlock = targetBlock; + + public PrisonBlock getCheckBlock() + { + return checkBlock; } + } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MineTeleportTask.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MineTeleportTask.java new file mode 100644 index 000000000..01cbeefc1 --- /dev/null +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MineTeleportTask.java @@ -0,0 +1,35 @@ +package tech.mcprison.prison.mines.tasks; + +import tech.mcprison.prison.mines.data.Mine; +import tech.mcprison.prison.tasks.PrisonRunnable; +import tech.mcprison.prison.tasks.PrisonTaskSubmitter; + +public class MineTeleportTask + implements PrisonRunnable +{ + private Mine mine; + + public MineTeleportTask( Mine mine ) { + super(); + + this.mine = mine; + } + + public void submitTaskSync() { + + + // Prevent the task from being submitted if it is a virtual mine: + if ( mine.isVirtual() ) { + return; + } + + PrisonTaskSubmitter.runTaskLater( this, 0 ); + } + + @Override + public void run() { + + mine.teleportAllPlayersOut(); + + } +} From 6b20575ab47ecf10be56a4d71dd83b56cb372f89 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Mon, 30 Aug 2021 00:20:02 -0400 Subject: [PATCH 029/283] Added a few more reporting entries on the block break handling. Reporting how many blocks are being processed and if it passes the validation phase. --- docs/changelog_v3.3.x.md | 4 ++++ .../prison/spigot/block/OnBlockBreakEventCore.java | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index d90130c48..3fca47249 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-08-29 +* **Added a few more reporting entries on the block break handling.** +Reporting how many blocks are being processed and if it passes the validation phase. + + * **Some fixes for teleporting and the removal of the teleport glass block.** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index 619e67005..b20d5ac10 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -470,6 +470,7 @@ else if ( pmEvent.getMine() != null || pmEvent.getMine() == null && private boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent, StringBuilder debugInfo ) { boolean results = true; + Long playerUUIDLSB = Long.valueOf( pmEvent.getPlayer().getUniqueId().getLeastSignificantBits() ); @@ -553,6 +554,11 @@ else if ( mine.isInMineExact( sBlock.getLocation() ) ) { } + debugInfo.append( "blocks(" ) + .append( pmEvent.getBlock() == null ? "0" : "1" ) + .append( "+" ) + .append( pmEvent.getExplodedBlocks().size() ) + .append( ") " ); if ( isToolDisabled( pmEvent.getPlayer() ) ) { @@ -630,6 +636,14 @@ else if ( pmEvent.isMonitor() && mine != null ) { results = false; } + + + if ( results ) { + debugInfo.append( "(PassedValidation) " ); + } + else { + debugInfo.append( "(ValidationFailed) " ); + } return results; From 3aafed7c1fbd6291659cb9a492606b20999979b3 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Mon, 30 Aug 2021 15:44:20 -0400 Subject: [PATCH 030/283] For the initial startup air count task, which is used to "reset" the block counts on a mine. This does not change any blocks, but just finds out where the mine was when the server was last shut down. This is needed to ensure we have valid counts for the mines before the first time they are reset. The other way to update these values is to do a full mine reset which is more costly. There was an inconclusive error that just listed "null" as the error messags, without identifying the actual line number. This error catching was changed to now generate a stack trace so it can be properly fixed if it occurs in the future. --- .../mcprison/prison/mines/data/MineReset.java | 33 ++++++++++++++----- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java index 7867757c4..c74a64005 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java @@ -1166,6 +1166,16 @@ else if ( !isUseNewBlockModel() && World world = worldOptional.get(); + if ( world == null ) { + Output.get().logError( + String.format( "MineReset: refreshAirCountAsyncTask failure: The world is invalid and " + + "cannot be located. mine= %s worldName=%s ", + getName(), getWorldName() )); + + + return; + } + // Reset the target block lists: clearMineTargetPrisonBlocks(); @@ -1210,12 +1220,14 @@ else if ( !isUseNewBlockModel() && PrisonBlock pBlock = tBlock.getPrisonBlock(); - // Increment the mine's block count. This block is one of the control blocks: - addMineTargetPrisonBlock( incrementResetBlockCount( pBlock ), x, y, z, isEdge ); - + if ( pBlock != null ) { + + // Increment the mine's block count. This block is one of the control blocks: + addMineTargetPrisonBlock( incrementResetBlockCount( pBlock ), x, y, z, isEdge ); + + } - if ( pBlock == null || - pBlock.equals( PrisonBlock.AIR ) ) { + if ( pBlock == null || pBlock.isAir() ) { airCount++; } } @@ -1223,9 +1235,12 @@ else if ( !isUseNewBlockModel() && BlockOld oBlock = new BlockOld( tBlock.getType() ); - // Increment the mine's block count. This block is one of the control blocks: - addMineTargetPrisonBlock( incrementResetBlockCount( oBlock ), x, y, z, isEdge ); - + if ( oBlock != null ) { + + // Increment the mine's block count. This block is one of the control blocks: + addMineTargetPrisonBlock( incrementResetBlockCount( oBlock ), x, y, z, isEdge ); + + } if ( tBlock.getType() == BlockType.AIR ) { airCount++; @@ -1245,7 +1260,7 @@ else if ( !isUseNewBlockModel() && "MineReset.refreshAirCountAsyncTask: Error counting air blocks: " + "Mine=%s coords=%s Error: %s ", getName(), coords, e.getMessage() ); if ( e.getMessage() != null && e.getMessage().contains( "Asynchronous entity world add" )) { - Output.get().logWarn( message ); + Output.get().logWarn( message, e ); } else { Output.get().logWarn( message, e ); } From 84a3c960454554c5c8868872caa2ecb4b0cd655e Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Mon, 30 Aug 2021 15:52:45 -0400 Subject: [PATCH 031/283] If the primary block was null, which it never should be, then this prevents a failure in this section of code in the OnBlockBreakEventCore. --- docs/changelog_v3.3.x.md | 11 ++++++++++- .../prison/spigot/block/OnBlockBreakEventCore.java | 3 ++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 3fca47249..0b1db35b3 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,16 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.1 2021-08-29 +# 3.2.11-alpha.1 2021-08-30 + + +* **If the primary block was null, which it never should be, then this prevents a failure in this section of code in the OnBlockBreakEventCore.** + + + +* **For the initial startup air count task, which is used to "reset" the block counts on a mine.** +This does not change any blocks, but just finds out where the mine was when the server was last shut down. This is needed to ensure we have valid counts for the mines before the first time they are reset. The other way to update these values is to do a full mine reset which is more costly. +There was an inconclusive error that just listed "null" as the error messags, without identifying the actual line number. This error catching was changed to now generate a stack trace so it can be properly fixed if it occurs in the future. * **Added a few more reporting entries on the block break handling.** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index b20d5ac10..78e1eb0ac 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -477,7 +477,8 @@ private boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent, StringBuilder // Get the cached mine, if it exists: Mine mine = getPlayerCache().get( playerUUIDLSB ); - if ( mine == null || !mine.isInMineExact( pmEvent.getSpigotBlock().getLocation() ) ) { + if ( mine == null || + pmEvent.getSpigotBlock() != null && !mine.isInMineExact( pmEvent.getSpigotBlock().getLocation() ) ) { // Look for the correct mine to use. // Set mine to null so if cannot find the right one it will return a null: mine = findMineLocation( pmEvent.getSpigotBlock() ); From 0f7538121595c39fabd88f290f0ba0716a146e5d Mon Sep 17 00:00:00 2001 From: AnonymousGCA Date: Mon, 30 Aug 2021 23:05:39 +0200 Subject: [PATCH 032/283] Changelogs: - Test Fix for NPE from SpigotRankManagerGUI and InventoryClickEvent. --- docs/changelog_v3.3.x.md | 4 ++++ .../spigot/gui/rank/SpigotRankManagerGUI.java | 14 +++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 3fca47249..b2cda4a94 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-08-29 +* **Trying to fix an error related to SpigotRankManager GUI:** I can't reproduce the issue but the NPE shouldn't +give a stacktrace in the console anymore. + + * **Added a few more reporting entries on the block break handling.** Reporting how many blocks are being processed and if it passes the validation phase. diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankManagerGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankManagerGUI.java index 96509e3cc..7edf28111 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankManagerGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankManagerGUI.java @@ -48,10 +48,18 @@ public void open() { RankPlayer rankPlayer = PrisonRanks.getInstance().getPlayerManager().getPlayer( new SpigotPlayer(p) ); PlayerRank pRank = rankPlayer.getRank( rank.getLadder() ); - + + + String rankCost; + try { + rankCost = PlaceholdersUtil.formattedKmbtSISize(pRank.getRankCost(), formatDecimal, ""); + } catch (NullPointerException ex){ + rankCost = "Can't get"; + } + ButtonLore editPriceLore = new ButtonLore(createLore(messages.getString("Lore.ClickToOpen")), createLore( - messages.getString("Lore.Info"), - messages.getString("Lore.Price") + PlaceholdersUtil.formattedKmbtSISize(pRank.getRankCost(), formatDecimal, ""))); + messages.getString("Lore.Info"), + messages.getString("Lore.Price") + rankCost)); ButtonLore editTagLore = new ButtonLore(createLore(messages.getString("Lore.ClickToOpen")), createLore( messages.getString("Lore.Info"), From c4fcb350cb63f27db656d38055209ae2af8ca906 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Mon, 30 Aug 2021 19:29:51 -0400 Subject: [PATCH 033/283] Update some messages to be clearer as to what they are. Removed the MONITOR from auto features since they should not have the monitor setting enabled. The blockBreakEvent has the monitoring event. --- docs/changelog_v3.3.x.md | 12 ++++++++---- .../spigot/autofeatures/AutoManagerFeatures.java | 8 ++++++-- .../prison/spigot/block/OnBlockBreakEventCore.java | 8 ++++---- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 7aebb7a17..17bb31fbd 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,14 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-08-30 +* **Update some messages to be clearer as to what they are.** +Removed the MONITOR from auto features since they should not have the monitor setting enabled. The blockBreakEvent has the monitoring event. + + +* **Trying to fix an error related to SpigotRankManager GUI:** I can't reproduce the issue but the NPE shouldn't +give a stacktrace in the console anymore. + + * **If the primary block was null, which it never should be, then this prevents a failure in this section of code in the OnBlockBreakEventCore.** @@ -25,10 +33,6 @@ This does not change any blocks, but just finds out where the mine was when the There was an inconclusive error that just listed "null" as the error messags, without identifying the actual line number. This error catching was changed to now generate a stack trace so it can be properly fixed if it occurs in the future. -* **Trying to fix an error related to SpigotRankManager GUI:** I can't reproduce the issue but the NPE shouldn't -give a stacktrace in the console anymore. - - * **Added a few more reporting entries on the block break handling.** Reporting how many blocks are being processed and if it passes the validation phase. diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java index ca5a1b462..53a55bb43 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java @@ -181,7 +181,9 @@ private boolean processAutoEvents( SpigotBlock spigotBlock, Player player, Mine if (isBoolean(AutoFeatures.isAutoManagerEnabled) && !spigotBlock.isEmpty() ) { - debugInfo.append( "(processAutoEvent) " ); + + debugInfo.append( "(doAction autoManager processAutoEvent single-block) "); + // Output.get().logInfo( "#### AutoManager.applyAutoEvents: BlockBreakEvent: :: " + mine.getName() + " " + // " blocks remaining= " + @@ -372,7 +374,9 @@ private boolean applyAutoEvents( Player player, Mine mine, SpigotItemStack itemInHand = SpigotCompatibility.getInstance() .getPrisonItemInMainHand( player ); - debugInfo.append( "(applyAutoEvents multi-blocks: " + explodedBlocks.size() ); + + debugInfo.append( "(doAction autoManager applyAutoEvents multi-blocks: " + explodedBlocks.size() + ") "); + // The explodedBlocks list have already been validated as being within the mine: boolean applyExhaustion = true; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index 78e1eb0ac..1eca4b309 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -205,7 +205,7 @@ protected void genericBlockExplodeEvent( BlastUseEvent e ) { protected void genericBlockExplodeEventAutoManager( BlastUseEvent e ) { // NOTE: If autoManager is turned off, then process only the blockEvents: boolean blockEventsOnly = !isBoolean(AutoFeatures.isAutoManagerEnabled); - genericBlastUseEvent( e, true, blockEventsOnly, true ); + genericBlastUseEvent( e, false, blockEventsOnly, true ); } @@ -237,7 +237,7 @@ protected void genericBlockExplodeEvent( PEExplosionEvent e ) { protected void genericBlockExplodeEventAutoManager( PEExplosionEvent e ) { // NOTE: If autoManager is turned off, then process only the blockEvents: boolean blockEventsOnly = !isBoolean(AutoFeatures.isAutoManagerEnabled); - genericExplosiveEvent( e, true, blockEventsOnly, true ); + genericExplosiveEvent( e, false, blockEventsOnly, true ); } @@ -271,7 +271,7 @@ protected void genericBlockExplodeEvent( ExplosiveBlockBreakEvent e ) { protected void genericBlockExplodeEventAutoManager( ExplosiveBlockBreakEvent e ) { // NOTE: If autoManager is turned off, then process only the blockEvents: boolean blockEventsOnly = !isBoolean(AutoFeatures.isAutoManagerEnabled); - genericExplosiveEvent( e, true, blockEventsOnly, true ); + genericExplosiveEvent( e, false, blockEventsOnly, true ); } @@ -1653,7 +1653,7 @@ public boolean doAction( Mine mine, Player player, List explodedBlo AutoManagerFeatures aMan = SpigotPrison.getInstance().getAutoFeatures(); - debugInfo.append( "(doAction multi-blocks: " + explodedBlocks.size() ); + debugInfo.append( "(doAction normalDrop multi-blocks: " + explodedBlocks.size() + ") "); // The explodedBlocks list have already been validated as being within the mine: boolean applyExhaustion = true; From fdf79dc76b91111d2c494851ca3e54e5fba3bfd1 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Mon, 30 Aug 2021 22:56:26 -0400 Subject: [PATCH 034/283] If the settings isPreventToolBreage is enabled, then don't allow the tool to break. --- docs/changelog_v3.3.x.md | 3 +++ .../prison/spigot/block/OnBlockBreakEventCore.java | 10 ++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 17bb31fbd..649e97998 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-08-30 +* **If the settings isPreventToolBreage is enabled, then don't allow the tool to break.** + + * **Update some messages to be clearer as to what they are.** Removed the MONITOR from auto features since they should not have the monitor setting enabled. The blockBreakEvent has the monitoring event. diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index 1eca4b309..1a6e666ab 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -2144,16 +2144,22 @@ protected void calculateAndApplyDurability(Player player, SpigotItemStack itemIn } } - if (damage > 0) { + int newDurability = durability + damage; + int remainingDurability = maxDurability - newDurability; + + if (damage > 0 && + (!isBoolean( AutoFeatures.isPreventToolBreakage ) || + isBoolean( AutoFeatures.isPreventToolBreakage ) && + remainingDurability > getInteger( AutoFeatures.preventToolBreakageThreshold ) ) ) { // Compatibility compat = SpigotPrison.getInstance().getCompatibility(); // int maxDurability = compat.getDurabilityMax( itemInHand ); // int durability = compat.getDurability( itemInHand ); - int newDurability = durability + damage; if (newDurability > maxDurability) { // Item breaks! ;( compat.breakItemInMainHand( player ); + itemInHand = null; toolBreak = true; } else { compat.setDurability( itemInHand, newDurability ); From e57f6ff3b158354c58eba7393e0808b9e28ebb23 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Tue, 31 Aug 2021 00:57:25 -0400 Subject: [PATCH 035/283] Removed the tps from the messages since they are not actually hooked up. --- .../java/tech/mcprison/prison/mines/data/MineReset.java | 4 ++-- .../prison/mines/tasks/MinePagedResetAsyncTask.java | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java index c74a64005..5fb34690e 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java @@ -359,8 +359,8 @@ public String statsMessage() { sb.append( statsMessageMineSweeper() ); - sb.append( " TPS: " ) - .append( Prison.get().getPrisonTPS().getAverageTPSFormatted() ); +// sb.append( " TPS: " ) +// .append( Prison.get().getPrisonTPS().getAverageTPSFormatted() ); return sb.toString(); } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java index aa4accb1d..16a8c1a5c 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java @@ -2,7 +2,6 @@ import java.util.List; -import tech.mcprison.prison.Prison; import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.mines.PrisonMines; import tech.mcprison.prison.mines.data.Mine; @@ -114,8 +113,10 @@ private void logStats() resetType.name() + " : page " + page + " of " + totalPages + " : " + " blocks = " + blocksPlaced + " elapsed = " + timeElapsedPage + - " ms TotalElapsed = " + timeElapsedTotal + " ms TPS " + - Prison.get().getPrisonTPS().getAverageTPSFormatted() ); + " ms TotalElapsed = " + timeElapsedTotal + " ms"// + +// " TPS " + +// Prison.get().getPrisonTPS().getAverageTPSFormatted() + ); } } From fc47ef7ddca99161cc2341a8b32257af845d1a23 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Tue, 31 Aug 2021 00:59:14 -0400 Subject: [PATCH 036/283] Replace the block with air through a task to get it out of the auto features thread. --- docs/changelog_v3.3.x.md | 5 ++- .../AutoManagerBreakBlockTask.java | 36 +++++++++++++++++++ .../autofeatures/AutoManagerFeatures.java | 14 +++++--- 3 files changed, 49 insertions(+), 6 deletions(-) create mode 100644 prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerBreakBlockTask.java diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 649e97998..7222e4c6a 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,10 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.1 2021-08-30 +# 3.2.11-alpha.1 2021-08-31 + + +* **Replace the block with air through a task to get it out of the auto features thread.** * **If the settings isPreventToolBreage is enabled, then don't allow the tool to break.** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerBreakBlockTask.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerBreakBlockTask.java new file mode 100644 index 000000000..de70fee45 --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerBreakBlockTask.java @@ -0,0 +1,36 @@ +package tech.mcprison.prison.spigot.autofeatures; + +import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.spigot.block.SpigotBlock; +import tech.mcprison.prison.tasks.PrisonRunnable; +import tech.mcprison.prison.tasks.PrisonTaskSubmitter; + +public class AutoManagerBreakBlockTask + implements PrisonRunnable +{ + private SpigotBlock block; + + public AutoManagerBreakBlockTask( SpigotBlock block ) { + super(); + + this.block = block; + } + + public static void submitTask( SpigotBlock block ) { + + AutoManagerBreakBlockTask blockTask = new AutoManagerBreakBlockTask( block ); + + PrisonTaskSubmitter.runTaskLater( blockTask, 0 ); + } + + @Override + public void run() { + +// // Set the broken block to AIR and cancel the event + if ( !block.isEmpty() ) { + block.setPrisonBlock( PrisonBlock.AIR ); + } + + } + +} diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java index 53a55bb43..b0b9b03e3 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java @@ -550,7 +550,8 @@ public int calculateNormalDrop( SpigotItemStack itemInHand, SpigotBlock block ) // Break the block and change it to air: - block.setPrisonBlock( PrisonBlock.AIR );; + AutoManagerBreakBlockTask.submitTask( block ); +// block.setPrisonBlock( PrisonBlock.AIR ); } return count; @@ -677,11 +678,14 @@ protected void autoPickupCleanup( SpigotBlock block, int count ) { // Auto pickup has been successful. Now clean up. if ( count > 0 ) { + + // submit a task to change the block to air: + AutoManagerBreakBlockTask.submitTask( block ); -// // Set the broken block to AIR and cancel the event - if ( !block.isEmpty() ) { - block.setPrisonBlock( PrisonBlock.AIR ); - } +//// // Set the broken block to AIR and cancel the event +// if ( !block.isEmpty() ) { +// block.setPrisonBlock( PrisonBlock.AIR ); +// } } } From 92f1c764263155e0fe0a6e664ce441e2310f21e1 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Tue, 31 Aug 2021 01:01:23 -0400 Subject: [PATCH 037/283] 3.2.11-alpha.1 2021-08-31 - Release the first alpha.1 --- docs/changelog_v3.3.x.md | 4 ++++ gradle.properties | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 7222e4c6a..f58a6d0fb 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-08-31 +* **3.2.11-alpha.1 2021-08-31** +- Release the first alpha.1 + + * **Replace the block with air through a task to get it out of the auto features thread.** diff --git a/gradle.properties b/gradle.properties index 7706c53f6..6937acf6b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ ## # This is actually the "correct" place to define the version for the project. ## # Used within build.gradle with ${project.version}. ## # Can be overridden on the command line: gradle -Pversion=3.2.1-alpha.3 -version=3.2.10 +version=3.2.11-alpha.1 #version=3.2.8.2 #version=3.3.0-alpha.6 From 5415f32dee6dd7b4572da7ac9816ee758d691950 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Wed, 1 Sep 2021 10:05:14 -0400 Subject: [PATCH 038/283] Fixed issue with tool's durability being cutoff right before reaching the threshold. Had to change a > to a >=. --- docs/changelog_v3.3.x.md | 4 ++++ .../mcprison/prison/spigot/block/OnBlockBreakEventCore.java | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index f58a6d0fb..79ada1ed7 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-08-31 +* **Fixed issue with tool's durability being cutoff right before reaching the threshold.** +Had to change a > to a >=. + + * **3.2.11-alpha.1 2021-08-31** - Release the first alpha.1 diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index 1a6e666ab..ed5ba8f83 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -2150,7 +2150,7 @@ protected void calculateAndApplyDurability(Player player, SpigotItemStack itemIn if (damage > 0 && (!isBoolean( AutoFeatures.isPreventToolBreakage ) || isBoolean( AutoFeatures.isPreventToolBreakage ) && - remainingDurability > getInteger( AutoFeatures.preventToolBreakageThreshold ) ) ) { + remainingDurability >= getInteger( AutoFeatures.preventToolBreakageThreshold ) ) ) { // Compatibility compat = SpigotPrison.getInstance().getCompatibility(); // int maxDurability = compat.getDurabilityMax( itemInHand ); From ad7a2627cd71f7bb296fd09dd32813483ef721b6 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Wed, 1 Sep 2021 10:06:37 -0400 Subject: [PATCH 039/283] Ran in to a situation where results was actually null. So this prevents a NPE. --- docs/changelog_v3.3.x.md | 5 ++++- .../java/tech/mcprison/prison/spigot/block/SpigotBlock.java | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 79ada1ed7..531deb4e5 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,10 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.1 2021-08-31 +# 3.2.11-alpha.1 2021-09-01 + + +* **Ran in to a situation where results was actually null. So this prevents a NPE.** * **Fixed issue with tool's durability being cutoff right before reaching the threshold.** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java index 8820bf778..de8aa83f2 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java @@ -113,7 +113,7 @@ public PrisonBlock getPrisonBlock() { results = SpigotCompatibility.getInstance().getPrisonBlock( getWrapper() ); } - if ( results.getLocation() == null && getLocation() != null ) { + if ( results != null && results.getLocation() == null && getLocation() != null ) { // Clone the block that was found in the mine. This will allow us to // set the location: results = new PrisonBlock( results ); From 67a1d4a905e21b78817c601380d7e0b3b4c50ad8 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Wed, 1 Sep 2021 10:11:33 -0400 Subject: [PATCH 040/283] Cleaned up some of the unused variables in the Utils titles command. There were plans for more commands, but they were eliminated. --- docs/changelog_v3.3.x.md | 4 ++ .../spigot/utils/PrisonUtilsModule.java | 12 ++-- .../spigot/utils/PrisonUtilsTitles.java | 62 +++++++++---------- prison-spigot/src/main/resources/modules.yml | 4 -- 4 files changed, 43 insertions(+), 39 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 531deb4e5..17344ae04 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-09-01 +* **Cleaned up some of the unused variables in the Utils titles command.** +There were plans for more commands, but they were eliminated. This will soon be rewritten to utilize XSeries's classes for these display items. + + * **Ran in to a situation where results was actually null. So this prevents a NPE.** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsModule.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsModule.java index b85a4ea4c..3306bcfc8 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsModule.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsModule.java @@ -112,11 +112,15 @@ public void enable() { PrisonUtilsTitles utils = new PrisonUtilsTitles(); utils.setEnableTitlesTitle( isEnabled( "utils.titles.title", true ) ); - utils.setEnableTitlesSubtitle( isEnabled( "utils.titles.subtitle", true ) ); +// utils.setEnableTitlesSubtitle( isEnabled( "utils.titles.subtitle", true ) ); utils.setEnableTitlesActionBar( isEnabled( "utils.titles.actionBar", true ) ); - utils.setEnableTitlesClear( isEnabled( "utils.titles.clear", true ) ); - utils.setEnableTitlesReset( isEnabled( "utils.titles.reset", true ) ); - utils.setEnableTitlesTimes( isEnabled( "utils.titles.times", true ) ); +// utils.setEnableTitlesClear( isEnabled( "utils.titles.clear", true ) ); +// utils.setEnableTitlesReset( isEnabled( "utils.titles.reset", true ) ); +// utils.setEnableTitlesTimes( isEnabled( "utils.titles.times", true ) ); + + Prison.get().getCommandHandler().registerCommands( utils ); + + } Prison.get().getCommandHandler().registerCommands( utils ); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsTitles.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsTitles.java index ae1968a7b..60bbd9cbc 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsTitles.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsTitles.java @@ -22,11 +22,11 @@ public class PrisonUtilsTitles extends PrisonUtils { private boolean enableTitlesTitle = false; - private boolean enableTitlesSubtitle = false; +// private boolean enableTitlesSubtitle = false; private boolean enableTitlesActionBar = false; - private boolean enableTitlesClear = false; - private boolean enableTitlesReset = false; - private boolean enableTitlesTimes = false; +// private boolean enableTitlesClear = false; +// private boolean enableTitlesReset = false; +// private boolean enableTitlesTimes = false; public PrisonUtilsTitles() { @@ -119,7 +119,7 @@ public void utilsTitlesActionBar( CommandSender sender, description = "The message to display in the action bar.") String message ) { - if ( !isEnableTitlesTitle() ) { + if ( !isEnableTitlesActionBar() ) { Output.get().logInfo( "Prison's utils command titles action bar is disabled in modules.yml." ); } @@ -271,12 +271,12 @@ public void setEnableTitlesTitle( boolean enableTitlesTitle ) { this.enableTitlesTitle = enableTitlesTitle; } - public boolean isEnableTitlesSubtitle() { - return enableTitlesSubtitle; - } - public void setEnableTitlesSubtitle( boolean enableTitlesSubtitle ) { - this.enableTitlesSubtitle = enableTitlesSubtitle; - } +// public boolean isEnableTitlesSubtitle() { +// return enableTitlesSubtitle; +// } +// public void setEnableTitlesSubtitle( boolean enableTitlesSubtitle ) { +// this.enableTitlesSubtitle = enableTitlesSubtitle; +// } public boolean isEnableTitlesActionBar() { return enableTitlesActionBar; @@ -285,25 +285,25 @@ public void setEnableTitlesActionBar( boolean enableTitlesActionBar ) { this.enableTitlesActionBar = enableTitlesActionBar; } - public boolean isEnableTitlesClear() { - return enableTitlesClear; - } - public void setEnableTitlesClear( boolean enableTitlesClear ) { - this.enableTitlesClear = enableTitlesClear; - } - - public boolean isEnableTitlesReset() { - return enableTitlesReset; - } - public void setEnableTitlesReset( boolean enableTitlesReset ) { - this.enableTitlesReset = enableTitlesReset; - } - - public boolean isEnableTitlesTimes() { - return enableTitlesTimes; - } - public void setEnableTitlesTimes( boolean enableTitlesTimes ) { - this.enableTitlesTimes = enableTitlesTimes; - } +// public boolean isEnableTitlesClear() { +// return enableTitlesClear; +// } +// public void setEnableTitlesClear( boolean enableTitlesClear ) { +// this.enableTitlesClear = enableTitlesClear; +// } +// +// public boolean isEnableTitlesReset() { +// return enableTitlesReset; +// } +// public void setEnableTitlesReset( boolean enableTitlesReset ) { +// this.enableTitlesReset = enableTitlesReset; +// } +// +// public boolean isEnableTitlesTimes() { +// return enableTitlesTimes; +// } +// public void setEnableTitlesTimes( boolean enableTitlesTimes ) { +// this.enableTitlesTimes = enableTitlesTimes; +// } } diff --git a/prison-spigot/src/main/resources/modules.yml b/prison-spigot/src/main/resources/modules.yml index 981e149e3..3c901935c 100644 --- a/prison-spigot/src/main/resources/modules.yml +++ b/prison-spigot/src/main/resources/modules.yml @@ -40,8 +40,4 @@ utils: titles: enabled: true title: true - subtitle: true actionBar: true - clear: true - reset: true - times: true From ef5d39860fd3fbdb08a14d9965f4ee1b8fb1536b Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Wed, 1 Sep 2021 10:25:49 -0400 Subject: [PATCH 041/283] Block turned out to be null, so check for null to prevent problems. --- .../main/java/tech/mcprison/prison/spigot/utils/BlockUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/BlockUtils.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/BlockUtils.java index 74f5aab81..0bcdc31a6 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/BlockUtils.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/BlockUtils.java @@ -44,7 +44,7 @@ public boolean isUnbreakable( SpigotBlock block ) { public boolean isUnbreakable( PrisonBlock block ) { - return block.getLocation() == null ? false : + return block == null || block.getLocation() == null ? false : getUnbreakableBlocks().containsKey( block.getLocation() ); } From ed2c9509b40cc883105453641b37319b93a5ef6f Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Wed, 1 Sep 2021 10:27:39 -0400 Subject: [PATCH 042/283] Initial setup of Prison's mine bombs. Initially it will be controllable as a utils command, so random chances can be assigned to explosions. --- docs/changelog_v3.3.x.md | 4 + .../spigot/utils/PrisonUtilsMineBombs.java | 137 ++++++++++++++++++ prison-spigot/src/main/resources/modules.yml | 4 + 3 files changed, 145 insertions(+) create mode 100644 prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 17344ae04..8a4eed3fc 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-09-01 +* **Initial setup of Prison's mine bombs.** +Initially it will be controllable as a utils command, so random chances can be assigned to explosions. + + * **Cleaned up some of the unused variables in the Utils titles command.** There were plans for more commands, but they were eliminated. This will soon be rewritten to utilize XSeries's classes for these display items. diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java new file mode 100644 index 000000000..bb3ee6f7f --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java @@ -0,0 +1,137 @@ +package tech.mcprison.prison.spigot.utils; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.Bukkit; + +import tech.mcprison.prison.commands.Arg; +import tech.mcprison.prison.commands.Command; +import tech.mcprison.prison.internal.CommandSender; +import tech.mcprison.prison.output.Output; +import tech.mcprison.prison.spigot.api.ExplosiveBlockBreakEvent; +import tech.mcprison.prison.spigot.block.SpigotBlock; +import tech.mcprison.prison.spigot.bombs.MineBombs; +import tech.mcprison.prison.spigot.game.SpigotPlayer; +import tech.mcprison.prison.spigot.game.SpigotWorld; +import tech.mcprison.prison.util.Location; + +public class PrisonUtilsMineBombs + extends PrisonUtils +{ + private boolean enableMineBombs = false; + + public PrisonUtilsMineBombs() { + super(); + + } + + /** + *

There is no initialization needed for these commands. + *

+ * + *

This function must return a value of true to indicate that this + * set of commands are enabled. If it is set to false, then these + * commands will not be registered when prison is loaded. + *

+ * + * @return + */ + @Override + protected Boolean initialize() + { + return true; + } + + @Command(identifier = "prison utils bombs", + description = "Activates a mine bomb for a given player at a specific location. " + + "The attributes of the bomb can be controlled with this command, such " + + "as shape, size, etc...", + onlyPlayers = false, + permissions = "prison.utils.bombs", + altPermissions = "prison.utils.bombs.others") + public void utilsMineBombs( CommandSender sender, + @Arg(name = "playerName", description = "Player name") String playerName, + @Arg(name = "worldCoordinates", + description = "Coordinates within the world that represents the target location " + + "of the bomb's explosion. Format:" + + "'(worldName,x,y,z)'. Use placeholder '{worldCoordinates}'") + String worldCoordinates, + + + @Arg(name = "shape", description = "Shape of Explosion. [round]", + def = "round") String shape, + @Arg(name = "radiusSize", description = "Size of Explosion in block radius. [1 though 20]", + def = "3" ) + String radiusSize + + ) { + + if ( !isEnableMineBombs() ) { + + Output.get().logInfo( "Prison's utils command mine bombs is disabled in modules.yml." ); + } + else { + + SpigotPlayer player = checkPlayerPerms( sender, playerName, + "prison.utils.bomb", "prison.utils.bomb.others" ); + + if ( player != null ) { + + if ( playerName != null && !playerName.equalsIgnoreCase( player.getName() ) ) { + // Need to shift the player's name over to the message: + + } + + + Location location = Location.decodeWorldCoordinates( worldCoordinates ); + + + + if ( location == null ) { + Output.get().logInfo( "Prison utils bomb: worldCoordinates requires a value that " + + "specifies the coordinates: '(worldName,x,y,z)'. " + + "Use placeholder '{worldCoordinates}'. Was: [%s]", + worldCoordinates ); + return; + } + + int radius = 3; + + radius = Integer.parseInt( radiusSize ); + + MineBombs mBombs = new MineBombs(); + + + SpigotWorld world = (SpigotWorld) location.getWorld(); + + List blockLocations = mBombs.calculateSphere( location, radius, false ); + List blocks = new ArrayList<>(); + + for ( Location bLocation : blockLocations ) { + SpigotBlock sBlock = (SpigotBlock) world.getBlockAt( bLocation ); + blocks.add( sBlock.getWrapper() ); + } + + + SpigotBlock targetBlock = (SpigotBlock) world.getBlockAt( location ); + + + + ExplosiveBlockBreakEvent explodeEvent = new ExplosiveBlockBreakEvent( + targetBlock.getWrapper(), player.getWrapper(), blocks ); + + Bukkit.getServer().getPluginManager().callEvent( explodeEvent ); + + } + } + } + + public boolean isEnableMineBombs() { + return enableMineBombs; + } + public void setEnableMineBombs( boolean enableMineBombs ) { + this.enableMineBombs = enableMineBombs; + } + +} diff --git a/prison-spigot/src/main/resources/modules.yml b/prison-spigot/src/main/resources/modules.yml index 3c901935c..4ada48eed 100644 --- a/prison-spigot/src/main/resources/modules.yml +++ b/prison-spigot/src/main/resources/modules.yml @@ -41,3 +41,7 @@ utils: enabled: true title: true actionBar: true + bombs: + enabled: true + bombs: true + From c93aab66208ae4fb24cf34621d1e65d21412b46c Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Wed, 1 Sep 2021 12:44:46 -0400 Subject: [PATCH 043/283] Missing the fragment for mine bombs. Did not want to commit these until they were working better. --- .../mcprison/prison/spigot/utils/PrisonUtilsModule.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsModule.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsModule.java index 3306bcfc8..1d4c78f7c 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsModule.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsModule.java @@ -121,6 +121,12 @@ public void enable() { Prison.get().getCommandHandler().registerCommands( utils ); } + + if ( isEnabled( "utils.bombs.enabled", true ) ) { + + PrisonUtilsMineBombs utils = new PrisonUtilsMineBombs(); + + utils.setEnableMineBombs( isEnabled( "utils.bombs.bombs", true ) ); Prison.get().getCommandHandler().registerCommands( utils ); From 22ebae38f762be8d2e0fbffa94cb8a9c2711ebe5 Mon Sep 17 00:00:00 2001 From: AnonymousGCA Date: Wed, 1 Sep 2021 23:13:27 +0200 Subject: [PATCH 044/283] Changelogs: - Fixed command /sellall hand not working properly. --- docs/changelog_v3.3.x.md | 3 +++ .../spigot/commands/PrisonSpigotSellAllCommands.java | 9 ++++++++- .../mcprison/prison/spigot/compat/Compatibility.java | 2 ++ .../tech/mcprison/prison/spigot/compat/Spigot110.java | 8 +++++++- .../tech/mcprison/prison/spigot/compat/Spigot113.java | 5 +++++ .../tech/mcprison/prison/spigot/compat/Spigot18.java | 8 +++++++- .../tech/mcprison/prison/spigot/compat/Spigot19.java | 7 ++++++- 7 files changed, 38 insertions(+), 4 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 8a4eed3fc..1a75e845c 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-09-01 +* **Fixed SellAll Hand not removing item:** SellAll Hand didn't work properly and got now fixed. + + * **Initial setup of Prison's mine bombs.** Initially it will be controllable as a utils command, so random chances can be assigned to explosions. diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotSellAllCommands.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotSellAllCommands.java index e88ef4aff..f3e5e5dd4 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotSellAllCommands.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotSellAllCommands.java @@ -16,8 +16,10 @@ import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.SpigotPlatform; import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.block.SpigotItemStack; import tech.mcprison.prison.spigot.compat.Compatibility; import tech.mcprison.prison.spigot.game.SpigotPlayer; +import tech.mcprison.prison.spigot.inventory.SpigotPlayerInventory; import tech.mcprison.prison.spigot.sellall.SellAllBlockData; import tech.mcprison.prison.spigot.sellall.SellAllUtil; @@ -294,7 +296,12 @@ public void sellAllSellHandCommand(CommandSender sender){ ArrayList itemStacks = new ArrayList<>(); itemStacks.add(compat.getItemInMainHand(p)); - sellAllUtil.sellAllSell(p, itemStacks, false, false, true, true, false, true, true); + itemStacks = sellAllUtil.sellAllSell(p, itemStacks, false, false, true, true, false, true, true); + if (itemStacks.isEmpty()){ + compat.setItemInMainHand(p, XMaterial.AIR.parseItem()); + } else { + compat.setItemInMainHand(p, itemStacks.get(0)); + } } public void sellAllSell(Player p){ diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Compatibility.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Compatibility.java index 0c891fec2..ca416693a 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Compatibility.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Compatibility.java @@ -57,6 +57,8 @@ public interface Compatibility public ItemStack getItemInOffHand(PlayerInventory playerInventory); public void setItemStackInMainHand( SpigotPlayerInventory inventory, SpigotItemStack itemStack ); + + public void setItemInMainHand(Player p, ItemStack itemStack); public void setItemStackInOffHand( SpigotPlayerInventory inventory, SpigotItemStack itemStack ); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot110.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot110.java index f08aba417..bee66b0a8 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot110.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot110.java @@ -1,5 +1,8 @@ package tech.mcprison.prison.spigot.compat; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + /** * Important note: Spigot 1.10 support is represented in Spigot110 and is * identical to Spigot19 except for two spigot 1.10 functions: sendTitle() @@ -11,7 +14,10 @@ public class Spigot110 extends Spigot110Player implements Compatibility { - + @Override + public void setItemInMainHand(Player p, ItemStack itemStack){ + p.getInventory().setItemInMainHand(itemStack); + } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113.java index 9fa5562de..50b260f85 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113.java @@ -71,6 +71,11 @@ public void setItemStackInMainHand( SpigotPlayerInventory inventory, SpigotItemS ((org.bukkit.inventory.PlayerInventory) inventory.getWrapper()) .setItemInMainHand( itemStack.getBukkitStack() ); } + + @Override + public void setItemInMainHand(Player p, ItemStack itemStack){ + p.getInventory().setItemInMainHand(itemStack); + } @Override public void setItemStackInOffHand( SpigotPlayerInventory inventory, SpigotItemStack itemStack ) { diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18.java index 4061d664e..c22439a8b 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18.java @@ -93,7 +93,13 @@ public void setItemStackInMainHand( SpigotPlayerInventory inventory, SpigotItemS ((org.bukkit.inventory.PlayerInventory) inventory.getWrapper()) .setItemInHand( itemStack.getBukkitStack() ); } - + + @SuppressWarnings("deprecation") + @Override + public void setItemInMainHand(Player p, ItemStack itemStack) { + p.getInventory().setItemInHand(itemStack); + } + /** * Spigot v1.8 does not have an off hand, so set it to main hand. */ diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot19.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot19.java index efc6757fe..018c72b46 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot19.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot19.java @@ -94,7 +94,12 @@ public void setItemStackInMainHand( SpigotPlayerInventory inventory, SpigotItemS ((org.bukkit.inventory.PlayerInventory) inventory.getWrapper()) .setItemInMainHand( itemStack.getBukkitStack() ); } - + + @Override + public void setItemInMainHand(Player p, ItemStack itemStack) { + p.getInventory().setItemInMainHand(itemStack); + } + @Override public void setItemStackInOffHand( SpigotPlayerInventory inventory, SpigotItemStack itemStack ) { From d64e449dd29b7c985ea7302670006f3fb8048617 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Thu, 2 Sep 2021 01:07:40 -0400 Subject: [PATCH 045/283] Updates to the Prison's explosion event handling to correct a few problems. --- .../prison/autofeatures/AutoFeaturesFileConfig.java | 3 ++- .../mcprison/prison/mines/features/MineBlockEvent.java | 1 + .../prison/spigot/block/OnBlockBreakEventCore.java | 10 +++++----- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java index f319e0477..e236f8faa 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java +++ b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java @@ -236,7 +236,8 @@ public enum AutoFeatures { isDebugSupressOnBlockBreakEventCancels(debug, false), isDebugSupressOnTEExplodeEventCancels(debug, false), isDebugSupressOnCEBlastUseEventCancels(debug, false), - isDebugSupressOnPEExplosiveEventCancels(debug, false) + isDebugSupressOnPEExplosiveEventCancels(debug, false), + isDebugSupressOnPrisonMinesBlockBreakEventCancels(debug, false) ; diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineBlockEvent.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineBlockEvent.java index 2af3b66d9..f03fcf63e 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineBlockEvent.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineBlockEvent.java @@ -33,6 +33,7 @@ public enum BlockEventType { TEXplosion, CEXplosion, PEExplosive, // PrisonEnchant: Pulsi_'s plugin + PrisonExplosion, eventTypeAll( all ), eventBlockBreak( blockBreak ), diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index ed5ba8f83..4f0b6d14f 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -1464,14 +1464,14 @@ protected void genericExplosiveEvent( ExplosiveBlockBreakEvent e, boolean monito if ( !monitor && !e.isCancelled() || monitor ) { - boolean isPEExplosiveEnabled = isBoolean( AutoFeatures.isProcessPrisonEnchantsExplosiveEvents ); + boolean isPPrisonExplosiveBlockBreakEnabled = isBoolean( AutoFeatures.isProcessPrisons_ExplosiveBlockBreakEvents ); // Need to wrap in a Prison block so it can be used with the mines: SpigotBlock sBlock = new SpigotBlock(e.getBlock()); SpigotPlayer sPlayer = new SpigotPlayer(e.getPlayer()); - BlockEventType eventType = BlockEventType.PEExplosive; + BlockEventType eventType = BlockEventType.PrisonExplosion; String triggered = e.getTriggeredBy(); PrisonMinesBlockBreakEvent pmEvent = new PrisonMinesBlockBreakEvent( e.getBlock(), e.getPlayer(), @@ -1493,7 +1493,7 @@ protected void genericExplosiveEvent( ExplosiveBlockBreakEvent e, boolean monito // now process all blocks (non-monitor): - else if ( isPEExplosiveEnabled && + else if ( isPPrisonExplosiveBlockBreakEnabled && ( pmEvent.getMine() != null || pmEvent.getMine() == null && !isBoolean( AutoFeatures.pickupLimitToMines )) ) { if ( pmEvent.getExplodedBlocks().size() > 0 ) { @@ -1509,9 +1509,9 @@ else if ( isPEExplosiveEnabled && else { if ( doAction( pmEvent.getMine(), e.getPlayer(), pmEvent.getExplodedBlocks(), - BlockEventType.PEExplosive, triggered, debugInfo ) ) { + BlockEventType.PrisonExplosion, triggered, debugInfo ) ) { - if ( !isBoolean( AutoFeatures.isDebugSupressOnPEExplosiveEventCancels ) ) { + if ( !isBoolean( AutoFeatures.isDebugSupressOnPrisonMinesBlockBreakEventCancels ) ) { e.setCancelled( true ); } From f3fb4a2dd9841a03fe5438849627a9bd86d733ad Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Thu, 2 Sep 2021 01:10:41 -0400 Subject: [PATCH 046/283] Adjustments to the BlockEvents and how it handles some of the event types. Expanded and fixed some of the settings for prison's explosions, and PE's too. Added the ability to exclude specfic triggers. --- .../prison/mines/commands/MinesCommands.java | 57 ++++++++++++---- .../prison/mines/features/MineBlockEvent.java | 67 ++++++++++++++----- 2 files changed, 95 insertions(+), 29 deletions(-) diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java index eb768b057..f34a8b65a 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java @@ -65,8 +65,8 @@ import tech.mcprison.prison.tasks.PrisonCommandTask.TaskMode; import tech.mcprison.prison.tasks.PrisonTaskSubmitter; import tech.mcprison.prison.util.Bounds; -import tech.mcprison.prison.util.JumboTextFont; import tech.mcprison.prison.util.Bounds.Edges; +import tech.mcprison.prison.util.JumboTextFont; import tech.mcprison.prison.util.Text; /** @@ -3533,7 +3533,8 @@ public void blockEventEventType(CommandSender sender, @Arg(name = "row") Integer row, @Arg(name = "eventType", def = "all", description = "EventType to trigger BlockEvent: " + - "[all, blockBreak, TEXplosion, CEXplosion]" + "[all, blockBreak, PrisonExplosion, PEExplosive, " + + "TEXplosion, CEXplosion]" ) String eventType ) { @@ -3580,6 +3581,14 @@ public void blockEventEventType(CommandSender sender, BlockEventType eTypeOld = blockEvent.getEventType(); blockEvent.setEventType( eType ); + + // If the event type does not support triggered, then set triggered to null: + if ( eType != BlockEventType.PrisonExplosion && + eType != BlockEventType.TEXplosion && + eType != BlockEventType.PEExplosive ) { + + blockEvent.setTriggered( null ); + } pMines.getMineManager().saveMine( m ); @@ -3600,13 +3609,21 @@ public void blockEventEventType(CommandSender sender, } - @Command(identifier = "mines blockEvent triggered", description = "Edits a BlockBreak triggered value.", + @Command(identifier = "mines blockEvent triggered", + description = "Edits a BlockBreak triggered value. The event's triggered value will " + + "identify which enchantment fired the explosion event. For example, 'laser' " + + "or 'nuked'. Provide the enchantment name to filter on that event type, or " + + "prefix it with '!' to exclude that event type. " + + " The use of this field is only supported by TokenEnchant, " + + "Prison's own Explosion Evennt, and Pulsi_'s PrisonEnchants' explosion events. " + + "Requires TokenEnchant v18.11.0 or newer.", onlyPlayers = false, permissions = "mines.set") public void blockEventTriggered(CommandSender sender, @Arg(name = "mineName") String mineName, @Arg(name = "row") Integer row, @Arg(name = "triggered", def = "none", - description = "TE Explosion Triggered sources. Requires TokenEnchant v18.11.0 or newer. [none, ...]" + description = "The enchantment that Triggered the explosion event. Use 'none' to " + + "remove it. [none, ...]" ) String triggered ) { @@ -3643,11 +3660,17 @@ public void blockEventTriggered(CommandSender sender, MineBlockEvent blockEvent = m.getBlockEvents().get( row - 1 ); + BlockEventType eType = blockEvent.getEventType(); - if ( blockEvent.getEventType() != BlockEventType.TEXplosion && triggered != null && + if ( eType != BlockEventType.PrisonExplosion && + eType != BlockEventType.TEXplosion && + eType != BlockEventType.PEExplosive && + triggered != null && !"none".equalsIgnoreCase( triggered ) ) { - sender.sendMessage( "&7Notice: triggered is only valid exclusivly for eventTEXplosion. " + - "Defaulting to none." ); + + sender.sendMessage( "&7Notice: triggered is only valid with " + + "PrisonExplosion, TEXplosion, or PEExplosive. " + + "Defaulting to 'none'." ); triggered = null; } if ( triggered != null && "none".equalsIgnoreCase( triggered ) ) { @@ -3662,13 +3685,21 @@ public void blockEventTriggered(CommandSender sender, pMines.getMineManager().saveMine( m ); - Output.get().sendInfo(sender, "&7BlockEvent triggered &b%s&7 was changed for mine '&b%s&7'. " + - "Was &b%s&7. Command '&b%s&7'", - (triggered == null ? "none" : triggered), - m.getTag(), - (oldTriggered == null ? "none" : oldTriggered), - blockEvent.getCommand() ); + sender.sendMessage( + String.format( "&7BlockEvent triggered &b%s&7 was changed for mine '&b%s&7'. " + + "Was &b%s&7. Command '&b%s&7'", + (triggered == null ? "none" : triggered), + m.getTag(), + (oldTriggered == null ? "none" : oldTriggered), + blockEvent.getCommand()) ); + if ( triggered.startsWith( "!" ) ) { + sender.sendMessage( + String.format( "BlockEvent triggered is negated to exclude triggered " + + "events of '%s'.", + triggered.replace( "!", "" ))); + + } // Redisplay the event list: blockEventList( sender, mineName ); diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineBlockEvent.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineBlockEvent.java index f03fcf63e..5a2fa2648 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineBlockEvent.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineBlockEvent.java @@ -336,28 +336,63 @@ public boolean removePrisonBlock( Integer rowBlockName ) { * @return */ public boolean isFireEvent( double chance, BlockEventType eventType, - MineTargetPrisonBlock targetBlock, String triggered ) { + MineTargetPrisonBlock targetBlock, String triggered ) { boolean results = false; - // First check chance, since that's perhaps the quickest check: + + // First check the chance and ensure the block is valid: if ( chance <= getChance() && + isValidBlock( targetBlock ) ) { + + // If the eventType is valid: + if ( getEventType() == BlockEventType.all || + getEventType() == eventType ) { - isValidBlock( targetBlock ) && - - // Make sure we have the correct eventTypes: - (eventType == BlockEventType.TEXplosion && - eventType == getEventType() && - ( getTriggered() == null || - getTriggered().equalsIgnoreCase( triggered )) || + // check if triggered and if valid eventTypes to support it: + if ( getTriggered() == null ) { + results = true; + } + else if ( getTriggered() != null && + (eventType == BlockEventType.PrisonExplosion || + eventType == BlockEventType.TEXplosion || + eventType == BlockEventType.PEExplosive) + ) { - getEventType() == BlockEventType.all || - getEventType() == eventType) ) { - - // The check for the player's perms will have to be done outside of this - // function. - - results = true; + // triggered can be negated to be used to exclude a triggered event + boolean notTriggered = getTriggered().startsWith( "!" ); + String trig = getTriggered().replace( "!", "" ); + + if ( !notTriggered && trig.equalsIgnoreCase( triggered ) || + notTriggered && !trig.equalsIgnoreCase( triggered ) ) { + + results = true; + } + + } + + } } + + +// // First check chance, since that's perhaps the quickest check: +// if ( chance <= getChance() && +// +// isValidBlock( targetBlock ) && +// +// // Make sure we have the correct eventTypes: +// (eventType == BlockEventType.TEXplosion && +// eventType == getEventType() && +// ( getTriggered() == null || +// getTriggered().equalsIgnoreCase( triggered )) || +// +// getEventType() == BlockEventType.all || +// getEventType() == eventType) ) { +// +// // The check for the player's perms will have to be done outside of this +// // function. +// +// results = true; +// } return results; From fea67b072ea4b4ec529107400816c4b3ad60649a Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Thu, 2 Sep 2021 01:13:18 -0400 Subject: [PATCH 047/283] Added the trigger "minebombs" for the utils command bombs. --- docs/changelog_v3.3.x.md | 13 ++++++++++++- .../prison/spigot/utils/PrisonUtilsMineBombs.java | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 1a75e845c..7f847d4c7 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,18 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.1 2021-09-01 +# 3.2.11-alpha.1 2021-09-02 + + +* **Added the trigger "minebombs" for the utils command bombs.** + + +* **Adjustments to the BlockEvents and how it handles some of the event types.** +Expanded and fixed some of the settings for prison's explosions, and PE's too. +Added the ability to exclude specfic triggers. + + +* **Updates to the Prison's explosion event handling to correct a few problems. ** * **Fixed SellAll Hand not removing item:** SellAll Hand didn't work properly and got now fixed. diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java index bb3ee6f7f..8404aa488 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java @@ -120,6 +120,7 @@ public void utilsMineBombs( CommandSender sender, ExplosiveBlockBreakEvent explodeEvent = new ExplosiveBlockBreakEvent( targetBlock.getWrapper(), player.getWrapper(), blocks ); + explodeEvent.setTriggeredBy( "minebombs" ); Bukkit.getServer().getPluginManager().callEvent( explodeEvent ); From 6691586b09feae63481a99477dbc464482f6ceea Mon Sep 17 00:00:00 2001 From: AnonymousGCA Date: Mon, 6 Sep 2021 22:35:45 +0200 Subject: [PATCH 048/283] Changelogs: - .properties file now got updated for Spigot and uses all the lores got moved into it and removed from the old .yml language file. Lores may have some defects as they aren't fully mature, but already working. --- docs/changelog_v3.3.x.md | 4 + .../resources/lang/spigot/en_US.properties | 123 ++++++++++++- .../mcprison/prison/spigot/SpigotPrison.java | 15 +- .../PrisonSpigotPrestigeCommands.java | 14 +- .../commands/PrisonSpigotSellAllCommands.java | 3 - .../prison/spigot/configs/MessagesConfig.java | 131 -------------- .../spigot/configs/NewMessagesConfig.java | 167 ++++++++++++++++++ .../spigot/gui/ListenersPrisonManager.java | 8 +- .../prison/spigot/gui/PrisonSetupGUI.java | 24 +-- .../prison/spigot/gui/SpigotPrisonGUI.java | 13 +- .../gui/autofeatures/SpigotAutoBlockGUI.java | 56 +++--- .../autofeatures/SpigotAutoFeaturesGUI.java | 81 +++------ .../gui/autofeatures/SpigotAutoPickupGUI.java | 61 +++---- .../gui/autofeatures/SpigotAutoSmeltGUI.java | 21 +-- .../gui/backpacks/BackpacksAdminGUI.java | 7 +- .../gui/backpacks/BackpacksAdminListGUI.java | 17 +- .../BackpacksAdminPlayerListGUI.java | 5 +- .../gui/backpacks/BackpacksListPlayerGUI.java | 13 +- .../spigot/gui/guiutility/ButtonLore.java | 4 +- .../gui/guiutility/SpigotGUIComponents.java | 17 ++ .../spigot/gui/mine/SpigotBlocksListGUI.java | 7 +- .../gui/mine/SpigotBlocksMineListGUI.java | 7 +- .../mine/SpigotMineBlockPercentageGUI.java | 31 ++-- .../spigot/gui/mine/SpigotMineInfoGUI.java | 64 +++---- .../mine/SpigotMineNotificationRadiusGUI.java | 13 +- .../gui/mine/SpigotMineNotificationsGUI.java | 17 +- .../gui/mine/SpigotMineResetTimeGUI.java | 9 +- .../spigot/gui/mine/SpigotMinesBlocksGUI.java | 17 +- .../gui/mine/SpigotMinesConfirmGUI.java | 9 +- .../spigot/gui/mine/SpigotMinesGUI.java | 36 ++-- .../spigot/gui/mine/SpigotPlayerMinesGUI.java | 7 +- .../gui/rank/SpigotConfirmPrestigeGUI.java | 15 +- .../spigot/gui/rank/SpigotLaddersGUI.java | 7 +- .../gui/rank/SpigotPlayerPrestigesGUI.java | 9 +- .../spigot/gui/rank/SpigotPlayerRanksGUI.java | 5 +- .../spigot/gui/rank/SpigotRankManagerGUI.java | 27 +-- .../spigot/gui/rank/SpigotRankPriceGUI.java | 9 +- .../gui/rank/SpigotRankUPCommandsGUI.java | 9 +- .../spigot/gui/rank/SpigotRanksGUI.java | 33 ++-- .../gui/sellall/SellAllAdminAutoSellGUI.java | 13 +- .../gui/sellall/SellAllAdminBlocksGUI.java | 13 +- .../spigot/gui/sellall/SellAllAdminGUI.java | 43 ++--- .../spigot/gui/sellall/SellAllDelayGUI.java | 7 +- .../spigot/gui/sellall/SellAllPlayerGUI.java | 9 +- .../SellAllPrestigesMultiplierGUI.java | 17 +- .../SellAllPrestigesSetMultiplierGUI.java | 9 +- .../spigot/gui/sellall/SellAllPriceGUI.java | 9 +- .../prison/spigot/sellall/SellAllUtil.java | 2 +- 48 files changed, 707 insertions(+), 530 deletions(-) create mode 100644 prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/NewMessagesConfig.java diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 7f847d4c7..71963d39b 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-09-02 +* **Moved all Lores to the new .properties Language file:** Changes to the old .yml language file about Lore messages +won't take effect, only if you edit the .properties file they will. + + * **Added the trigger "minebombs" for the utils command bombs.** diff --git a/prison-core/src/main/resources/lang/spigot/en_US.properties b/prison-core/src/main/resources/lang/spigot/en_US.properties index 444d11ae0..fba061e0e 100644 --- a/prison-core/src/main/resources/lang/spigot/en_US.properties +++ b/prison-core/src/main/resources/lang/spigot/en_US.properties @@ -49,11 +49,128 @@ ## /prison support submit. ## - -messages__version=1 +messages__version=3 messages__auto_refresh=true +## Click to do something +spigot_gui_lore_click_to_add=Click to add. +spigot_gui_lore_click_to_add_backpack=Click to add a Backpack. +spigot_gui_lore_click_to_cancel=Click to cancel. +spigot_gui_lore_click_to_close=Click to close. +spigot_gui_lore_click_to_confirm=Click to confirm. +spigot_gui_lore_click_to_decrease=Click to decrease. +spigot_gui_lore_click_to_delete=Click to delete. +spigot_gui_lore_click_to_disable=Click to disable. +spigot_gui_lore_click_to_edit=Click to edit. +spigot_gui_lore_click_to_enable=Click to enable. +spigot_gui_lore_click_to_increase=Click to increase. +spigot_gui_lore_click_to_manage_rank=Click to manage Rank. +spigot_gui_lore_click_to_open=Click to open. +spigot_gui_lore_click_to_rankup=Click to Rankup. +spigot_gui_lore_click_to_rename=Click to rename. +spigot_gui_lore_click_to_select=Click to select. +spigot_gui_lore_click_to_start_block_setup=Click to add a block. +spigot_gui_lore_click_to_teleport=Click to teleport. +spigot_gui_lore_click_to_use=Click to use. + +## Left-Click to do something. +spigot_gui_lore_click_left_to_confirm=Left-Click to confirm. +spigot_gui_lore_click_left_to_reset=Left-Click to reset. +spigot_gui_lore_click_left_to_open=Left-Click to open. +spigot_gui_lore_click_left_to_edit=Left-Click to edit. + +## Right-Click to do something. +spigot_gui_lore_click_right_to_cancel=Right-Click to cancel. +spigot_gui_lore_click_right_to_delete=Right-Click to delete. +spigot_gui_lore_click_right_to_disable=Right-Click to disable. +spigot_gui_lore_click_right_to_enable=Right-Click to enable. +spigot_gui_lore_click_right_to_toggle=Right-Click to toggle. + +## Shift and Right-Click to do something +spigot_gui_lore_click_right_and_shift_to_delete=Shift and Right-Click to delete. +spigot_gui_lore_click_right_and_shift_to_disable=Shift and Right-Click to disable. +spigot_gui_lore_click_right_and_shift_to_toggle=Shift and Right-Click to toggle. + +## Titles or data naming. +spigot_gui_lore_backpack_id=Backpack ID: +spigot_gui_lore_blocks=Blocks: +spigot_gui_lore_blocktype=Blocktype: +spigot_gui_lore_chance=Chance: +spigot_gui_lore_command=Command: +spigot_gui_lore_currency=Currency: +spigot_gui_lore_delay=Delay: +spigot_gui_lore_id=ID: +spigot_gui_lore_info=Info: +spigot_gui_lore_minename=Minename: +spigot_gui_lore_multiplier=Multiplier: +spigot_gui_lore_name=Name: +spigot_gui_lore_owner=Owner: +spigot_gui_lore_percentage=Percentage: +spigot_gui_lore_permission=Permission: +spigot_gui_lore_players_at_rank=Players at rank: +spigot_gui_lore_prestige_name=Prestige name: +spigot_gui_lore_price=Price: +spigot_gui_lore_radius=Radius: +spigot_gui_lore_rank_tag=Rank Tag: +spigot_gui_lore_reset_time=Reset time(s): +spigot_gui_lore_size=Size: +spigot_gui_lore_show_item=Show Item: +spigot_gui_lore_spawnpoint=Spawnpoint: +spigot_gui_lore_volume=Volume: +spigot_gui_lore_value=Value: +spigot_gui_lore_world=World: + +## Simple actions or status. +spigot_gui_lore_disabled=Disabled. +spigot_gui_lore_enabled=Enabled. +spigot_gui_lore_locked=Locked! +spigot_gui_lore_next_page=Next page. +spigot_gui_lore_prior_page=Prior page. +spigot_gui_lore_rankup=Rankup. +spigot_gui_lore_selected=Selected. +spigot_gui_lore_unlocked=Unlocked! + +## Descriptions. +spigot_gui_lore_add_backpack_instruction_1=Please add at least one item +spigot_gui_lore_add_backpack_instruction_2=If you don't, the Backpack +spigot_gui_lore_add_backpack_instruction_3=Won't be saved. +spigot_gui_lore_prestige_warning_1=Prestige will reset: +spigot_gui_lore_prestige_warning_2=- Rank. +spigot_gui_lore_prestige_warning_3=- Balance. +spigot_gui_lore_ranks_setup_1=There aren't Ranks! +spigot_gui_lore_ranks_setup_2=If you want continue the setup. +spigot_gui_lore_ranks_setup_3=All Ranks and Mines from A to Z will be made +spigot_gui_lore_ranks_setup_4=With &adefault &3values! +spigot_gui_lore_ranks_setup_5=You can also use: +spigot_gui_lore_ranks_setup_6=&1/ranks autoConfigure full ! +spigot_gui_lore_ranks_setup_7=&3Please replace the X with the starting price and +spigot_gui_lore_ranks_setup_8=&3multiplier, default price = 50000, multiplier = 1.5. +spigot_gui_lore_sellall_delay_use_1=Short delay before using again +spigot_gui_lore_sellall_delay_use_2=the &3/sellall sell &8command. +spigot_gui_lore_set_mine_delay_instruction_1=Set a mine's delay +spigot_gui_lore_set_mine_delay_instruction_2=before reset when it +spigot_gui_lore_set_mine_delay_instruction_3=reaches zero blocks. +spigot_gui_lore_show_item_description_1=This's the item +spigot_gui_lore_show_item_description_2=shown in the Player's GUI +spigot_gui_lore_show_item_description_3=or /mines GUI. +spigot_gui_lore_skip_reset_instruction_1=Skip the reset if +spigot_gui_lore_skip_reset_instruction_2=not enough blocks +spigot_gui_lore_skip_reset_instruction_3=have been mined. -spigot___= +## Button names or single line descriptions. +spigot_gui_lore_autofeatures_button_description=Manage AutoFeatures. +spigot_gui_lore_backpacks_button_description=Manage BackPacks. +spigot_gui_lore_disable_notifications=Disable notifications. +spigot_gui_lore_enable_radius_mode=Enable Radius mode. +spigot_gui_lore_enable_within_mode=Enable Within mode. +spigot_gui_lore_mines_button_description=Manage Mines. +spigot_gui_lore_no_multipliers=[!] There aren't multipliers! +spigot_gui_lore_ranks_button_description=Ranks GUI manager. +spigot_gui_lore_rankup_if_enough_money=If you have enough money. +spigot_gui_lore_sellall_button_description=Manage SellAll. +spigot_gui_lore_sellall_edit_info=Edit SellAll Currency. +spigot_gui_lore_tp_to_mine=Click to teleport to Mine. +## Messages +spigot_message_missing_permission=Sorry, You don't have the permission to use that! diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPrison.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPrison.java index 1fc10086e..70935316e 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPrison.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPrison.java @@ -73,10 +73,7 @@ import tech.mcprison.prison.spigot.commands.PrisonSpigotSellAllCommands; import tech.mcprison.prison.spigot.compat.Compatibility; import tech.mcprison.prison.spigot.compat.SpigotCompatibility; -import tech.mcprison.prison.spigot.configs.BackpacksConfig; -import tech.mcprison.prison.spigot.configs.GuiConfig; -import tech.mcprison.prison.spigot.configs.MessagesConfig; -import tech.mcprison.prison.spigot.configs.SellAllConfig; +import tech.mcprison.prison.spigot.configs.*; import tech.mcprison.prison.spigot.customblock.CustomItems; import tech.mcprison.prison.spigot.economies.EssentialsEconomy; import tech.mcprison.prison.spigot.economies.GemsEconomy; @@ -118,7 +115,8 @@ public class SpigotPrison private AutoManagerFeatures autoFeatures = null; // private FileConfiguration autoFeaturesConfig = null; - + + private NewMessagesConfig newMessagesConfig; private MessagesConfig messagesConfig; private GuiConfig guiConfig; private SellAllConfig sellAllConfig; @@ -403,6 +401,13 @@ public FileConfiguration getMessagesConfig() { return messagesConfig.getFileGuiMessagesConfig(); } + public NewMessagesConfig getNewMessagesConfig(){ + if (newMessagesConfig == null){ + newMessagesConfig = NewMessagesConfig.get(); + } + return newMessagesConfig; + } + public FileConfiguration getBackpacksConfig() { if (backpacksConfig == null){ backpacksConfig = new BackpacksConfig(); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotPrestigeCommands.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotPrestigeCommands.java index 9da1d7658..9200d6062 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotPrestigeCommands.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotPrestigeCommands.java @@ -14,6 +14,7 @@ import tech.mcprison.prison.ranks.data.RankLadder; import tech.mcprison.prison.ranks.managers.LadderManager; import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.gui.ListenersPrisonManager; import tech.mcprison.prison.spigot.gui.rank.SpigotConfirmPrestigeGUI; @@ -118,16 +119,15 @@ private void prestigeByChat(CommandSender sender) { ListenersPrisonManager listenersPrisonManager = ListenersPrisonManager.get(); listenersPrisonManager.chatEventActivator(); + NewMessagesConfig newMessages = SpigotPrison.getInstance().getNewMessagesConfig(); - sender.sendMessage( SpigotPrison.format(getPrisonConfig("Lore.PrestigeWarning") + - getPrisonConfig("Lore.PrestigeWarning2") + - getPrisonConfig("Lore.PrestigeWarning3"))); - - sender.sendMessage( SpigotPrison.format(messages.getString("Message.ConfirmPrestige"))); - sender.sendMessage( SpigotPrison.format(messages.getString("Message.CancelPrestige"))); + Output.get().sendInfo(sender, newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_prestige_warning_1) + " " + + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_prestige_warning_2) + " " + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_prestige_warning_3)); - final Player player = getSpigotPlayer( sender ); + Output.get().sendInfo(sender, messages.getString("Message.ConfirmPrestige")); + Output.get().sendInfo(sender, messages.getString("Message.CancelPrestige")); + final Player player = getSpigotPlayer( sender ); listenersPrisonManager.chatInteractData(player, ListenersPrisonManager.ChatMode.Prestige); } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotSellAllCommands.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotSellAllCommands.java index f3e5e5dd4..022843241 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotSellAllCommands.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotSellAllCommands.java @@ -16,15 +16,12 @@ import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.SpigotPlatform; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.block.SpigotItemStack; import tech.mcprison.prison.spigot.compat.Compatibility; import tech.mcprison.prison.spigot.game.SpigotPlayer; -import tech.mcprison.prison.spigot.inventory.SpigotPlayerInventory; import tech.mcprison.prison.spigot.sellall.SellAllBlockData; import tech.mcprison.prison.spigot.sellall.SellAllUtil; import java.util.ArrayList; -import java.util.Collection; /** * @author GABRYCA diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/MessagesConfig.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/MessagesConfig.java index ab85f886d..f6473f621 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/MessagesConfig.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/MessagesConfig.java @@ -65,137 +65,6 @@ private void dataConfig(String key, boolean value){ // All the strings should be here private void values(){ - dataConfig("Lore.ActivateWithinMode","&8Activate Within mode."); - dataConfig("Lore.ActivateRadiusMode","&8Activate Radius mode."); - dataConfig("Lore.AutoPickupGuiManager","&8AutoPickup Manager."); - dataConfig("Lore.AutoSmeltGuiManager","&8AutoSmelt Manager."); - dataConfig("Lore.AutoBlockGuiManager","&8AutoBlock Manager."); - dataConfig("Lore.BlockType","&3BlockType: "); - dataConfig("Lore.Blocks","&3Blocks:"); - dataConfig("Lore.Blocks2","&8Manage blocks of the Mine."); - dataConfig("Lore.BackpackID", "&3Backpack ID: "); - dataConfig("Lore.ClickToAddBackpack", "&8Click to add backpack."); - dataConfig("Lore.ClickToAddBackpackInst0", "&3Instructions: "); - dataConfig("Lore.ClickToAddBackpackInst1", "&8Remember to add an item"); - dataConfig("Lore.ClickToAddBackpackInst2", "&8Inside the backpack to"); - dataConfig("Lore.ClickToAddBackpackInst3", "&8Save it"); - dataConfig("Lore.ClickToChoose","&8Click to choose."); - dataConfig("Lore.ClickToConfirm","&8Click to confirm."); - dataConfig("Lore.ClickToCancel","&8Click to cancel."); - dataConfig("Lore.ClickToDecrease","&8Click to decrease."); - dataConfig("Lore.ClickToIncrease","&8Click to increase."); - dataConfig("Lore.ClickToManageRank","&8Manage this rank."); - dataConfig("Lore.ClickToManageCommands","&8Manage RankUPCommands."); - dataConfig("Lore.ClickToOpen","&8Click to open."); - dataConfig("Lore.ClickToOpenBackpack", "&8Click to open Prison Backpack."); - dataConfig("Lore.ClickToRename", "&8Click to rename."); - dataConfig("Lore.ClickToTeleport","&8Click to teleport."); - dataConfig("Lore.ClickToUse","&8Click to use."); - dataConfig("Lore.ClickToRankup","&8Click to rankup"); - dataConfig("Lore.ClickToEditBlock", "&8Click to edit percentage."); - dataConfig("Lore.ClickToEdit", "&8Click to edit."); - dataConfig("Lore.ClickToClose", "&8Click to close the GUI."); - dataConfig("Lore.ClickToPriorPage", "&aClick to see the prior page."); - dataConfig("Lore.ClickToNextPage", "&aClick to see the next page."); - dataConfig("Lore.ClickToStartBlockSetup", "&aClick to setup block."); - dataConfig("Lore.ClickToSelect", "&7Click to select."); - dataConfig("Lore.ClickToAddBlock", "&aClick to add a block."); - dataConfig("Lore.ClickToEnable", "&aClick to enable."); - dataConfig("Lore.ClickToDisable", "&cClick to disable."); - dataConfig("Lore.Chance","&3Chance: "); - dataConfig("Lore.Command","&3Command: &7"); - dataConfig("Lore.ContainsTheRank","&3The Rank "); - dataConfig("Lore.ContainsNoCommands"," &3contains no commands."); - dataConfig("Lore.DelaySellAll", "&3Delay: &8"); - dataConfig("Lore.DisableNotifications","&8Disable notifications."); - dataConfig("Lore.DisabledAll","&3All features &cOFF&3."); - dataConfig("Lore.EnabledAll","&aAll features ON"); - dataConfig("Lore.EmptyMultiplier", "&c[!] There aren't multipliers!"); - dataConfig("Lore.FullSoundEnabled","&aFull Inv., notify with sound ON"); - dataConfig("Lore.FullSoundDisabled","&cFull Inv., notify with sound OFF"); - dataConfig("Lore.FullHologramEnabled","&aFull Inv., notify with hologram ON"); - dataConfig("Lore.FullHologramDisabled","&cFull Inv., notify with hologram OFF"); - dataConfig("Lore.Id","&3Rank id: &7"); - dataConfig("Lore.Info","&8&l|&3Info&8|"); - dataConfig("Lore.IfYouHaveEnoughMoney","&8If you have enough money"); - dataConfig("Lore.LadderThereAre","&8There're &3"); - dataConfig("Lore.LadderCommands"," &3Commands at ladder:"); - dataConfig("Lore.LeftClickToConfirm","&aLeft-Click to confirm."); - dataConfig("Lore.LeftClickToOpen","&8Left Click to open."); - dataConfig("Lore.LeftClickToReset","&aLeft Click to reset"); - dataConfig("Lore.LeftClickToEdit", "&aLeft-Click to edit value"); - dataConfig("Lore.ManageResetTime","&8Manage the reset time of Mine."); - dataConfig("Lore.MinesButton","&3Mines GUI manager."); - dataConfig("Lore.MineName", "&3Mine Name: &f"); - dataConfig("Lore.Multiplier", "&3Multiplier: &f"); - dataConfig("Lore.Name","&3Rank Name: &7"); - dataConfig("Lore.Notifications","&8Edit Mines notifications."); - dataConfig("Lore.Permission", "&3Permission: "); - dataConfig("Lore.PlayerOwner", "&3Backpack owner: "); - dataConfig("Lore.PlayersWithTheRank","&3Players at rank: &7"); - dataConfig("Lore.PrestigeWarning", "&3Prestige will reset: "); - dataConfig("Lore.PrestigeWarning2", "&3 - &bRank"); - dataConfig("Lore.PrestigeWarning3", "&3 - &bBalance"); - dataConfig("Lore.PrestigeName", "&8Prestige name: &3"); - dataConfig("Lore.PrestigeMultiplier", "&8Multiplier: &3"); - dataConfig("Lore.PrestigeMultiplierInfoGUI", "&3Manage multipliers."); - dataConfig("Lore.Price","&3Price: &a$"); - dataConfig("Lore.Price2","&8Price: &a$"); - dataConfig("Lore.Price3","&3Rank Price: &a$"); - dataConfig("Lore.Percentage", "&8Percentage: "); - dataConfig("Lore.PrisonTasksButton","&3Prison Tasks Manager."); - dataConfig("Lore.ResetTime","&3Reset time(s): &7"); - dataConfig("Lore.Radius","&8Radius: "); - dataConfig("Lore.RankupCommands","&8&l|&3RankUPCommands&8| &8&l- &3"); - dataConfig("Lore.Rankup","&aRankup"); - dataConfig("Lore.RanksButton","&3Ranks GUI manager."); - dataConfig("Lore.ResetButton","&8Resets the mine."); - dataConfig("Lore.RightClickToCancel","&cRight-Click to cancel."); - dataConfig("Lore.RightClickToEnable","&cRight-Click to &aenable&c."); - dataConfig("Lore.RightClickToDisable", "&cRight-Click to disable."); - dataConfig("Lore.RightClickToToggle","&3Right click to toggle."); - dataConfig("Lore.RightClickToDelete", "&cRight-Click to delete."); - dataConfig("Lore.RightClickToEdit", "&8Right click to edit."); - dataConfig("Lore.SpawnPoint","&3Spawnpoint: &7"); - dataConfig("Lore.StatusLockedMine","&8Status: &cLocked"); - dataConfig("Lore.StatusUnlockedMine","&8Status: &aUnlocked"); - dataConfig("Lore.SpawnPoint2","&8Set the mine spawn point."); - dataConfig("Lore.SizeOfMine","&3Size of Mine: &7"); - dataConfig("Lore.Selected","&3Selected"); - dataConfig("Lore.ShowItem", "&3Show Item: &7"); - dataConfig("Lore.ShowItemDescription", "&7This's the item"); - dataConfig("Lore.ShowItemDescription2", "&7Shown in the Player's GUI"); - dataConfig("Lore.ShowItemDescription3", "&7Or /mines GUI."); - dataConfig("Lore.SellAllDelayInfo", "&8Short delay before using again"); - dataConfig("Lore.SellAllDelayInfo2", "&8the &3/sellall sell &8command."); - dataConfig("Lore.SellAllCurrencyInfo", "&3Edit SellAll Currency."); - dataConfig("Lore.SellAllActiveCurrency", "&3Currency: &a"); - dataConfig("Lore.ShiftAndRightClickToDelete","&cShift + Right click to delete."); - dataConfig("Lore.ShiftAndRightClickToDisable","&cShift + Right click to disable"); - dataConfig("Lore.ShiftAndRightClickToToggle","&cShift + Right click to toggle"); - dataConfig("Lore.StatusEnabled","&8Enabled"); - dataConfig("Lore.StatusDisabled","&8Disabled"); - dataConfig("Lore.SkipReset1","&8Skip the reset if "); - dataConfig("Lore.SkipReset2","&8not enough blocks "); - dataConfig("Lore.SkipReset3","&8have been mined."); - dataConfig("Lore.Tp","&8Tp to the mine."); - dataConfig("Lore.Tag","&3Tag: &8"); - dataConfig("Lore.Tag2","&3Rank Tag: &7"); - dataConfig("Lore.Time","&8Time: "); - dataConfig("Lore.Volume","&3Volume: &7"); - dataConfig("Lore.Value", "&3Value: &a$"); - dataConfig("Lore.World","&3World: &7"); - dataConfig("Lore.noRanksFoundSetup", "&3There aren't Ranks!"); - dataConfig("Lore.noRanksFoundSetup2", "&3If you want continue the setup."); - dataConfig("Lore.noRanksFoundSetup3", "&3All Ranks and Mines from A to Z will be made"); - dataConfig("Lore.noRanksFoundSetup4", "&3With &adefault &3values!"); - dataConfig("Lore.noRanksFoundSetup5", "&3You can do the same by command:"); - dataConfig("Lore.noRanksFoundSetup6", "&1/ranks autoConfigure full !"); - dataConfig("Lore.noRanksFoundSetup7", "&3Please replace the X with the starting price and"); - dataConfig("Lore.noRanksFoundSetup8", "&3multiplier, default price = 50000, multiplier = 1.5."); - dataConfig("Lore.ZeroBlocksReset1","&8Set a mine's delay "); - dataConfig("Lore.ZeroBlocksReset2","&8before reset when it "); - dataConfig("Lore.ZeroBlocksReset3","&8reaches zero blocks."); dataConfig("Message.BackPackIsDisabled", "Backpacks are disabled in the config.yml, you can't use this!"); dataConfig("Message.BackPackNeedPlayer", "Please add a playername."); dataConfig("Message.BackPackDeleteOperationSuccess", "The backpack should've been deleted with success!"); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/NewMessagesConfig.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/NewMessagesConfig.java new file mode 100644 index 000000000..e613c1fed --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/NewMessagesConfig.java @@ -0,0 +1,167 @@ +package tech.mcprison.prison.spigot.configs; + +import tech.mcprison.prison.spigot.SpigotPrison; + +import java.io.*; +import java.util.Properties; + +public class NewMessagesConfig { + + private static NewMessagesConfig instance; + private Properties properties = new Properties(); + private final String defaultLanguage = SpigotPrison.getInstance().getConfig().getString("default-language"); + private final String path = "/module_conf/spigot/lang/"; + + /** + * Get MessagesConfig class and initialize it if necessary. + * */ + public static NewMessagesConfig get(){ + if (instance == null){ + instance = new NewMessagesConfig(); + instance.initConfig(); + } + return instance; + } + + /** + * Initialize the config, reading and caching data. + * */ + private void initConfig(){ + try(FileInputStream data = new FileInputStream(SpigotPrison.getInstance().getDataFolder() + path + defaultLanguage + ".properties")){ + + Properties temp = new Properties(); + temp.load(new InputStreamReader(data)); + properties = temp; + + } catch (IOException ex){ + ex.printStackTrace(); + } + } + + /** + * Get String. + * */ + public String getString(StringID message){ + return properties.getProperty(message.toString()); + } + + public void reload(){ + initConfig(); + } + + public enum StringID { + + spigot_gui_lore_click_to_add, + spigot_gui_lore_click_to_add_backpack, + spigot_gui_lore_click_to_cancel, + spigot_gui_lore_click_to_close, + spigot_gui_lore_click_to_confirm, + spigot_gui_lore_click_to_decrease, + spigot_gui_lore_click_to_delete, + spigot_gui_lore_click_to_disable, + spigot_gui_lore_click_to_edit, + spigot_gui_lore_click_to_enable, + spigot_gui_lore_click_to_increase, + spigot_gui_lore_click_to_manage_rank, + spigot_gui_lore_click_to_open, + spigot_gui_lore_click_to_rankup, + spigot_gui_lore_click_to_rename, + spigot_gui_lore_click_to_select, + spigot_gui_lore_click_to_start_block_setup, + spigot_gui_lore_click_to_teleport, + spigot_gui_lore_click_to_use, + + spigot_gui_lore_click_left_to_confirm, + spigot_gui_lore_click_left_to_edit, + spigot_gui_lore_click_left_to_open, + spigot_gui_lore_click_left_to_reset, + + spigot_gui_lore_click_right_to_cancel, + spigot_gui_lore_click_right_to_delete, + spigot_gui_lore_click_right_to_disable, + spigot_gui_lore_click_right_to_enable, + spigot_gui_lore_click_right_to_toggle, + + spigot_gui_lore_click_right_and_shift_to_delete, + spigot_gui_lore_click_right_and_shift_to_disable, + spigot_gui_lore_click_right_and_shift_to_toggle, + + spigot_gui_lore_backpack_id, + spigot_gui_lore_blocks, + spigot_gui_lore_blocktype, + spigot_gui_lore_chance, + spigot_gui_lore_command, + spigot_gui_lore_currency, + spigot_gui_lore_delay, + spigot_gui_lore_id, + spigot_gui_lore_info, + spigot_gui_lore_minename, + spigot_gui_lore_multiplier, + spigot_gui_lore_name, + spigot_gui_lore_owner, + spigot_gui_lore_percentage, + spigot_gui_lore_permission, + spigot_gui_lore_players_at_rank, + spigot_gui_lore_prestige_name, + spigot_gui_lore_price, + spigot_gui_lore_radius, + spigot_gui_lore_rank_tag, + spigot_gui_lore_reset_time, + spigot_gui_lore_show_item, + spigot_gui_lore_size, + spigot_gui_lore_spawnpoint, + spigot_gui_lore_volume, + spigot_gui_lore_value, + spigot_gui_lore_world, + + spigot_gui_lore_disabled, + spigot_gui_lore_enabled, + spigot_gui_lore_locked, + spigot_gui_lore_next_page, + spigot_gui_lore_prior_page, + spigot_gui_lore_rankup, + spigot_gui_lore_selected, + spigot_gui_lore_unlocked, + + spigot_gui_lore_add_backpack_instruction_1, + spigot_gui_lore_add_backpack_instruction_2, + spigot_gui_lore_add_backpack_instruction_3, + spigot_gui_lore_prestige_warning_1, + spigot_gui_lore_prestige_warning_2, + spigot_gui_lore_prestige_warning_3, + spigot_gui_lore_ranks_setup_1, + spigot_gui_lore_ranks_setup_2, + spigot_gui_lore_ranks_setup_3, + spigot_gui_lore_ranks_setup_4, + spigot_gui_lore_ranks_setup_5, + spigot_gui_lore_ranks_setup_6, + spigot_gui_lore_ranks_setup_7, + spigot_gui_lore_ranks_setup_8, + spigot_gui_lore_sellall_delay_use_1, + spigot_gui_lore_sellall_delay_use_2, + spigot_gui_lore_set_mine_delay_instruction_1, + spigot_gui_lore_set_mine_delay_instruction_2, + spigot_gui_lore_set_mine_delay_instruction_3, + spigot_gui_lore_show_item_description_1, + spigot_gui_lore_show_item_description_2, + spigot_gui_lore_show_item_description_3, + spigot_gui_lore_skip_reset_instruction_1, + spigot_gui_lore_skip_reset_instruction_2, + spigot_gui_lore_skip_reset_instruction_3, + + spigot_gui_lore_autofeatures_button_description, + spigot_gui_lore_backpacks_button_description, + spigot_gui_lore_disable_notifications, + spigot_gui_lore_enable_radius_mode, + spigot_gui_lore_enable_within_mode, + spigot_gui_lore_mines_button_description, + spigot_gui_lore_no_multipliers, + spigot_gui_lore_ranks_button_description, + spigot_gui_lore_rankup_if_enough_money, + spigot_gui_lore_sellall_button_description, + spigot_gui_lore_sellall_edit_info, + spigot_gui_lore_tp_to_mine, + + spigot_general_missing_permission + } +} diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java index b255c6acb..7b74cc0b7 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java @@ -45,6 +45,7 @@ import tech.mcprison.prison.spigot.commands.PrisonSpigotSellAllCommands; import tech.mcprison.prison.spigot.compat.Compatibility; import tech.mcprison.prison.spigot.compat.SpigotCompatibility; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.autofeatures.SpigotAutoBlockGUI; import tech.mcprison.prison.spigot.gui.autofeatures.SpigotAutoFeaturesGUI; @@ -95,6 +96,7 @@ public class ListenersPrisonManager implements Listener { private final Configuration guiConfig = SpigotPrison.getInstance().getGuiConfig(); private final Configuration messages = SpigotPrison.getInstance().getMessagesConfig(); + private final NewMessagesConfig newMessages = SpigotPrison.getInstance().getNewMessagesConfig(); boolean guiNotEnabled = !(config.getString("prison-gui-enabled").equalsIgnoreCase("true")); private Optional ladder; public ChatMode mode; @@ -1846,7 +1848,7 @@ private void rankManagerGUI(InventoryClickEvent e, Player p, String[] parts) { private void playerRanksGUI(InventoryClickEvent e, Player p, String buttonNameMain) { // Check the buttonName and do the actions. - if (buttonNameMain.equals(SpigotPrison.format(messages.getString("Lore.Rankup").substring(2)))){ + if (buttonNameMain.equals(SpigotPrison.format(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_rankup).substring(2)))){ Bukkit.dispatchCommand(p, "rankup " + guiConfig.getString("Options.Ranks.Ladder")); p.closeInventory(); } @@ -2349,7 +2351,7 @@ private void mineNotificationsGUI(InventoryClickEvent e, Player p, String[] part typeNotification = "within"; // Execute command - Bukkit.dispatchCommand(p, "mines set notification " + mineName + " " + typeNotification + " " + "0"); + Bukkit.dispatchCommand(p, "mines set notification " + mineName + " " + typeNotification + " 0"); // Cancel the event and close the inventory e.setCancelled(true); @@ -2375,7 +2377,7 @@ private void mineNotificationsGUI(InventoryClickEvent e, Player p, String[] part typeNotification = "disabled"; // Execute the command - Bukkit.dispatchCommand(p, "mines set notification " + mineName + " " + typeNotification + " " + "0"); + Bukkit.dispatchCommand(p, "mines set notification " + mineName + " " + typeNotification + " 0"); // Cancel the event and close the inventory e.setCancelled(true); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/PrisonSetupGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/PrisonSetupGUI.java index c3ce8c842..483a423f2 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/PrisonSetupGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/PrisonSetupGUI.java @@ -2,6 +2,7 @@ import com.cryptomorin.xseries.XMaterial; import org.bukkit.entity.Player; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -24,23 +25,22 @@ public void open(){ PrisonGUI gui = new PrisonGUI(p, 9, "&3Prison Setup -> Confirmation"); // Create lore. - ButtonLore lore = new ButtonLore(createLore(messages.getString("Lore.ClickToConfirm")), createLore( - messages.getString("Lore.noRanksFoundSetup"), - messages.getString("Lore.noRanksFoundSetup1"), - messages.getString("Lore.noRanksFoundSetup2"), - messages.getString("Lore.noRanksFoundSetup3"), - messages.getString("Lore.noRanksFoundSetup4"), - messages.getString("Lore.noRanksFoundSetup5"), - messages.getString("Lore.noRanksFoundSetup6"), - messages.getString("Lore.noRanksFoundSetup7"), - messages.getString("Lore.noRanksFoundSetup8"))); + ButtonLore lore = new ButtonLore(createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_confirm)), createLore( + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_ranks_setup_1), + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_ranks_setup_2), + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_ranks_setup_3), + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_ranks_setup_4), + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_ranks_setup_5), + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_ranks_setup_6), + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_ranks_setup_7), + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_ranks_setup_8))); // Add button. - gui.addButton(new Button(2, XMaterial.EMERALD_BLOCK, lore, "&3" + "Confirm: Setup")); + gui.addButton(new Button(2, XMaterial.EMERALD_BLOCK, lore, "&3Confirm: Setup")); // Add button. gui.addButton(new Button(6, XMaterial.REDSTONE_BLOCK, createLore( - messages.getString("Lore.ClickToCancel")), "&3" + "Cancel: Setup")); + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_cancel)), "&3Cancel: Setup")); // Open Prison GUI. gui.open(); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/SpigotPrisonGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/SpigotPrisonGUI.java index 01269ece8..ff44db784 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/SpigotPrisonGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/SpigotPrisonGUI.java @@ -3,6 +3,7 @@ import com.cryptomorin.xseries.XMaterial; import org.bukkit.entity.Player; import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -26,12 +27,12 @@ public void open() { PrisonGUI gui = new PrisonGUI(p, dimension, "&3PrisonManager"); // Create and add buttons. - gui.addButton(new Button(10, XMaterial.TRIPWIRE_HOOK, new ButtonLore(messages.getString("Lore.ClickToOpen"), messages.getString("Lore.RanksButton")), "&3" + "Ranks - Ladders")); - gui.addButton(new Button(13, XMaterial.IRON_PICKAXE, new ButtonLore(messages.getString("Lore.ClickToOpen"), messages.getString("Lore.PrisonTasksButton")), SpigotPrison.format("&3" + "AutoManager"))); - gui.addButton(new Button(16, XMaterial.DIAMOND_ORE, new ButtonLore(messages.getString("Lore.ClickToOpen"), messages.getString("Lore.MinesButton")), SpigotPrison.format("&3" + "Mines"))); - gui.addButton(new Button(29, XMaterial.CHEST, new ButtonLore(messages.getString("Lore.ClickToOpen"), null), SpigotPrison.format("&3" + "SellAll"))); - gui.addButton(new Button(33, XMaterial.CHEST_MINECART, new ButtonLore(messages.getString("Lore.ClickToOpen"), null), SpigotPrison.format("&3" + "Backpacks"))); - gui.addButton(new Button(44, XMaterial.RED_STAINED_GLASS_PANE, new ButtonLore(messages.getString("Lore.ClickToClose"), null), SpigotPrison.format("&c" + "Close"))); + gui.addButton(new Button(10, XMaterial.TRIPWIRE_HOOK, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_ranks_button_description)), "&3Ranks - Ladders")); + gui.addButton(new Button(13, XMaterial.IRON_PICKAXE, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_autofeatures_button_description)), SpigotPrison.format("&3AutoManager"))); + gui.addButton(new Button(16, XMaterial.DIAMOND_ORE, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_mines_button_description)), SpigotPrison.format("&3Mines"))); + gui.addButton(new Button(29, XMaterial.CHEST, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_sellall_button_description)), SpigotPrison.format("&3SellAll"))); + gui.addButton(new Button(33, XMaterial.CHEST_MINECART, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_backpacks_button_description)), SpigotPrison.format("&3Backpacks"))); + gui.addButton(new Button(44, XMaterial.RED_STAINED_GLASS_PANE, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_close), null), SpigotPrison.format("&cClose"))); gui.open(); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoBlockGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoBlockGUI.java index c507954c4..f74105fcb 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoBlockGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoBlockGUI.java @@ -6,6 +6,7 @@ import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig; import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -29,83 +30,82 @@ public void open() { PrisonGUI gui = new PrisonGUI(p, 36, "&3AutoFeatures -> AutoBlock"); // Lores - ButtonLore enabledLore = new ButtonLore(messages.getString("Lore.ShiftAndRightClickToDisable"), null); - ButtonLore disabledLore = new ButtonLore(messages.getString("Lore.RightClickToEnable"), null); - - gui.addButton(new Button(35, XMaterial.RED_STAINED_GLASS_PANE, new ButtonLore(messages.getString("Lore.ClickToClose"), null), SpigotPrison.format("&c" + "Close"))); + ButtonLore enabledLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_and_shift_to_disable), null); + ButtonLore disabledLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_enable), null); + gui.addButton(new Button(35, XMaterial.RED_STAINED_GLASS_PANE, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_close), null), "&cClose")); if (afConfig != null) { if (afConfig.isFeatureBoolean(AutoFeatures.blockAllBlocks)) { - gui.addButton(new Button(null, XMaterial.LIME_STAINED_GLASS_PANE, enabledLore, SpigotPrison.format("&a" + "All_Blocks Enabled"))); + gui.addButton(new Button(null, XMaterial.LIME_STAINED_GLASS_PANE, enabledLore, SpigotPrison.format("&aAll_Blocks Enabled"))); } else { - gui.addButton(new Button(null, XMaterial.RED_STAINED_GLASS_PANE, disabledLore, SpigotPrison.format("&c" + "All_Blocks Disabled"))); + gui.addButton(new Button(null, XMaterial.RED_STAINED_GLASS_PANE, disabledLore, SpigotPrison.format("&cAll_Blocks Disabled"))); } if (afConfig.isFeatureBoolean(AutoFeatures.blockGoldBlock)) { - gui.addButton(new Button(null, XMaterial.GOLD_BLOCK, enabledLore, SpigotPrison.format("&a" + "Gold_Block Enabled"))); + gui.addButton(new Button(null, XMaterial.GOLD_BLOCK, enabledLore, SpigotPrison.format("&aGold_Block Enabled"))); } else { - gui.addButton(new Button(null, XMaterial.GOLD_BLOCK, disabledLore, SpigotPrison.format("&c" + "Gold_Block Disabled"))); + gui.addButton(new Button(null, XMaterial.GOLD_BLOCK, disabledLore, SpigotPrison.format("&cGold_Block Disabled"))); } if (afConfig.isFeatureBoolean(AutoFeatures.blockIronBlock)) { - gui.addButton(new Button(null, XMaterial.IRON_BLOCK, enabledLore, SpigotPrison.format("&a" + "Iron_Block Enabled"))); + gui.addButton(new Button(null, XMaterial.IRON_BLOCK, enabledLore, SpigotPrison.format("&aIron_Block Enabled"))); } else { - gui.addButton(new Button(null, XMaterial.IRON_BLOCK, disabledLore, SpigotPrison.format("&c" + "Iron_Block Disabled"))); + gui.addButton(new Button(null, XMaterial.IRON_BLOCK, disabledLore, SpigotPrison.format("&cIron_Block Disabled"))); } if (afConfig.isFeatureBoolean(AutoFeatures.blockCoalBlock)) { - gui.addButton(new Button(null, XMaterial.COAL_BLOCK, enabledLore, SpigotPrison.format("&a" + "Coal_Block Enabled"))); + gui.addButton(new Button(null, XMaterial.COAL_BLOCK, enabledLore, SpigotPrison.format("&aCoal_Block Enabled"))); } else { - gui.addButton(new Button(null, XMaterial.COAL_BLOCK, disabledLore, SpigotPrison.format("&c" + "Coal_Block Disabled"))); + gui.addButton(new Button(null, XMaterial.COAL_BLOCK, disabledLore, SpigotPrison.format("&cCoal_Block Disabled"))); } if (afConfig.isFeatureBoolean(AutoFeatures.blockDiamondBlock)) { - gui.addButton(new Button(null, XMaterial.DIAMOND_BLOCK, enabledLore, SpigotPrison.format("&a" + "Diamond_Block Enabled"))); + gui.addButton(new Button(null, XMaterial.DIAMOND_BLOCK, enabledLore, SpigotPrison.format("&aDiamond_Block Enabled"))); } else { - gui.addButton(new Button(null, XMaterial.DIAMOND_BLOCK, disabledLore, SpigotPrison.format("&c" + "Diamond_Block Disabled"))); + gui.addButton(new Button(null, XMaterial.DIAMOND_BLOCK, disabledLore, SpigotPrison.format("&cDiamond_Block Disabled"))); } if (afConfig.isFeatureBoolean(AutoFeatures.blockRedstoneBlock)) { - gui.addButton(new Button(null, XMaterial.REDSTONE_BLOCK, enabledLore, SpigotPrison.format("&a" + "Redstone_Block Enabled"))); + gui.addButton(new Button(null, XMaterial.REDSTONE_BLOCK, enabledLore, SpigotPrison.format("&aRedstone_Block Enabled"))); } else { - gui.addButton(new Button(null, XMaterial.REDSTONE_BLOCK, disabledLore, SpigotPrison.format("&c" + "Redstone_Block Disabled"))); + gui.addButton(new Button(null, XMaterial.REDSTONE_BLOCK, disabledLore, SpigotPrison.format("&cRedstone_Block Disabled"))); } if (afConfig.isFeatureBoolean(AutoFeatures.blockEmeraldBlock)) { - gui.addButton(new Button(null, XMaterial.EMERALD_BLOCK, enabledLore, SpigotPrison.format("&a" + "Emerald_Block Enabled"))); + gui.addButton(new Button(null, XMaterial.EMERALD_BLOCK, enabledLore, SpigotPrison.format("&aEmerald_Block Enabled"))); } else { - gui.addButton(new Button(null, XMaterial.EMERALD_BLOCK, disabledLore, SpigotPrison.format("&c" + "Emerald_Block Disabled"))); + gui.addButton(new Button(null, XMaterial.EMERALD_BLOCK, disabledLore, SpigotPrison.format("&cEmerald_Block Disabled"))); } if (afConfig.isFeatureBoolean(AutoFeatures.blockQuartzBlock)) { - gui.addButton(new Button(null, XMaterial.QUARTZ_BLOCK, enabledLore, SpigotPrison.format("&a" + "Quartz_Block Enabled"))); + gui.addButton(new Button(null, XMaterial.QUARTZ_BLOCK, enabledLore, SpigotPrison.format("&aQuartz_Block Enabled"))); } else { - gui.addButton(new Button(null, XMaterial.QUARTZ_BLOCK, disabledLore, SpigotPrison.format("&c" + "Quartz_Block Disabled"))); + gui.addButton(new Button(null, XMaterial.QUARTZ_BLOCK, disabledLore, SpigotPrison.format("&cQuartz_Block Disabled"))); } if (afConfig.isFeatureBoolean(AutoFeatures.blockPrismarineBlock)) { - gui.addButton(new Button(null, XMaterial.PRISMARINE, enabledLore, SpigotPrison.format("&a" + "Prismarine_Block Enabled"))); + gui.addButton(new Button(null, XMaterial.PRISMARINE, enabledLore, SpigotPrison.format("&aPrismarine_Block Enabled"))); } else { - gui.addButton(new Button(null, XMaterial.PRISMARINE, disabledLore, SpigotPrison.format("&c" + "Prismarine_Block Disabled"))); + gui.addButton(new Button(null, XMaterial.PRISMARINE, disabledLore, SpigotPrison.format("&cPrismarine_Block Disabled"))); } if (afConfig.isFeatureBoolean(AutoFeatures.blockLapisBlock)) { - gui.addButton(new Button(null, XMaterial.LAPIS_BLOCK, enabledLore, SpigotPrison.format("&a" + "Lapis_Block Enabled"))); + gui.addButton(new Button(null, XMaterial.LAPIS_BLOCK, enabledLore, SpigotPrison.format("&aLapis_Block Enabled"))); } else { - gui.addButton(new Button(null, XMaterial.LAPIS_BLOCK, disabledLore, SpigotPrison.format("&c" + "Lapis_Block Disabled"))); + gui.addButton(new Button(null, XMaterial.LAPIS_BLOCK, disabledLore, SpigotPrison.format("&cLapis_Block Disabled"))); } if (afConfig.isFeatureBoolean(AutoFeatures.blockSnowBlock)) { - gui.addButton(new Button(null, XMaterial.SNOW_BLOCK, enabledLore, SpigotPrison.format("&a" + "Snow_Block Enabled"))); + gui.addButton(new Button(null, XMaterial.SNOW_BLOCK, enabledLore, SpigotPrison.format("&aSnow_Block Enabled"))); } else { - gui.addButton(new Button(null, XMaterial.SNOW_BLOCK, disabledLore, SpigotPrison.format("&c" + "Snow_Block Disabled"))); + gui.addButton(new Button(null, XMaterial.SNOW_BLOCK, disabledLore, SpigotPrison.format("&cSnow_Block Disabled"))); } if (afConfig.isFeatureBoolean(AutoFeatures.blockGlowstone)) { - gui.addButton(new Button(null, XMaterial.GLOWSTONE, enabledLore, SpigotPrison.format("&a" + "Glowstone_Block Enabled"))); + gui.addButton(new Button(null, XMaterial.GLOWSTONE, enabledLore, SpigotPrison.format("&aGlowstone_Block Enabled"))); } else { - gui.addButton(new Button(null, XMaterial.GLOWSTONE, disabledLore, SpigotPrison.format("&c" + "Glowstone_Block Disabled"))); + gui.addButton(new Button(null, XMaterial.GLOWSTONE, disabledLore, SpigotPrison.format("&cGlowstone_Block Disabled"))); } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoFeaturesGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoFeaturesGUI.java index d4d3f8365..17d1bd20c 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoFeaturesGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoFeaturesGUI.java @@ -7,6 +7,7 @@ import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig; import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -30,106 +31,72 @@ public void open() { PrisonGUI gui; - ButtonLore closeGUILore = new ButtonLore(messages.getString("Lore.ClickToClose"), null); + ButtonLore closeGUILore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_close), null); if (afConfig != null && afConfig.isFeatureBoolean(AutoFeatures.isAutoManagerEnabled)) { - ButtonLore disable = new ButtonLore(messages.getString("Lore.ShiftAndRightClickToDisable"), null); - ButtonLore enable = new ButtonLore(messages.getString("Lore.RightClickToEnable"), null); + ButtonLore disable = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_and_shift_to_disable), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_enabled)); + ButtonLore enable = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_enable), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_disabled)); gui = new PrisonGUI(p, dimension, "&3PrisonManager -> AutoFeatures"); - - gui.addButton(new Button(dimension -1,XMaterial.RED_STAINED_GLASS_PANE, closeGUILore, SpigotPrison.format("&c" + "Close"))); + gui.addButton(new Button(dimension -1,XMaterial.RED_STAINED_GLASS_PANE, closeGUILore, SpigotPrison.format("&cClose"))); if (afConfig.isFeatureBoolean(AutoFeatures.playSoundIfInventoryIsFull)) { - - disable.setLoreDescription(messages.getString("Lore.FullSoundEnabled")); - gui.addButton(new Button(0, XMaterial.LIME_STAINED_GLASS_PANE, disable, SpigotPrison.format("&a" + "Full-Inventory-Sound Enabled"))); - + gui.addButton(new Button(0, XMaterial.LIME_STAINED_GLASS_PANE, disable, SpigotPrison.format("&aFull-Inventory-Sound Enabled"))); } else { - - enable.setLoreDescription(messages.getString("Lore.FullSoundDisabled")); - gui.addButton(new Button(0, XMaterial.RED_STAINED_GLASS_PANE, enable, SpigotPrison.format("&c" + "Full-Inventory-Sound Disabled"))); - + gui.addButton(new Button(0, XMaterial.RED_STAINED_GLASS_PANE, enable, SpigotPrison.format("&cFull-Inventory-Sound Disabled"))); } if (afConfig.isFeatureBoolean(AutoFeatures.hologramIfInventoryIsFull)) { - - disable.setLoreDescription(messages.getString("Lore.FullHologramEnabled")); - gui.addButton(new Button(8, XMaterial.LIME_STAINED_GLASS_PANE, disable, SpigotPrison.format("&a" + "Full-Inventory-Hologram Enabled"))); - + gui.addButton(new Button(8, XMaterial.LIME_STAINED_GLASS_PANE, disable, SpigotPrison.format("&aFull-Inventory-Hologram Enabled"))); } else { - - enable.setLoreDescription(messages.getString("Lore.FullHologramDisabled")); - gui.addButton(new Button(8, XMaterial.RED_STAINED_GLASS_PANE, enable, SpigotPrison.format("&c" + "Full-Inventory-Hologram Disabled"))); - + gui.addButton(new Button(8, XMaterial.RED_STAINED_GLASS_PANE, enable, SpigotPrison.format("&cFull-Inventory-Hologram Disabled"))); } if (afConfig.isFeatureBoolean(AutoFeatures.isAutoManagerEnabled)) { - - disable.setLoreDescription(messages.getString("Lore.EnabledAll")); - gui.addButton(new Button(18, XMaterial.LIME_STAINED_GLASS_PANE, disable, SpigotPrison.format("&a" + "All Enabled"))); - + gui.addButton(new Button(18, XMaterial.LIME_STAINED_GLASS_PANE, disable, SpigotPrison.format("&aAll Enabled"))); } else { - - enable.setLoreDescription(messages.getString("Lore.DisabledAll")); - gui.addButton(new Button(18, XMaterial.RED_STAINED_GLASS_PANE, enable, SpigotPrison.format("&c" + "All Disabled"))); - + gui.addButton(new Button(18, XMaterial.RED_STAINED_GLASS_PANE, enable, SpigotPrison.format("&cAll Disabled"))); } disable.setLoreAction(createLore( - messages.getString("Lore.LeftClickToOpen"), - messages.getString("Lore.ShiftAndRightClickToDisable") + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_left_to_open), + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_disable) )); enable.setLoreAction(createLore( - messages.getString("Lore.LeftClickToOpen"), - messages.getString("Lore.RightClickToEnable") + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_left_to_open), + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_enable) )); if (afConfig.isFeatureBoolean(AutoFeatures.autoPickupEnabled)) { - - disable.setLoreDescription(messages.getString("Lore.AutoPickupGuiManager")); - gui.addButton(new Button(11, XMaterial.CHEST, disable, SpigotPrison.format("&3" + "AutoPickup Enabled"))); + gui.addButton(new Button(11, XMaterial.CHEST, disable, SpigotPrison.format("&3AutoPickup Enabled"))); } else { - - enable.setLoreDescription(messages.getString("Lore.AutoPickupGuiManager")); - gui.addButton(new Button(11, XMaterial.CHEST, enable, SpigotPrison.format("&c" + "AutoPickup Disabled"))); + gui.addButton(new Button(11, XMaterial.CHEST, enable, SpigotPrison.format("&cAutoPickup Disabled"))); } if (afConfig.isFeatureBoolean(AutoFeatures.autoSmeltEnabled)) { - - disable.setLoreDescription(messages.getString("Lore.AutoSmeltGuiManager")); - gui.addButton(new Button(13, XMaterial.FURNACE, disable, SpigotPrison.format("&3" + "AutoSmelt Enabled"))); + gui.addButton(new Button(13, XMaterial.FURNACE, disable, SpigotPrison.format("&3AutoSmelt Enabled"))); } else { - - enable.setLoreDescription(messages.getString("Lore.AutoSmeltGuiManager")); - gui.addButton(new Button(13, XMaterial.FURNACE, enable, SpigotPrison.format("&c" + "AutoSmelt Disabled"))); + gui.addButton(new Button(13, XMaterial.FURNACE, enable, SpigotPrison.format("&cAutoSmelt Disabled"))); } if (afConfig.isFeatureBoolean(AutoFeatures.autoBlockEnabled)) { - - disable.setLoreDescription(messages.getString("Lore.AutoBlockGuiManager")); - gui.addButton(new Button(15, XMaterial.CRAFTING_TABLE, disable, SpigotPrison.format("&3" + "AutoBlock Enabled"))); - + gui.addButton(new Button(15, XMaterial.CRAFTING_TABLE, disable, SpigotPrison.format("&3AutoBlock Enabled"))); } else { - - enable.setLoreDescription(messages.getString("Lore.AutoBlockGuiManager")); - gui.addButton(new Button(15, XMaterial.CRAFTING_TABLE, enable, SpigotPrison.format("&c" + "AutoBlock Disabled"))); + gui.addButton(new Button(15, XMaterial.CRAFTING_TABLE, enable, SpigotPrison.format("&cAutoBlock Disabled"))); } } else { gui = new PrisonGUI(p, 9, "&3PrisonManager -> AutoFeatures"); - ButtonLore lore = new ButtonLore(messages.getString("Lore.RightClickToEnable"), messages.getString("Lore.DisabledAll")); - - Button enabledOrDisabled = new Button(2, XMaterial.LIME_STAINED_GLASS_PANE, lore, SpigotPrison.format("&c" + "All Disabled")); - + ButtonLore lore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_enable), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_disabled)); + Button enabledOrDisabled = new Button(2, XMaterial.LIME_STAINED_GLASS_PANE, lore, SpigotPrison.format("&cAll Disabled")); gui.addButton(enabledOrDisabled); - gui.addButton(new Button(6,XMaterial.RED_STAINED_GLASS_PANE, closeGUILore, SpigotPrison.format("&c" + "Close"))); + gui.addButton(new Button(6,XMaterial.RED_STAINED_GLASS_PANE, closeGUILore, SpigotPrison.format("&cClose"))); } gui.open(); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoPickupGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoPickupGUI.java index a04b7322c..b1a668281 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoPickupGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoPickupGUI.java @@ -7,6 +7,7 @@ import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; @@ -30,89 +31,89 @@ public void open() { int dimension = 36; PrisonGUI gui = new PrisonGUI(p, dimension, "&3AutoFeatures -> AutoPickup"); - ButtonLore enabledLore = new ButtonLore(messages.getString("Lore.ShiftAndRightClickToDisable"), null); - ButtonLore disabledLore = new ButtonLore(messages.getString("Lore.RightClickToEnable"), null); - ButtonLore closeGUILore = new ButtonLore(messages.getString("Lore.ClickToClose"), null); + ButtonLore enabledLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_and_shift_to_disable), null); + ButtonLore disabledLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_enable), null); + ButtonLore closeGUILore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_close), null); - gui.addButton(new Button(35, XMaterial.RED_STAINED_GLASS_PANE, closeGUILore, SpigotPrison.format("&c" + "Close"))); + gui.addButton(new Button(35, XMaterial.RED_STAINED_GLASS_PANE, closeGUILore, SpigotPrison.format("&cClose"))); if (afConfig != null) { if (afConfig.isFeatureBoolean(AutoFeatures.pickupAllBlocks)) { - gui.addButton(new Button(null, XMaterial.LIME_STAINED_GLASS_PANE, enabledLore, SpigotPrison.format("&a" + "All_Blocks Enabled"))); + gui.addButton(new Button(null, XMaterial.LIME_STAINED_GLASS_PANE, enabledLore, SpigotPrison.format("&aAll_Blocks Enabled"))); } else { - gui.addButton(new Button(null, XMaterial.RED_STAINED_GLASS_PANE, disabledLore, SpigotPrison.format("&c" + "All_Blocks Disabled"))); + gui.addButton(new Button(null, XMaterial.RED_STAINED_GLASS_PANE, disabledLore, SpigotPrison.format("&cAll_Blocks Disabled"))); } if (afConfig.isFeatureBoolean(AutoFeatures.pickupCobbleStone)) { - gui.addButton(new Button(null, XMaterial.COBBLESTONE, enabledLore, SpigotPrison.format("&a" + "Cobblestone Enabled"))); + gui.addButton(new Button(null, XMaterial.COBBLESTONE, enabledLore, SpigotPrison.format("&aCobblestone Enabled"))); } else { - gui.addButton(new Button(null, XMaterial.COBBLESTONE, disabledLore, SpigotPrison.format("&c" + "Cobblestone Disabled"))); + gui.addButton(new Button(null, XMaterial.COBBLESTONE, disabledLore, SpigotPrison.format("&cCobblestone Disabled"))); } if (afConfig.isFeatureBoolean(AutoFeatures.pickupStone)) { - gui.addButton(new Button(null, XMaterial.STONE, enabledLore, SpigotPrison.format("&a" + "Stone Enabled"))); + gui.addButton(new Button(null, XMaterial.STONE, enabledLore, SpigotPrison.format("&aStone Enabled"))); } else { - gui.addButton(new Button(null, XMaterial.STONE, disabledLore, SpigotPrison.format("&c" + "Stone Disabled"))); + gui.addButton(new Button(null, XMaterial.STONE, disabledLore, SpigotPrison.format("&cStone Disabled"))); } if (afConfig.isFeatureBoolean(AutoFeatures.pickupGoldOre)) { - gui.addButton(new Button(null, XMaterial.GOLD_ORE, enabledLore, SpigotPrison.format("&a" + "Gold_Ore Enabled"))); + gui.addButton(new Button(null, XMaterial.GOLD_ORE, enabledLore, SpigotPrison.format("&aGold_Ore Enabled"))); } else { - gui.addButton(new Button(null, XMaterial.GOLD_ORE, disabledLore, SpigotPrison.format("&c" + "Gold_Ore Disabled"))); + gui.addButton(new Button(null, XMaterial.GOLD_ORE, disabledLore, SpigotPrison.format("&cGold_Ore Disabled"))); } if (afConfig.isFeatureBoolean(AutoFeatures.pickupIronOre)) { - gui.addButton(new Button(null, XMaterial.IRON_ORE, enabledLore, SpigotPrison.format("&a" + "Iron_Ore Enabled"))); + gui.addButton(new Button(null, XMaterial.IRON_ORE, enabledLore, SpigotPrison.format("&aIron_Ore Enabled"))); } else { - gui.addButton(new Button(null, XMaterial.IRON_ORE, disabledLore, SpigotPrison.format("&c" + "Iron_Ore Disabled"))); + gui.addButton(new Button(null, XMaterial.IRON_ORE, disabledLore, SpigotPrison.format("&cIron_Ore Disabled"))); } if (afConfig.isFeatureBoolean(AutoFeatures.pickupCoalOre)) { - gui.addButton(new Button(null, XMaterial.COAL_ORE, enabledLore, SpigotPrison.format("&a" + "Coal_Ore Enabled"))); + gui.addButton(new Button(null, XMaterial.COAL_ORE, enabledLore, SpigotPrison.format("&aCoal_Ore Enabled"))); } else { - gui.addButton(new Button(null, XMaterial.COAL_ORE, disabledLore, SpigotPrison.format("&c" + "Coal_Ore Disabled"))); + gui.addButton(new Button(null, XMaterial.COAL_ORE, disabledLore, SpigotPrison.format("&cCoal_Ore Disabled"))); } if (afConfig.isFeatureBoolean(AutoFeatures.pickupDiamondOre)) { - gui.addButton(new Button(null, XMaterial.DIAMOND_ORE, enabledLore, SpigotPrison.format("&a" + "Diamond_Ore Enabled"))); + gui.addButton(new Button(null, XMaterial.DIAMOND_ORE, enabledLore, SpigotPrison.format("&aDiamond_Ore Enabled"))); } else { - gui.addButton(new Button(null, XMaterial.DIAMOND_ORE, disabledLore, SpigotPrison.format("&c" + "Diamond_Ore Disabled"))); + gui.addButton(new Button(null, XMaterial.DIAMOND_ORE, disabledLore, SpigotPrison.format("&cDiamond_Ore Disabled"))); } if (afConfig.isFeatureBoolean(AutoFeatures.pickupRedStoneOre)) { - gui.addButton(new Button(null, XMaterial.REDSTONE_ORE, enabledLore, SpigotPrison.format("&a" + "Redstone_Ore Enabled"))); + gui.addButton(new Button(null, XMaterial.REDSTONE_ORE, enabledLore, SpigotPrison.format("&aRedstone_Ore Enabled"))); } else { - gui.addButton(new Button(null, XMaterial.REDSTONE_ORE, disabledLore, SpigotPrison.format("&c" + "Redstone_Ore Disabled"))); + gui.addButton(new Button(null, XMaterial.REDSTONE_ORE, disabledLore, SpigotPrison.format("&cRedstone_Ore Disabled"))); } if (afConfig.isFeatureBoolean(AutoFeatures.pickupEmeraldOre)) { - gui.addButton(new Button(null, XMaterial.EMERALD_ORE, enabledLore, SpigotPrison.format("&a" + "Emerald_Ore Enabled"))); + gui.addButton(new Button(null, XMaterial.EMERALD_ORE, enabledLore, SpigotPrison.format("&aEmerald_Ore Enabled"))); } else { - gui.addButton(new Button(null, XMaterial.EMERALD_ORE, disabledLore, SpigotPrison.format("&c" + "Emerald_Ore Disabled"))); + gui.addButton(new Button(null, XMaterial.EMERALD_ORE, disabledLore, SpigotPrison.format("&cEmerald_Ore Disabled"))); } if (afConfig.isFeatureBoolean(AutoFeatures.pickupQuartzOre)) { - gui.addButton(new Button(null, XMaterial.NETHER_QUARTZ_ORE, 1, enabledLore, SpigotPrison.format("&a" + "Quartz_Ore Enabled"))); + gui.addButton(new Button(null, XMaterial.NETHER_QUARTZ_ORE, 1, enabledLore, SpigotPrison.format("&aQuartz_Ore Enabled"))); } else { - gui.addButton(new Button(null, XMaterial.NETHER_QUARTZ_ORE, 1, disabledLore, SpigotPrison.format("&c" + "Quartz_Ore Disabled"))); + gui.addButton(new Button(null, XMaterial.NETHER_QUARTZ_ORE, 1, disabledLore, SpigotPrison.format("&cQuartz_Ore Disabled"))); } if (afConfig.isFeatureBoolean(AutoFeatures.pickupLapisOre)) { - gui.addButton(new Button(null, XMaterial.LAPIS_ORE, enabledLore, SpigotPrison.format("&a" + "Lapis_Ore Enabled"))); + gui.addButton(new Button(null, XMaterial.LAPIS_ORE, enabledLore, SpigotPrison.format("&aLapis_Ore Enabled"))); } else { - gui.addButton(new Button(null, XMaterial.LAPIS_ORE, disabledLore, SpigotPrison.format("&c" + "Lapis_Ore Disabled"))); + gui.addButton(new Button(null, XMaterial.LAPIS_ORE, disabledLore, SpigotPrison.format("&cLapis_Ore Disabled"))); } if (afConfig.isFeatureBoolean(AutoFeatures.pickupSnowBall)) { - gui.addButton(new Button(null, XMaterial.SNOWBALL, 1, enabledLore, SpigotPrison.format("&a" + "Snow_Ball Enabled"))); + gui.addButton(new Button(null, XMaterial.SNOWBALL, 1, enabledLore, SpigotPrison.format("&aSnow_Ball Enabled"))); } else { - gui.addButton(new Button(null, XMaterial.SNOWBALL, 1, disabledLore, SpigotPrison.format("&c" + "Snow_Ball Disabled"))); + gui.addButton(new Button(null, XMaterial.SNOWBALL, 1, disabledLore, SpigotPrison.format("&cSnow_Ball Disabled"))); } if (afConfig.isFeatureBoolean(AutoFeatures.pickupGlowstoneDust)) { - gui.addButton(new Button(null, XMaterial.GLOWSTONE_DUST, enabledLore, SpigotPrison.format("&a" + "Glowstone_Dust Enabled"))); + gui.addButton(new Button(null, XMaterial.GLOWSTONE_DUST, enabledLore, SpigotPrison.format("&aGlowstone_Dust Enabled"))); } else { - gui.addButton(new Button(null, XMaterial.GLOWSTONE_DUST, disabledLore, SpigotPrison.format("&c" + "Glowstone_Dust Disabled"))); + gui.addButton(new Button(null, XMaterial.GLOWSTONE_DUST, disabledLore, SpigotPrison.format("&cGlowstone_Dust Disabled"))); } } else { Output.get().sendError(new SpigotPlayer(p), "An error occurred, the AutoFeatures Config is broken or missing!"); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoSmeltGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoSmeltGUI.java index 17468ac4b..059a4fa2d 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoSmeltGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoSmeltGUI.java @@ -7,6 +7,7 @@ import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; @@ -30,29 +31,29 @@ public void open() { int dimension = 36; PrisonGUI gui = new PrisonGUI(p, dimension, "&3AutoFeatures -> AutoSmelt"); - ButtonLore enabledLore = new ButtonLore(messages.getString("Lore.ShiftAndRightClickToDisable"), null); - ButtonLore disabledLore = new ButtonLore(messages.getString("Lore.RightClickToEnable"), null); - ButtonLore closeGUILore = new ButtonLore(messages.getString("Lore.ClickToClose"), null); + ButtonLore enabledLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_and_shift_to_disable), null); + ButtonLore disabledLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_enable), null); + ButtonLore closeGUILore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_close), null); - gui.addButton(new Button(35, XMaterial.RED_STAINED_GLASS_PANE, closeGUILore, SpigotPrison.format("&c" + "Close"))); + gui.addButton(new Button(35, XMaterial.RED_STAINED_GLASS_PANE, closeGUILore, SpigotPrison.format("&cClose"))); if(afConfig != null) { if (afConfig.isFeatureBoolean(AutoFeatures.smeltAllBlocks)) { - gui.addButton(new Button(null, XMaterial.LIME_STAINED_GLASS_PANE, enabledLore, SpigotPrison.format("&a" + "All_Ores Enabled"))); + gui.addButton(new Button(null, XMaterial.LIME_STAINED_GLASS_PANE, enabledLore, SpigotPrison.format("&aAll_Ores Enabled"))); } else { - gui.addButton(new Button(null, XMaterial.RED_STAINED_GLASS_PANE, disabledLore, SpigotPrison.format("&c" + "All_Ores Disabled"))); + gui.addButton(new Button(null, XMaterial.RED_STAINED_GLASS_PANE, disabledLore, SpigotPrison.format("&cAll_Ores Disabled"))); } if (afConfig.isFeatureBoolean(AutoFeatures.smeltGoldOre)) { - gui.addButton(new Button(null, XMaterial.GOLD_ORE, enabledLore, SpigotPrison.format("&a" + "Gold_Ore Enabled"))); + gui.addButton(new Button(null, XMaterial.GOLD_ORE, enabledLore, SpigotPrison.format("&aGold_Ore Enabled"))); } else { - gui.addButton(new Button(null, XMaterial.GOLD_ORE, disabledLore, SpigotPrison.format("&c" + "Gold_Ore Disabled"))); + gui.addButton(new Button(null, XMaterial.GOLD_ORE, disabledLore, SpigotPrison.format("&cGold_Ore Disabled"))); } if (afConfig.isFeatureBoolean(AutoFeatures.smeltIronOre)) { - gui.addButton(new Button(null, XMaterial.IRON_ORE, enabledLore, SpigotPrison.format("&a" + "Iron_Ore Enabled"))); + gui.addButton(new Button(null, XMaterial.IRON_ORE, enabledLore, SpigotPrison.format("&aIron_Ore Enabled"))); } else { - gui.addButton(new Button(null, XMaterial.IRON_ORE, disabledLore, SpigotPrison.format("&c" + "Iron_Ore Disabled"))); + gui.addButton(new Button(null, XMaterial.IRON_ORE, disabledLore, SpigotPrison.format("&cIron_Ore Disabled"))); } } else { Output.get().sendError(new SpigotPlayer(p), "An error occurred, the AutoFeatures Config is broken or missing!"); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksAdminGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksAdminGUI.java index 9878a3d5f..9ba2b3417 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksAdminGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksAdminGUI.java @@ -4,6 +4,7 @@ import org.bukkit.entity.Player; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.backpacks.BackpacksUtil; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; @@ -30,13 +31,13 @@ public void open(){ } int dimension = 27; - PrisonGUI gui = new PrisonGUI(p, dimension, "&3" + "Backpacks-Admin"); + PrisonGUI gui = new PrisonGUI(p, dimension, "&3Backpacks-Admin"); - ButtonLore lore = new ButtonLore(messages.getString("Lore.ClickToOpen"), null); + ButtonLore lore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open), null); gui.addButton(new Button(11, XMaterial.CHEST, lore, "&3Backpacks-List")); gui.addButton(new Button(15, XMaterial.PAPER, lore, "&3Backpack-Settings")); - gui.addButton(new Button(dimension -1, XMaterial.RED_STAINED_GLASS_PANE, new ButtonLore(messages.getString("Lore.ClickToClose"), null), "&c" + "Close")); + gui.addButton(new Button(dimension -1, XMaterial.RED_STAINED_GLASS_PANE, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_close), null), "&cClose")); gui.open(); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksAdminListGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksAdminListGUI.java index 9809d9eff..eee18f5d1 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksAdminListGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksAdminListGUI.java @@ -4,6 +4,7 @@ import org.bukkit.configuration.Configuration; import org.bukkit.entity.Player; import tech.mcprison.prison.spigot.backpacks.BackpacksUtil; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -19,10 +20,10 @@ public class BackpacksAdminListGUI extends SpigotGUIComponents { private final Player p; private final String playerBackpackName; private final Configuration backpacksData = BackpacksUtil.get().getBackpacksData(); - private final String loreShiftAndRightClickToDelete = messages.getString("Lore.ShiftAndRightClickToDelete"); - private final String loreInfo = messages.getString("Lore.Info"); - private final String lorePlayerOwner = messages.getString("Lore.PlayerOwner"); - private final String loreBackpackID = messages.getString("Lore.BackpackID"); + private final String loreShiftAndRightClickToDelete = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_and_shift_to_delete); + private final String loreInfo = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_info); + private final String lorePlayerOwner = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_owner); + private final String loreBackpackID = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_backpack_id); public BackpacksAdminListGUI(Player p, String playerBackpackName){ this.p = p; @@ -32,7 +33,7 @@ public BackpacksAdminListGUI(Player p, String playerBackpackName){ public void open(){ int dimension = 54; - PrisonGUI gui = new PrisonGUI(p, dimension, "&3" + "Backpacks-Admin-List"); + PrisonGUI gui = new PrisonGUI(p, dimension, "&3Backpacks-Admin-List"); Set playerUUID = backpacksData.getConfigurationSection("Inventories").getKeys(false); @@ -59,10 +60,10 @@ public void open(){ ButtonLore backpacksLore = new ButtonLore(createLore(loreShiftAndRightClickToDelete), createLore( loreInfo, - lorePlayerOwner + name, - loreBackpackID + id)); + lorePlayerOwner + " " + name, + loreBackpackID + " " + id)); - gui.addButton(new Button(backpacksFound, XMaterial.CHEST, backpacksLore, "&3" + "Backpack " + name + " " + id)); + gui.addButton(new Button(backpacksFound, XMaterial.CHEST, backpacksLore, "&3Backpack " + name + " " + id)); backpacksFound++; } } else { diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksAdminPlayerListGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksAdminPlayerListGUI.java index 5720ba444..09e7fc459 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksAdminPlayerListGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksAdminPlayerListGUI.java @@ -5,6 +5,7 @@ import org.bukkit.entity.Player; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.backpacks.BackpacksUtil; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; @@ -20,7 +21,7 @@ public class BackpacksAdminPlayerListGUI extends SpigotGUIComponents { private final Player p; private final Configuration backpacksData = BackpacksUtil.get().getBackpacksData(); - private final String clickToOpen = messages.getString("Lore.ClickToOpen"); + private final String clickToOpen = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open); public BackpacksAdminPlayerListGUI(Player p){ this.p = p; @@ -29,7 +30,7 @@ public BackpacksAdminPlayerListGUI(Player p){ public void open(){ int dimension = 54; - PrisonGUI gui = new PrisonGUI(p, dimension, "&3" + "Backpacks-Admin-Players"); + PrisonGUI gui = new PrisonGUI(p, dimension, "&3Backpacks-Admin-Players"); if (backpacksData.getConfigurationSection("Inventories") == null){ Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.BackPackListEmpty")); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksListPlayerGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksListPlayerGUI.java index 4e7c07e03..11037a97a 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksListPlayerGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksListPlayerGUI.java @@ -5,6 +5,7 @@ import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.backpacks.BackpacksUtil; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; @@ -32,13 +33,13 @@ public void open(){ int dimension = 54; PrisonGUI gui = new PrisonGUI(p, dimension, "&3" + p.getName() + " -> Backpacks"); - ButtonLore loreAddBackpackButton = new ButtonLore(createLore(messages.getString("Lore.ClickToAddBackpack")), createLore(messages.getString("Lore.ClickToAddBackpackInst0"), - messages.getString("Lore.ClickToAddBackpackInst1"), - messages.getString("Lore.ClickToAddBackpackInst2"), - messages.getString("Lore.ClickToAddBackpackInst3"))); + ButtonLore loreAddBackpackButton = new ButtonLore(createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_add_backpack)), createLore( + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_add_backpack_instruction_1), + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_add_backpack_instruction_2), + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_add_backpack_instruction_3))); // Global Strings. - String loreClickToOpen = messages.getString("Lore.ClickToOpen"); + String loreClickToOpen = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open); if (!BackpacksUtil.get().getBackpacksIDs(p).isEmpty()) { int slot = 0; @@ -63,7 +64,7 @@ public void open(){ gui.addButton(new Button(49, XMaterial.EMERALD_BLOCK, loreAddBackpackButton, "&aNew Backpack")); } - gui.addButton(new Button(dimension-1, XMaterial.RED_STAINED_GLASS_PANE, new ButtonLore(messages.getString("Lore.ClickToClose"), null), "&c" + "Close")); + gui.addButton(new Button(dimension-1, XMaterial.RED_STAINED_GLASS_PANE, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_close), null), "&cClose")); gui.open(); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/guiutility/ButtonLore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/guiutility/ButtonLore.java index 68754f71a..45dc560d5 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/guiutility/ButtonLore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/guiutility/ButtonLore.java @@ -99,7 +99,7 @@ public void setLoreAction(String descriptionAction){ * @param line - String. * */ public void addLineLoreAction(String line){ - this.descriptionAction.add(SpigotPrison.format(line)); + this.descriptionAction.add(SpigotPrison.format(colorIDAction + line)); } /** @@ -130,7 +130,7 @@ public void setLoreDescription(String description){ * @param line - String. * */ public void addLineLoreDescription(String line){ - this.description.add(SpigotPrison.format(line)); + this.description.add(SpigotPrison.format(colorIDDescription + line)); } /** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/guiutility/SpigotGUIComponents.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/guiutility/SpigotGUIComponents.java index 1ec47bc8c..3d3b30bfb 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/guiutility/SpigotGUIComponents.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/guiutility/SpigotGUIComponents.java @@ -20,6 +20,7 @@ import tech.mcprison.prison.output.Output; import tech.mcprison.prison.ranks.PrisonRanks; import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.ListenersPrisonManager; import tech.mcprison.prison.spigot.sellall.SellAllUtil; @@ -30,6 +31,7 @@ */ public abstract class SpigotGUIComponents { + public static NewMessagesConfig newMessages = getNewMessages(); public static Configuration messages = getMessages(); public static Configuration guiConfig = getGuiConfig(); public static Configuration sellAllConfig = getSellAll(); @@ -125,6 +127,13 @@ protected boolean checkRanks(Player p){ return module instanceof PrisonRanks; } + /** + * Get new Messages config. + * */ + protected static NewMessagesConfig getNewMessages(){ + return SpigotPrison.getInstance().getNewMessagesConfig(); + } + /** * Get Messages config. * */ @@ -162,6 +171,14 @@ public static AutoFeaturesFileConfig afConfig() { return AutoFeaturesWrapper.getInstance().getAutoFeaturesConfig(); } + /** + * Reload new Messages config for GUIs. + * */ + public static void updateNewMessages(){ + NewMessagesConfig.get().reload(); + newMessages = NewMessagesConfig.get(); + } + /** * Reload messages config for GUIs. * */ diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotBlocksListGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotBlocksListGUI.java index e4a6fefac..448c75b38 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotBlocksListGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotBlocksListGUI.java @@ -10,6 +10,7 @@ import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.internal.block.PrisonBlockTypes; import tech.mcprison.prison.spigot.SpigotUtil; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -39,7 +40,7 @@ public void open(){ // Create the inventory PrisonGUI gui = new PrisonGUI(p, dimension, "&3Mines -> BlocksList"); - ButtonLore lore = new ButtonLore(messages.getString("Lore.ClickToStartBlockSetup"), null); + ButtonLore lore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_start_block_setup), null); // This will skip all BlockTypes that are invalid for the versions of MC that the server is running: PrisonBlockTypes prisonBlockTypes = Prison.get().getPlatform().getPrisonBlockTypes(); @@ -63,10 +64,10 @@ public void open(){ prisonBlock.getBlockName().toUpperCase() + " &0" + mineName + " " + counter)); } if ( i < blockTypes.size() ) { - gui.addButton(new Button(53, XMaterial.BOOK, new ButtonLore(messages.getString("Lore.ClickToNextPage"), null), "&7Next &0" + mineName + " " + (i + 1))); + gui.addButton(new Button(53, XMaterial.BOOK, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_next_page), null), "&7Next &0" + mineName + " " + (i + 1))); } if ( i >= (pageSize * 2) ) { - gui.addButton(new Button(51, XMaterial.BOOK, new ButtonLore(messages.getString("Lore.ClickToPriorPage"), null), "&7Prior &0" + mineName + " " + (i - (pageSize * 2) - 1))); + gui.addButton(new Button(51, XMaterial.BOOK, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_prior_page), null), "&7Prior &0" + mineName + " " + (i - (pageSize * 2) - 1))); } // Open the inventory diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotBlocksMineListGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotBlocksMineListGUI.java index db8ea3918..7709696c7 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotBlocksMineListGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotBlocksMineListGUI.java @@ -6,6 +6,7 @@ import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.internal.block.PrisonBlockTypes; import tech.mcprison.prison.spigot.SpigotUtil; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -37,7 +38,7 @@ public void open(){ // Create the inventory PrisonGUI gui = new PrisonGUI(p, dimension, "&3Select -> ShowBlock"); - ButtonLore lore = new ButtonLore(messages.getString("Lore.ClickToSelect"), null); + ButtonLore lore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_select), null); // This will skip all BlockTypes that are invalid for the versions of MC that the server is running: PrisonBlockTypes prisonBlockTypes = Prison.get().getPlatform().getPrisonBlockTypes(); @@ -61,10 +62,10 @@ public void open(){ prisonBlock.getBlockName().toUpperCase() + " " + mineName + " " + counter)); } if ( i < blockTypes.size() ) { - gui.addButton(new Button(53, XMaterial.BOOK, new ButtonLore(messages.getString("Lore.ClickToNextPage"), null), "&7Next " + mineName + " " + (i + 1))); + gui.addButton(new Button(53, XMaterial.BOOK, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_next_page), null), "&7Next " + mineName + " " + (i + 1))); } if ( i >= (pageSize * 2) ) { - gui.addButton(new Button(51, XMaterial.BOOK, new ButtonLore(messages.getString("Lore.ClickToPriorPage"), null), "&7Prior " + mineName + " " + (i - (pageSize * 2) - 1))); + gui.addButton(new Button(51, XMaterial.BOOK, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_prior_page), null), "&7Prior " + mineName + " " + (i - (pageSize * 2) - 1))); } // Open the inventory diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineBlockPercentageGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineBlockPercentageGUI.java index 8a430f6bd..16a16350d 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineBlockPercentageGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineBlockPercentageGUI.java @@ -6,6 +6,7 @@ import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.spigot.SpigotUtil; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -36,32 +37,32 @@ public void open() { int dimension = 45; PrisonGUI gui = new PrisonGUI(p, dimension, "&3MineInfo -> BlockPercentage"); - ButtonLore changeDecreaseValueLore = new ButtonLore(messages.getString("Lore.ClickToDecrease"), null); - ButtonLore confirmButtonLore = new ButtonLore(createLore(messages.getString("Lore.LeftClickToConfirm"), messages.getString("Lore.RightClickToCancel")), createLore(messages.getString("Lore.Percentage") + val)); - ButtonLore changeIncreaseValueLore = new ButtonLore(messages.getString("Lore.ClickToIncrease"), null); + ButtonLore changeDecreaseValueLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_decrease), null); + ButtonLore confirmButtonLore = new ButtonLore(createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_confirm), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_cancel)), createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_percentage) + " " + val)); + ButtonLore changeIncreaseValueLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_decrease), null); XMaterial decreaseMaterial = XMaterial.REDSTONE_BLOCK; // Decrease button - gui.addButton(new Button(1, decreaseMaterial, changeDecreaseValueLore, "&3" + mineName + " " + blockName + " " + val + " - 1" + " &0" + counter)); - gui.addButton(new Button(10, decreaseMaterial, 5, changeDecreaseValueLore, "&3" + mineName + " " + blockName + " " + val + " - 5" + " &0" + counter)); - gui.addButton(new Button(19, decreaseMaterial, 10, changeDecreaseValueLore, "&3" + mineName + " " + blockName + " " + val + " - 10" + " &0" + counter)); - gui.addButton(new Button(28, decreaseMaterial, 50, changeDecreaseValueLore, "&3" + mineName + " " + blockName + " " + val + " - 50" + " &0" + counter)); - gui.addButton(new Button(37, decreaseMaterial, changeDecreaseValueLore, "&3" + mineName + " " + blockName + " " + val + " - 100" + " &0" + counter)); + gui.addButton(new Button(1, decreaseMaterial, changeDecreaseValueLore, "&3" + mineName + " " + blockName + " " + val + " - 1 &0" + counter)); + gui.addButton(new Button(10, decreaseMaterial, 5, changeDecreaseValueLore, "&3" + mineName + " " + blockName + " " + val + " - 5 &0" + counter)); + gui.addButton(new Button(19, decreaseMaterial, 10, changeDecreaseValueLore, "&3" + mineName + " " + blockName + " " + val + " - 10 &0" + counter)); + gui.addButton(new Button(28, decreaseMaterial, 50, changeDecreaseValueLore, "&3" + mineName + " " + blockName + " " + val + " - 50 &0" + counter)); + gui.addButton(new Button(37, decreaseMaterial, changeDecreaseValueLore, "&3" + mineName + " " + blockName + " " + val + " - 100 &0" + counter)); - gui.addButton(new Button(22, XMaterial.CLOCK, 1, confirmButtonLore, "&3" + "Confirm: " + mineName + " " + blockName + " " + val + " &0" + counter)); + gui.addButton(new Button(22, XMaterial.CLOCK, 1, confirmButtonLore, "&3Confirm: " + mineName + " " + blockName + " " + val + " &0" + counter)); XMaterial increaseMat = XMaterial.EMERALD_BLOCK; // Increase button - gui.addButton(new Button(7, increaseMat, changeIncreaseValueLore, "&3" + mineName + " " + blockName + " " + val + " + 1" + " &0" + counter)); - gui.addButton(new Button(16, increaseMat, 5, changeIncreaseValueLore, "&3" + mineName + " " + blockName + " " + val + " + 5" + " &0" + counter)); - gui.addButton(new Button(25, increaseMat, 10, changeIncreaseValueLore, "&3" + mineName + " " + blockName + " " + val + " + 10" + " &0" + counter)); - gui.addButton(new Button(34, increaseMat, 50, changeIncreaseValueLore, "&3" + mineName + " " + blockName + " " + val + " + 50" + " &0" + counter)); - gui.addButton(new Button(43, increaseMat, changeIncreaseValueLore, "&3" + mineName + " " + blockName + " " + val + " + 100" + " &0" + counter)); + gui.addButton(new Button(7, increaseMat, changeIncreaseValueLore, "&3" + mineName + " " + blockName + " " + val + " + 1 &0" + counter)); + gui.addButton(new Button(16, increaseMat, 5, changeIncreaseValueLore, "&3" + mineName + " " + blockName + " " + val + " + 5 &0" + counter)); + gui.addButton(new Button(25, increaseMat, 10, changeIncreaseValueLore, "&3" + mineName + " " + blockName + " " + val + " + 10 &0" + counter)); + gui.addButton(new Button(34, increaseMat, 50, changeIncreaseValueLore, "&3" + mineName + " " + blockName + " " + val + " + 50 &0" + counter)); + gui.addButton(new Button(43, increaseMat, changeIncreaseValueLore, "&3" + mineName + " " + blockName + " " + val + " + 100 &0" + counter)); // Close gui: - gui.addButton(new Button(40, XMaterial.RED_STAINED_GLASS_PANE, new ButtonLore(messages.getString("Lore.ClickToClose"), null), "&c" + "Close" + " &0" + mineName + " " + counter)); + gui.addButton(new Button(40, XMaterial.RED_STAINED_GLASS_PANE, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_close), null), "&cClose &0" + mineName + " " + counter)); // Show the selected block at the top center position: XMaterial xMat = SpigotUtil.getXMaterial( blockName ); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineInfoGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineInfoGUI.java index 3b8397aa2..c13203450 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineInfoGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineInfoGUI.java @@ -8,6 +8,7 @@ import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.SpigotUtil; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -34,34 +35,35 @@ public void open(){ PrisonGUI gui = new PrisonGUI(p, dimension, SpigotPrison.format("&3Mines -> MineInfo")); ButtonLore resetMineLore = new ButtonLore(createLore( - messages.getString("Lore.LeftClickToReset"), - messages.getString("Lore.RightClickToToggle"), - messages.getString("Lore.ShiftAndRightClickToToggle")), - createLore(messages.getString("Lore.SkipReset1"), - messages.getString("Lore.SkipReset2"), - messages.getString("Lore.SkipReset3"), - messages.getString("Lore.ZeroBlocksReset1"), - messages.getString("Lore.ZeroBlocksReset2"), - messages.getString("Lore.ZeroBlocksReset3"))); + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_left_to_reset), + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_toggle), + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_and_shift_to_toggle)), + createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_skip_reset_instruction_1), + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_skip_reset_instruction_2), + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_skip_reset_instruction_3), + "", + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_set_mine_delay_instruction_1), + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_set_mine_delay_instruction_2), + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_set_mine_delay_instruction_3))); - ButtonLore mineSpawnLore = new ButtonLore(messages.getString("Lore.ClickToUse"), messages.getString("Lore.SpawnPoint2")); - ButtonLore minesNotificationsLore = new ButtonLore(messages.getString("Lore.ClickToOpen"), messages.getString("Lore.Notifications")); - ButtonLore minesTpLore = new ButtonLore(messages.getString("Lore.ClickToTeleport"), messages.getString("Lore.Tp")); - ButtonLore blocksOfTheMineLore = new ButtonLore(messages.getString("Lore.ClickToOpen"), messages.getString("Lore.Blocks2")); - ButtonLore mineResetTimeLore = new ButtonLore(createLore(messages.getString("Lore.ClickToOpen")), createLore(messages.getString("Lore.ManageResetTime"), - messages.getString("Lore.ResetTime") + mine.getResetTime())); - ButtonLore mineRenameLore = new ButtonLore(messages.getString("Lore.ClickToRename"), messages.getString("Lore.MineName") + mineName); - ButtonLore closeGUILore = new ButtonLore(messages.getString("Lore.ClickToClose"), null); + ButtonLore mineSpawnLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_use), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_spawnpoint)); + ButtonLore minesNotificationsLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_edit)); + ButtonLore minesTpLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_teleport), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_tp_to_mine)); + ButtonLore blocksOfTheMineLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_blocks)); + ButtonLore mineResetTimeLore = new ButtonLore(createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open)), createLore( + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_reset_time) + " &7" + mine.getResetTime())); + ButtonLore mineRenameLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_rename), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_minename) + " " + mineName); + ButtonLore closeGUILore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_close), null); // Create the button, set the material, amount, lore and name - gui.addButton(new Button(dimension-1, XMaterial.RED_STAINED_GLASS_PANE, closeGUILore, SpigotPrison.format("&c" + "Close"))); - gui.addButton(new Button(10, XMaterial.EMERALD_BLOCK, resetMineLore, SpigotPrison.format("&3" + "Reset_Mine: " + mineName))); - gui.addButton(new Button(12, XMaterial.COMPASS, mineSpawnLore, SpigotPrison.format("&3" + "Mine_Spawn: " + mineName))); - gui.addButton(new Button(14, XMaterial.OAK_SIGN, minesNotificationsLore, SpigotPrison.format("&3" + "Mine_notifications: " + mineName))); - gui.addButton(new Button(16, XMaterial.ARROW, minesTpLore, SpigotPrison.format("&3" + "TP_to_the_Mine: " + mineName))); - gui.addButton(new Button(28, XMaterial.COAL_ORE, blocksOfTheMineLore, SpigotPrison.format("&3" + "Blocks_of_the_Mine: " + mineName))); - gui.addButton(new Button(30, XMaterial.CLOCK, 1, mineResetTimeLore, SpigotPrison.format("&3" + "Reset_Time: " + mineName))); - gui.addButton(new Button(32 ,XMaterial.FEATHER, mineRenameLore, SpigotPrison.format("&3" + "Mine_Name: " + mineName))); + gui.addButton(new Button(dimension-1, XMaterial.RED_STAINED_GLASS_PANE, closeGUILore, SpigotPrison.format("&cClose"))); + gui.addButton(new Button(10, XMaterial.EMERALD_BLOCK, resetMineLore, SpigotPrison.format("&3Reset_Mine: " + mineName))); + gui.addButton(new Button(12, XMaterial.COMPASS, mineSpawnLore, SpigotPrison.format("&3Mine_Spawn: " + mineName))); + gui.addButton(new Button(14, XMaterial.OAK_SIGN, minesNotificationsLore, SpigotPrison.format("&3Mine_notifications: " + mineName))); + gui.addButton(new Button(16, XMaterial.ARROW, minesTpLore, SpigotPrison.format("&3TP_to_the_Mine: " + mineName))); + gui.addButton(new Button(28, XMaterial.COAL_ORE, blocksOfTheMineLore, SpigotPrison.format("&3Blocks_of_the_Mine: " + mineName))); + gui.addButton(new Button(30, XMaterial.CLOCK, 1, mineResetTimeLore, SpigotPrison.format("&3Reset_Time: " + mineName))); + gui.addButton(new Button(32 ,XMaterial.FEATHER, mineRenameLore, SpigotPrison.format("&3Mine_Name: " + mineName))); // Mine show Item of Player's GUI aka /gui mines. XMaterial xMaterial = XMaterial.COAL_ORE; @@ -74,15 +76,15 @@ public void open(){ } // Lore - ButtonLore mineShowItemLore = new ButtonLore(createLore(messages.getString("Lore.ClickToEdit")), createLore( - messages.getString("Lore.ShowItem") + xMaterial.name(), - messages.getString("Lore.ShowItemDescription"), - messages.getString("Lore.ShowItemDescription2"), - messages.getString("Lore.ShowItemDescription3") + ButtonLore mineShowItemLore = new ButtonLore(createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_edit)), createLore( + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_show_item) + " &7" + xMaterial.name(), + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_show_item_description_1), + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_show_item_description_2), + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_show_item_description_3) )); // ItemStack - gui.addButton(new Button(34, xMaterial, mineShowItemLore, SpigotPrison.format("&3Mine_Show_Item: ") + mineName)); + gui.addButton(new Button(34, xMaterial, mineShowItemLore, "&3Mine_Show_Item: " + mineName)); // Opens the inventory gui.open(); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineNotificationRadiusGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineNotificationRadiusGUI.java index 103939aa2..88dc77b01 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineNotificationRadiusGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineNotificationRadiusGUI.java @@ -2,6 +2,7 @@ import com.cryptomorin.xseries.XMaterial; import org.bukkit.entity.Player; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -30,11 +31,11 @@ public void open() { int dimension = 45; PrisonGUI gui = new PrisonGUI(p, dimension, "&3MineNotifications -> Radius"); - ButtonLore changeDecreaseValueLore = new ButtonLore(messages.getString("Lore.ClickToDecrease"), null); - ButtonLore confirmButtonLore = new ButtonLore(createLore(messages.getString("Lore.LeftClickToConfirm")), createLore( - messages.getString("Lore.Radius") + val, - messages.getString("Lore.RightClickToCancel"))); - ButtonLore changeIncreaseValueLore = new ButtonLore(messages.getString("Lore.ClickToIncrease"), null); + ButtonLore changeDecreaseValueLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_decrease), null); + ButtonLore confirmButtonLore = new ButtonLore(createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_left_to_confirm)), createLore( + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_radius) + " " + val, + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_cancel))); + ButtonLore changeIncreaseValueLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_increase), null); // XMaterials. XMaterial decreaseMat = XMaterial.REDSTONE_BLOCK; @@ -49,7 +50,7 @@ public void open() { gui.addButton(new Button(37, decreaseMat, changeDecreaseValueLore, "&3" + mineName + " " + val + " - 100 " + typeNotification)); // Confirm button. - gui.addButton(new Button(22, watch, confirmButtonLore, "&3" + "Confirm: " + mineName + " " + val + " " + typeNotification)); + gui.addButton(new Button(22, watch, confirmButtonLore, "&3Confirm: " + mineName + " " + val + " " + typeNotification)); // Increase buttons. gui.addButton(new Button(7, increaseMat, changeIncreaseValueLore, "&3" + mineName + " " + val + " + 1 " + typeNotification)); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineNotificationsGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineNotificationsGUI.java index fc8059fa9..f5afba8d9 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineNotificationsGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineNotificationsGUI.java @@ -6,6 +6,7 @@ import tech.mcprison.prison.mines.PrisonMines; import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -35,29 +36,29 @@ public void open() { Mine m = pMines.getMine(mineName); String enabledOrDisabled = m.getNotificationMode().name(); - ButtonLore modeWithinLore = new ButtonLore(messages.getString("Lore.ClickToChoose"), messages.getString("Lore.ActivateWithinMode")); - ButtonLore modeRadiusLore = new ButtonLore(messages.getString("Lore.ClickToChoose"), messages.getString("Lore.ActivateRadiusMode")); - ButtonLore disabledModeLore = new ButtonLore(messages.getString("Lore.ClickToChoose"), messages.getString("Lore.DisableNotifications")); - ButtonLore closeGUILore = new ButtonLore(messages.getString("Lore.ClickToClose"), null); + ButtonLore modeWithinLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_select), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_enable_within_mode)); + ButtonLore modeRadiusLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_select), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_enable_radius_mode)); + ButtonLore disabledModeLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_select), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_disable_notifications)); + ButtonLore closeGUILore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_close), null); // Add button. - gui.addButton(new Button(26, XMaterial.RED_STAINED_GLASS_PANE, closeGUILore, "&c" + "Close")); + gui.addButton(new Button(26, XMaterial.RED_STAINED_GLASS_PANE, closeGUILore, "&cClose")); // Add the selected lore to the mode used if (enabledOrDisabled.equalsIgnoreCase("disabled")){ // Add the selected lore - disabledModeLore.addLineLoreDescription(SpigotPrison.format(messages.getString("Lore.Selected"))); + disabledModeLore.addLineLoreDescription(SpigotPrison.format(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_selected))); } else if (enabledOrDisabled.equalsIgnoreCase("within")){ // Add the selected lore - modeWithinLore.addLineLoreDescription(SpigotPrison.format(messages.getString("Lore.Selected"))); + modeWithinLore.addLineLoreDescription(SpigotPrison.format(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_selected))); } else if (enabledOrDisabled.equalsIgnoreCase("radius")){ // Add the selected lore - modeRadiusLore.addLineLoreDescription(SpigotPrison.format(messages.getString("Lore.Selected"))); + modeRadiusLore.addLineLoreDescription(SpigotPrison.format(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_selected))); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineResetTimeGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineResetTimeGUI.java index f37fffcc1..3f43c71f8 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineResetTimeGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineResetTimeGUI.java @@ -2,6 +2,7 @@ import com.cryptomorin.xseries.XMaterial; import org.bukkit.entity.Player; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -29,9 +30,9 @@ public void open() { PrisonGUI gui = new PrisonGUI(p, dimension, "&3MineInfo -> ResetTime"); - ButtonLore changeDecreaseValueLore = new ButtonLore(messages.getString("Lore.ClickToDecrease"), null); - ButtonLore confirmButtonLore = new ButtonLore(createLore(messages.getString("Lore.LeftClickToConfirm"), messages.getString("Lore.RightClickToCancel")), createLore(messages.getString("Lore.Time") + val)); - ButtonLore changeIncreaseValueLore = new ButtonLore(messages.getString("Lore.ClickToIncrease"), null); + ButtonLore changeDecreaseValueLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_decrease), null); + ButtonLore confirmButtonLore = new ButtonLore(createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_left_to_confirm), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_cancel)), createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_reset_time) + " " + val)); + ButtonLore changeIncreaseValueLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_increase), null); // XMaterials. XMaterial decreaseMat = XMaterial.REDSTONE_BLOCK; @@ -46,7 +47,7 @@ public void open() { gui.addButton(new Button(37, decreaseMat, changeDecreaseValueLore, "&3" + mineName + " " + val + " - 100")); // Create a button and set the position - gui.addButton(new Button(22, watch, confirmButtonLore, "&3" + "Confirm: " + mineName + " " + val)); + gui.addButton(new Button(22, watch, confirmButtonLore, "&3Confirm: " + mineName + " " + val)); // Increase button gui.addButton(new Button(7, increaseMat, changeIncreaseValueLore, "&3" + mineName + " " + val + " + 1")); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesBlocksGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesBlocksGUI.java index ea300cd77..492bdeb6c 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesBlocksGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesBlocksGUI.java @@ -1,7 +1,5 @@ package tech.mcprison.prison.spigot.gui.mine; -import java.util.List; - import com.cryptomorin.xseries.XMaterial; import org.bukkit.entity.Player; @@ -11,6 +9,7 @@ import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.SpigotUtil; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -26,11 +25,11 @@ public class SpigotMinesBlocksGUI extends SpigotGUIComponents { private final String mineName; // Global Strings. - private final String loreShiftRightClickToDelete = messages.getString("Lore.ShiftAndRightClickToDelete"); - private final String loreClickToEditBlock = messages.getString("Lore.ClickToEditBlock"); - private final String loreInfo = messages.getString("Lore.Info"); - private final String loreChance = messages.getString("Lore.Chance"); - private final String loreBlockType = messages.getString("Lore.BlockType"); + private final String loreShiftRightClickToDelete = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_and_shift_to_delete); + private final String loreClickToEditBlock = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_edit); + private final String loreInfo = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_info); + private final String loreChance = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_chance); + private final String loreBlockType = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_blocktype); public SpigotMinesBlocksGUI(Player p, String mineName){ this.p = p; @@ -46,10 +45,10 @@ public void open(){ Mine m = PrisonMines.getInstance().getMine(mineName); boolean useNewBlockModel = Prison.get().getPlatform().isUseNewPrisonBlockModel(); - ButtonLore addBlockLore = new ButtonLore(messages.getString("Lore.ClickToAddBlock"), null); + ButtonLore addBlockLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_add), null); // Add the button to the GUI. - gui.addButton(new Button(dimension - 1, XMaterial.LIME_STAINED_GLASS_PANE, addBlockLore, "&a" + "Add" + " " + mineName)); + gui.addButton(new Button(dimension - 1, XMaterial.LIME_STAINED_GLASS_PANE, addBlockLore, "&aAdd " + mineName)); if (useNewBlockModel) { diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesConfirmGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesConfirmGUI.java index cf08ec495..1d95b3ebc 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesConfirmGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesConfirmGUI.java @@ -2,6 +2,7 @@ import com.cryptomorin.xseries.XMaterial; import org.bukkit.entity.Player; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -26,13 +27,13 @@ public void open(){ int dimension = 9; PrisonGUI gui = new PrisonGUI(p, dimension, "&3Mines -> Delete"); - ButtonLore confirmLore = new ButtonLore(messages.getString("Lore.ClickToConfirm"), null); - ButtonLore cancelLore = new ButtonLore(messages.getString("Lore.ClickToCancel"), null); + ButtonLore confirmLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_confirm), null); + ButtonLore cancelLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_cancel), null); // Position of the button - gui.addButton(new Button(2, XMaterial.EMERALD_BLOCK, confirmLore, "&3" + "Confirm: " + mineName)); - gui.addButton(new Button(6, XMaterial.REDSTONE_BLOCK, cancelLore, "&3" + "Cancel: " + mineName)); + gui.addButton(new Button(2, XMaterial.EMERALD_BLOCK, confirmLore, "&3Confirm: " + mineName)); + gui.addButton(new Button(6, XMaterial.REDSTONE_BLOCK, cancelLore, "&3Cancel: " + mineName)); // Open GUI. gui.open(); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesGUI.java index b9103df84..aab8b94cf 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesGUI.java @@ -9,6 +9,7 @@ import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.mines.data.PrisonSortableResults; import tech.mcprison.prison.mines.managers.MineManager.MineSortOrder; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.gui.PrisonSetupGUI; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; @@ -16,7 +17,6 @@ import tech.mcprison.prison.spigot.gui.guiutility.SpigotGUIComponents; import java.text.DecimalFormat; -import java.util.List; /** * @author GABRYCA @@ -54,15 +54,15 @@ public void open(){ PrisonGUI gui = new PrisonGUI(p, dimension, "&3MinesManager -> Mines"); // Global Strings. - String loreLeftClickOpen = messages.getString("Lore.LeftClickToOpen"); - String loreShiftRightClickToDelete = messages.getString("Lore.ShiftAndRightClickToDelete"); - String loreInfo = messages.getString("Lore.Info"); - String loreWorld = messages.getString("Lore.World"); - String loreSpawnPoint = messages.getString("Lore.SpawnPoint"); - String loreResetTime = messages.getString("Lore.ResetTime"); - String loreSizeOfMine = messages.getString("Lore.SizeOfMine"); - String loreVolume = messages.getString("Lore.Volume"); - String loreBlocks = messages.getString("Lore.Blocks"); + String loreLeftClickOpen = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_left_to_open); + String loreShiftRightClickToDelete = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_and_shift_to_delete); + String loreInfo = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_info); + String loreWorld = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_world); + String loreSpawnPoint = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_spawnpoint); + String loreResetTime = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_reset_time); + String loreSizeOfMine = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_size); + String loreVolume = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_volume); + String loreBlocks = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_blocks); // Global boolean. boolean useNewBlockModel = Prison.get().getPlatform().isUseNewPrisonBlockModel(); @@ -79,19 +79,19 @@ public void open(){ ), createLore(loreInfo)); // Add a lore - minesLore.addLineLoreDescription(loreWorld + m.getWorldName()); + minesLore.addLineLoreDescription("&7" + loreWorld + " &b" + m.getWorldName()); String spawnPoint = m.getSpawn() != null ? m.getSpawn().toBlockCoordinates() : "&cnot set"; - minesLore.addLineLoreDescription(loreSpawnPoint + spawnPoint); - minesLore.addLineLoreDescription(loreResetTime + m.getResetTime()); + minesLore.addLineLoreDescription("&7" + loreSpawnPoint + " &b" + spawnPoint); + minesLore.addLineLoreDescription("&7" + loreResetTime + " &b" + m.getResetTime()); if (!m.isVirtual()) { // Add a lore - minesLore.addLineLoreDescription(loreSizeOfMine + m.getBounds().getDimensions()); - minesLore.addLineLoreDescription(loreVolume + m.getBounds().getTotalBlockCount()); + minesLore.addLineLoreDescription("&7" + loreSizeOfMine + " &b" + m.getBounds().getDimensions()); + minesLore.addLineLoreDescription("&7" + loreVolume + " &b" + m.getBounds().getTotalBlockCount()); } // Add a lore - minesLore.addLineLoreDescription(loreBlocks); + minesLore.addLineLoreDescription("&7" + loreBlocks); // Init some variables and do the actions DecimalFormat dFmt = new DecimalFormat("##0.00"); @@ -126,10 +126,10 @@ public void open(){ } if (i < mines.getSortedList().size()) { - gui.addButton(new Button(53, XMaterial.BOOK, new ButtonLore(messages.getString("Lore.ClickToNextPage"), null), "&7Next " + (i + 1))); + gui.addButton(new Button(53, XMaterial.BOOK, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_next_page), null), "&7Next " + (i + 1))); } if (i >= (pageSize * 2)) { - gui.addButton(new Button(51, XMaterial.BOOK, new ButtonLore(messages.getString("Lore.ClickToPriorPage"), null), "&7Prior " + (i - (pageSize * 2) - 1))); + gui.addButton(new Button(51, XMaterial.BOOK, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_prior_page), null), "&7Prior " + (i - (pageSize * 2) - 1))); } // Open the GUI. diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotPlayerMinesGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotPlayerMinesGUI.java index 75e82358d..97531b68b 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotPlayerMinesGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotPlayerMinesGUI.java @@ -13,6 +13,7 @@ import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.SpigotUtil; import tech.mcprison.prison.spigot.configs.GuiConfig; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; @@ -28,9 +29,9 @@ public class SpigotPlayerMinesGUI extends SpigotGUIComponents { private final Player p; private final SpigotPlayer spigotPlayer; private final String permissionWarpPlugin = guiConfig.getString("Options.Mines.PermissionWarpPlugin"); - private final String statusUnlockedMine = messages.getString("Lore.StatusUnlockedMine"); - private final String clickToTeleport = messages.getString("Lore.ClickToTeleport"); - private final String statusLockedMine = messages.getString("Lore.StatusLockedMine"); + private final String statusUnlockedMine = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_unlocked); + private final String clickToTeleport = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_teleport); + private final String statusLockedMine = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_locked); public SpigotPlayerMinesGUI(Player p) { this.p = p; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotConfirmPrestigeGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotConfirmPrestigeGUI.java index a91862405..c6df32492 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotConfirmPrestigeGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotConfirmPrestigeGUI.java @@ -3,6 +3,7 @@ import com.cryptomorin.xseries.XMaterial; import org.bukkit.entity.Player; import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -25,17 +26,17 @@ public void open(){ int dimension = 9; PrisonGUI gui = new PrisonGUI(p, dimension, "&3Prestige -> Confirmation"); - ButtonLore confirmLore = new ButtonLore(createLore(messages.getString("Lore.ClickToConfirm")), createLore( - messages.getString("Lore.PrestigeWarning"), - messages.getString("Lore.PrestigeWarning2"), - messages.getString("Lore.PrestigeWarning3"))); + ButtonLore confirmLore = new ButtonLore(createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_confirm)), createLore( + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_prestige_warning_1), + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_prestige_warning_2), + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_prestige_warning_3))); - ButtonLore cancelLore = new ButtonLore(messages.getString("Lore.ClickToCancel"), null); + ButtonLore cancelLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_cancel), null); // Create the button, set up the material, amount, lore and name - gui.addButton(new Button(2, XMaterial.EMERALD_BLOCK, confirmLore, SpigotPrison.format("&3" + "Confirm: Prestige"))); - gui.addButton(new Button(6, XMaterial.REDSTONE_BLOCK, cancelLore, SpigotPrison.format("&3" + "Cancel: Don't Prestige"))); + gui.addButton(new Button(2, XMaterial.EMERALD_BLOCK, confirmLore, SpigotPrison.format("&3Confirm: Prestige"))); + gui.addButton(new Button(6, XMaterial.REDSTONE_BLOCK, cancelLore, SpigotPrison.format("&3Cancel: Don't Prestige"))); gui.open(); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotLaddersGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotLaddersGUI.java index ba29381a2..49015eecf 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotLaddersGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotLaddersGUI.java @@ -7,6 +7,7 @@ import tech.mcprison.prison.ranks.data.RankLadder; import tech.mcprison.prison.ranks.managers.LadderManager; import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; @@ -49,7 +50,7 @@ public void open(){ PrisonGUI gui = new PrisonGUI(p, dimension, "&3RanksManager -> Ladders"); - ButtonLore laddersLore = new ButtonLore(messages.getString("Lore.ClickToOpen"), messages.getString("Lore.ShiftAndRightClickToDelete")); + ButtonLore laddersLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_and_shift_to_delete)); // Only loop over the blocks that we need to show: int i = counter; @@ -62,10 +63,10 @@ public void open(){ } if (i < lm.getLadders().size()) { - gui.addButton(new Button(53, XMaterial.BOOK, 1, new ButtonLore(messages.getString("Lore.ClickToNextPage"), null), "&7Next " + (i + 1))); + gui.addButton(new Button(53, XMaterial.BOOK, 1, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_next_page), null), "&7Next " + (i + 1))); } if (i >= (pageSize * 2)) { - gui.addButton(new Button(51, XMaterial.BOOK, 1, new ButtonLore(messages.getString("Lore.ClickToPriorPage"), null), + gui.addButton(new Button(51, XMaterial.BOOK, 1, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_prior_page), null), "&7Prior " + (i - (pageSize * 2) - 1))); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerPrestigesGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerPrestigesGUI.java index 58f69fc15..281094c69 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerPrestigesGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerPrestigesGUI.java @@ -21,6 +21,7 @@ import tech.mcprison.prison.ranks.managers.LadderManager; import tech.mcprison.prison.ranks.managers.PlayerManager; import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; @@ -145,8 +146,8 @@ public void open() { int hackyCounterEnchant = 0; // Global strings. - String loreInfo = messages.getString("Lore.Info"); - String lorePrice3 = messages.getString("Lore.Price3"); + String loreInfo = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_info); + String lorePrice3 = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_price); // Global boolean. boolean enchantmentEffectEnabled = getBoolean(guiConfig.getString("Options.Ranks.Enchantment_effect_current_rank")); @@ -164,7 +165,7 @@ public void open() { if (placeholderAPINotNull) { if (hackyCounterEnchant == 1) { hackyCounterEnchant++; - ranksLore.addLineLoreDescription(SpigotPrison.format(PlaceholderAPI.setPlaceholders(Bukkit.getOfflinePlayer(player.getUniqueId()), "%prison_rcb_prestiges%"))); + ranksLore.addLineLoreDescription(PlaceholderAPI.setPlaceholders(Bukkit.getOfflinePlayer(player.getUniqueId()), "%prison_rcb_prestiges%")); } } @@ -185,7 +186,7 @@ public void open() { rank = rank.getRankNext(); } - ButtonLore rankupLore = new ButtonLore(messages.getString("Lore.ClickToRankup"), messages.getString("Lore.IfYouHaveEnoughMoney")); + ButtonLore rankupLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_rankup), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_rankup_if_enough_money)); // Add button to GUI. gui.addButton(new Button(dimension - 5, XMaterial.EMERALD_BLOCK, rankupLore, SpigotPrison.format("&aPrestige"))); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerRanksGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerRanksGUI.java index 0ec63ded1..c8145878f 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerRanksGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerRanksGUI.java @@ -25,6 +25,7 @@ import tech.mcprison.prison.ranks.managers.LadderManager; import tech.mcprison.prison.ranks.managers.PlayerManager; import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; @@ -183,10 +184,10 @@ public void open() { rank = rank.getRankNext(); } - ButtonLore rankupLore = new ButtonLore(messages.getString("Lore.ClickToRankup"), messages.getString("Lore.IfYouHaveEnoughMoney")); + ButtonLore rankupLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_rankup), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_rankup_if_enough_money)); // Add button. - gui.addButton(new Button(dimension - 5, XMaterial.EMERALD_BLOCK, rankupLore, SpigotPrison.format(messages.getString("Lore.Rankup")))); + gui.addButton(new Button(dimension - 5, XMaterial.EMERALD_BLOCK, rankupLore, SpigotPrison.format(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_rankup)))); // Open GUI. gui.open(); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankManagerGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankManagerGUI.java index 7edf28111..e9a4f612c 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankManagerGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankManagerGUI.java @@ -12,6 +12,7 @@ import tech.mcprison.prison.ranks.data.Rank; import tech.mcprison.prison.ranks.data.RankPlayer; import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; @@ -39,9 +40,9 @@ public void open() { } int dimension = 27; - PrisonGUI gui = new PrisonGUI(p, dimension, "&3" + "Ranks -> RankManager"); + PrisonGUI gui = new PrisonGUI(p, dimension, "&3Ranks -> RankManager"); - ButtonLore rankupCommandsLore = new ButtonLore(messages.getString("Lore.ClickToOpen"), null); + ButtonLore rankupCommandsLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open), null); // Decimal Rank cost format. DecimalFormat formatDecimal = new DecimalFormat("###,##0.00"); @@ -57,22 +58,22 @@ public void open() { rankCost = "Can't get"; } - ButtonLore editPriceLore = new ButtonLore(createLore(messages.getString("Lore.ClickToOpen")), createLore( - messages.getString("Lore.Info"), - messages.getString("Lore.Price") + rankCost)); + ButtonLore editPriceLore = new ButtonLore(createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open)), createLore( + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_info), + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_price) + " " + rankCost)); - ButtonLore editTagLore = new ButtonLore(createLore(messages.getString("Lore.ClickToOpen")), createLore( - messages.getString("Lore.Info"), - messages.getString("Lore.Tag") + rank.getTag())); + ButtonLore editTagLore = new ButtonLore(createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open)), createLore( + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_info), + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_rank_tag) + " " + rank.getTag())); - ButtonLore closeGUILore = new ButtonLore(messages.getString("Lore.ClickToClose"), null); + ButtonLore closeGUILore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_close), null); // Create the button - gui.addButton(new Button(26, XMaterial.RED_STAINED_GLASS_PANE, closeGUILore, SpigotPrison.format("&c" + "Close"))); - gui.addButton(new Button(10, XMaterial.COMMAND_BLOCK_MINECART, rankupCommandsLore, SpigotPrison.format("&3" + "RankupCommands" + " " + rank.getName()))); - gui.addButton(new Button(13, XMaterial.GOLD_NUGGET, editPriceLore, SpigotPrison.format("&3" + "RankPrice" + " " + rank.getName()))); - gui.addButton(new Button(16, XMaterial.NAME_TAG, editTagLore, SpigotPrison.format("&3" + "RankTag" + " " + rank.getName()))); + gui.addButton(new Button(26, XMaterial.RED_STAINED_GLASS_PANE, closeGUILore, SpigotPrison.format("&cClose"))); + gui.addButton(new Button(10, XMaterial.COMMAND_BLOCK_MINECART, rankupCommandsLore, SpigotPrison.format("&3RankupCommands" + " " + rank.getName()))); + gui.addButton(new Button(13, XMaterial.GOLD_NUGGET, editPriceLore, SpigotPrison.format("&3RankPrice" + " " + rank.getName()))); + gui.addButton(new Button(16, XMaterial.NAME_TAG, editTagLore, SpigotPrison.format("&3RankTag" + " " + rank.getName()))); gui.open(); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankPriceGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankPriceGUI.java index 9a2320694..9af9b042e 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankPriceGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankPriceGUI.java @@ -3,6 +3,7 @@ import com.cryptomorin.xseries.XMaterial; import org.bukkit.entity.Player; import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -33,9 +34,9 @@ public void open() { int dimension = 45; PrisonGUI gui = new PrisonGUI(p, dimension, "&3RankManager -> RankPrice"); - ButtonLore changeDecreaseValueLore = new ButtonLore(messages.getString("Lore.ClickToDecrease"), null); - ButtonLore confirmButtonLore = new ButtonLore(createLore(messages.getString("Lore.LeftClickToConfirm"), messages.getString("Lore.RightClickToCancel")), createLore(messages.getString("Lore.Price2") + val)); - ButtonLore changeIncreaseValueLore = new ButtonLore(messages.getString("Lore.ClickToIncrease"), null); + ButtonLore changeDecreaseValueLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_decrease), null); + ButtonLore confirmButtonLore = new ButtonLore(createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_left_to_confirm), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_cancel)), createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_price) + " " + val)); + ButtonLore changeIncreaseValueLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_increase), null); XMaterial decreaseMat = XMaterial.REDSTONE_BLOCK; @@ -47,7 +48,7 @@ public void open() { gui.addButton(new Button(37, decreaseMat, changeDecreaseValueLore, SpigotPrison.format("&3" + rankName + " " + val + " - 10000"))); // Create a button and set the position - gui.addButton(new Button(22, XMaterial.TRIPWIRE_HOOK, confirmButtonLore, SpigotPrison.format("&3" + "Confirm: " + rankName + " " + val))); + gui.addButton(new Button(22, XMaterial.TRIPWIRE_HOOK, confirmButtonLore, SpigotPrison.format("&3Confirm: " + rankName + " " + val))); XMaterial increaseMat = XMaterial.EMERALD_BLOCK; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankUPCommandsGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankUPCommandsGUI.java index 9fa59f57a..e5dc8cf02 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankUPCommandsGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankUPCommandsGUI.java @@ -6,6 +6,7 @@ import tech.mcprison.prison.output.Output; import tech.mcprison.prison.ranks.data.Rank; import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; @@ -21,9 +22,9 @@ public class SpigotRankUPCommandsGUI extends SpigotGUIComponents { private final Rank rank; // Global Strings. - private final String shiftRightClickToDelete = messages.getString("Lore.ShiftAndRightClickToDelete"); - private final String loreInfo = messages.getString("Lore.Info"); - private final String loreCommand = messages.getString("Lore.Command"); + private final String shiftRightClickToDelete = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_and_shift_to_delete); + private final String loreInfo = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_info); + private final String loreCommand = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_command); public SpigotRankUPCommandsGUI(Player p, Rank rank) { this.p = p; @@ -66,7 +67,7 @@ public void open() { ButtonLore commandsLore = new ButtonLore(shiftRightClickToDelete, loreInfo); - commandsLore.addLineLoreDescription(SpigotPrison.format(loreCommand + command)); + commandsLore.addLineLoreDescription(SpigotPrison.format(loreCommand + " " + command)); // Add the button to the inventory gui.addButton(new Button(null, XMaterial.TRIPWIRE_HOOK, commandsLore, SpigotPrison.format("&3" + rank.getName() + " " + command))); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRanksGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRanksGUI.java index 9503fe16f..9e647048d 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRanksGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRanksGUI.java @@ -14,6 +14,7 @@ import tech.mcprison.prison.ranks.data.Rank; import tech.mcprison.prison.ranks.data.RankLadder; import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; @@ -52,17 +53,17 @@ public void open(){ int dimension = 54; int pageSize = 45; - PrisonGUI gui = new PrisonGUI(p, dimension, "&3" + "Ladders -> Ranks"); + PrisonGUI gui = new PrisonGUI(p, dimension, "&3Ladders -> Ranks"); // Global Strings. - String loreShiftRightClickDelete = messages.getString("Lore.ShiftAndRightClickToDelete"); - String loreClickToManageRank = messages.getString("Lore.ClickToManageRank"); - String loreInfo = messages.getString("Lore.Info"); - String loreId = messages.getString("Lore.Id"); - String loreName = messages.getString("Lore.Name"); - String loreTag2 = messages.getString("Lore.Tag2"); - String lorePrice3 = messages.getString("Lore.Price3"); - String lorePlayersWithRank = messages.getString("Lore.PlayersWithTheRank"); + String loreShiftRightClickDelete = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_and_shift_to_delete); + String loreClickToManageRank = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_manage_rank); + String loreInfo = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_info); + String loreId = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_id); + String loreName = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_name); + String loreTag2 = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_rank_tag); + String lorePrice3 = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_price); + String lorePlayersWithRank = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_players_at_rank); // Decimal Rank cost format. DecimalFormat formatDecimal = new DecimalFormat("###,##0.00"); @@ -84,10 +85,10 @@ public void open(){ // double ladderBaseRankMultiplier = PlayerRank.getLadderBaseRankdMultiplier( rank ); // Add the RankID Lore - ranksLore.addLineLoreDescription(SpigotPrison.format(loreId + rank.getId())); - ranksLore.addLineLoreDescription(SpigotPrison.format(loreName + rank.getName())); - ranksLore.addLineLoreDescription(SpigotPrison.format(loreTag2 + ChatColor.translateAlternateColorCodes('&', rank.getTag()))); - ranksLore.addLineLoreDescription(SpigotPrison.format(lorePrice3 + PlaceholdersUtil.formattedKmbtSISize(rawRankCost, formatDecimal, ""))); + ranksLore.addLineLoreDescription(SpigotPrison.format(loreId + " " + rank.getId())); + ranksLore.addLineLoreDescription(SpigotPrison.format(loreName + " " + rank.getName())); + ranksLore.addLineLoreDescription(SpigotPrison.format(loreTag2 + " " + ChatColor.translateAlternateColorCodes('&', rank.getTag()))); + ranksLore.addLineLoreDescription(SpigotPrison.format(lorePrice3 + " " + PlaceholdersUtil.formattedKmbtSISize(rawRankCost, formatDecimal, ""))); // Init a variable int playerCount = rank.getPlayers().size(); @@ -97,17 +98,17 @@ public void open(){ // .collect(Collectors.toList()); // Add the number of players with this rank - ranksLore.addLineLoreDescription(SpigotPrison.format(lorePlayersWithRank + playerCount)); + ranksLore.addLineLoreDescription(SpigotPrison.format(lorePlayersWithRank + " " + playerCount)); // Add the button to the inventory gui.addButton(new Button(i - counter, XMaterial.TRIPWIRE_HOOK, ranksLore, SpigotPrison.format("&3" + rank.getName()))); } if (i < ladder.get().getRanks().size()) { - gui.addButton(new Button(53, XMaterial.BOOK, 1, new ButtonLore(messages.getString("Lore.ClickToNextPage"), null), "&7Next " + (i + 1))); + gui.addButton(new Button(53, XMaterial.BOOK, 1, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_next_page), null), "&7Next " + (i + 1))); } if (i >= (pageSize * 2)) { - gui.addButton(new Button(51, XMaterial.BOOK, 1, new ButtonLore(messages.getString("Lore.ClickToPriorPage"), null), + gui.addButton(new Button(51, XMaterial.BOOK, 1, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_prior_page), null), "&7Prior " + (i - (pageSize * 2) - 1))); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllAdminAutoSellGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllAdminAutoSellGUI.java index 0cc736297..be95a8507 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllAdminAutoSellGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllAdminAutoSellGUI.java @@ -3,6 +3,7 @@ import com.cryptomorin.xseries.XMaterial; import org.bukkit.entity.Player; import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -26,7 +27,7 @@ public void open() { PrisonGUI gui = new PrisonGUI(p, dimension, "&3SellAll -> AutoSell"); - ButtonLore closeGUILore = new ButtonLore(messages.getString("Lore.ClickToClose"), null); + ButtonLore closeGUILore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_close), null); ButtonLore perUserToggleableLore = new ButtonLore(); ButtonLore enableDisableLore = new ButtonLore(); @@ -34,22 +35,22 @@ public void open() { Button enableDisableButton; if (sellAllConfig.getString("Options.Full_Inv_AutoSell_perUserToggleable").equalsIgnoreCase("true")){ - perUserToggleableLore.setLoreAction(messages.getString("Lore.ClickToDisable")); + perUserToggleableLore.setLoreAction(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_disable)); perUserToggleableButton = new Button(11, XMaterial.LIME_STAINED_GLASS_PANE, perUserToggleableLore, "&3PerUserToggleable"); } else { - perUserToggleableLore.setLoreAction(messages.getString("Lore.ClickToEnable")); + perUserToggleableLore.setLoreAction(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_enable)); perUserToggleableButton = new Button(11, XMaterial.RED_STAINED_GLASS_PANE, perUserToggleableLore, "&cPerUserToggleable-Disabled"); } if (sellAllConfig.getString("Options.Full_Inv_AutoSell").equalsIgnoreCase("true")){ - enableDisableLore.setLoreAction(messages.getString("Lore.ClickToDisable")); + enableDisableLore.setLoreAction(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_disable)); enableDisableButton = new Button(15, XMaterial.LIME_STAINED_GLASS_PANE, enableDisableLore, "&3AutoSell"); } else { - enableDisableLore.setLoreAction(messages.getString("Lore.ClickToEnable")); + enableDisableLore.setLoreAction(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_enable)); enableDisableButton = new Button(15, XMaterial.RED_STAINED_GLASS_PANE, enableDisableLore, "&cAutoSell-Disabled"); } - gui.addButton(new Button(dimension-1, XMaterial.RED_STAINED_GLASS_PANE, closeGUILore, SpigotPrison.format("&c" + "Close"))); + gui.addButton(new Button(dimension-1, XMaterial.RED_STAINED_GLASS_PANE, closeGUILore, SpigotPrison.format("&cClose"))); gui.addButton(perUserToggleableButton); gui.addButton(enableDisableButton); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllAdminBlocksGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllAdminBlocksGUI.java index 6ee1c3cee..d232d4824 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllAdminBlocksGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllAdminBlocksGUI.java @@ -5,6 +5,7 @@ import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.SpigotUtil; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; @@ -56,11 +57,11 @@ public void open() { Set items = sellAllConfig.getConfigurationSection("Items").getKeys(false); // Global strings. - String loreLine1 = messages.getString("Lore.RightClickToDelete"); - String loreLine2 = messages.getString("Lore.LeftClickToEdit"); - String lorePermission = messages.getString("Lore.Permission"); + String loreLine1 = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_delete); + String loreLine2 = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_left_to_edit); + String lorePermission = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_permission); String permissionSellAllBlock = sellAllConfig.getString("Options.Sell_Per_Block_Permission"); - String loreValue = messages.getString("Lore.Value"); + String loreValue = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_value); boolean sellAllPerBlockPermissionEnabled = getBoolean(sellAllConfig.getString("Options.Sell_Per_Block_Permission_Enabled")); @@ -71,11 +72,11 @@ public void open() { if (itemsRead >= startingItem) { if (startingItem != 0){ - gui.addButton(new Button(45, XMaterial.BOOK, new ButtonLore(messages.getString("Lore.ClickToPriorPage"), null), "&7Prior " + (startingItem - 45))); + gui.addButton(new Button(45, XMaterial.BOOK, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_prior_page), null), "&7Prior " + (startingItem - 45))); } if (itemsAdded >= 45){ - gui.addButton(new Button(53, XMaterial.BOOK, new ButtonLore(messages.getString("Lore.ClickToNextPage"), null), "&7Next " + (startingItem + itemsAdded))); + gui.addButton(new Button(53, XMaterial.BOOK, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_next_page), null), "&7Next " + (startingItem + itemsAdded))); } if (itemsAdded < 45) { diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllAdminGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllAdminGUI.java index 43b135d4b..ef6eb9154 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllAdminGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllAdminGUI.java @@ -4,6 +4,7 @@ import org.bukkit.entity.Player; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; @@ -33,12 +34,12 @@ public void open() { PrisonGUI gui = new PrisonGUI(p, dimension, "&3Prison -> SellAll-Admin"); - ButtonLore blocksLore = new ButtonLore(messages.getString("Lore.ClickToOpen"), null); - ButtonLore closeGUILore = new ButtonLore(messages.getString("Lore.ClickToClose"), null); - ButtonLore setCurrencyLore = new ButtonLore(createLore(messages.getString("Lore.ClickToEdit")), createLore( - messages.getString("Lore.SellAllActiveCurrency") + sellAllConfig.getString("Options.SellAll_Currency"), - messages.getString("Lore.SellAllCurrencyInfo"))); - ButtonLore multipliersLore = new ButtonLore(messages.getString("Lore.ClickToOpen"), messages.getString("Lore.PrestigeMultiplierInfoGUI")); + ButtonLore blocksLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open), null); + ButtonLore closeGUILore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_close), null); + ButtonLore setCurrencyLore = new ButtonLore(createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_edit)), createLore( + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_currency) + sellAllConfig.getString("Options.SellAll_Currency"), + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_edit))); + ButtonLore multipliersLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_edit)); ButtonLore autoSellLore = new ButtonLore(); ButtonLore sellAllDelayLore = new ButtonLore(); @@ -47,51 +48,51 @@ public void open() { if (sellAllConfig.getString("Options.Full_Inv_AutoSell").equalsIgnoreCase("true")){ autoSellLore.setLoreAction(createLore( - messages.getString("Lore.ClickToOpen"), - messages.getString("Lore.RightClickToDisable") + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open), + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_disable) )); autoSellButton = new Button(13, XMaterial.CHEST, autoSellLore, "&3AutoSell"); } else { - autoSellLore.setLoreAction(messages.getString("Lore.RightClickToEnable")); + autoSellLore.setLoreAction(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_enable)); autoSellButton = new Button(13, XMaterial.CHEST, autoSellLore, "&cAutoSell-Disabled"); } if (sellAllConfig.getString("Options.Sell_Delay_Enabled").equalsIgnoreCase("true")){ sellAllDelayLore.setLoreAction(createLore( - messages.getString("Lore.ClickToOpen"), - messages.getString("Lore.RightClickToDisable"))); + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open), + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_disable))); sellAllDelayLore.setLoreDescription(createLore( - messages.getString("Lore.DelaySellAll") + sellAllConfig.getString("Options.Sell_Delay_Seconds") + "s", - messages.getString("Lore.SellAllDelayInfo"), - messages.getString("Lore.SellAllDelayInfo2"))); + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_delay) + sellAllConfig.getString("Options.Sell_Delay_Seconds") + "s", + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_sellall_delay_use_1), + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_sellall_delay_use_2))); sellAllDelayButton = new Button(11, XMaterial.CLOCK, sellAllDelayLore, "&3Delay-Enabled"); } else { - sellAllDelayLore.setLoreAction(messages.getString("Lore.RightClickToEnable")); + sellAllDelayLore.setLoreAction(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_enable)); sellAllDelayLore.setLoreDescription(createLore( - messages.getString("Lore.SellAllDelayInfo"), - messages.getString("Lore.SellAllDelayInfo2"))); + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_sellall_delay_use_1), + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_sellall_delay_use_2))); sellAllDelayButton = new Button(11, XMaterial.CLOCK, sellAllDelayLore, "&cDelay-Disabled"); } try { if (sellAllConfig.getConfigurationSection("Multiplier") == null) { - multipliersLore.addLineLoreDescription(SpigotPrison.format(messages.getString("Lore.EmptyMultiplier"))); + multipliersLore.addLineLoreDescription(SpigotPrison.format(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_no_multipliers))); } else if (sellAllConfig.getConfigurationSection("Multiplier").getKeys(false).size() == 0) { - multipliersLore.addLineLoreDescription(SpigotPrison.format(messages.getString("Lore.EmptyMultiplier"))); + multipliersLore.addLineLoreDescription(SpigotPrison.format(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_no_multipliers))); } } catch (NullPointerException ex){ - multipliersLore.addLineLoreDescription(SpigotPrison.format(messages.getString("Lore.EmptyMultiplier"))); + multipliersLore.addLineLoreDescription(SpigotPrison.format(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_no_multipliers))); } gui.addButton(new Button(15, XMaterial.EMERALD, setCurrencyLore, SpigotPrison.format("&3SellAll-Currency"))); gui.addButton(new Button(8, XMaterial.PAPER, multipliersLore, SpigotPrison.format("&3Prestige-Multipliers"))); gui.addButton(new Button(0, XMaterial.DIAMOND_ORE, blocksLore, "&3Blocks-Shop")); - gui.addButton(new Button(dimension-1, XMaterial.RED_STAINED_GLASS_PANE, closeGUILore, SpigotPrison.format("&c" + "Close"))); + gui.addButton(new Button(dimension-1, XMaterial.RED_STAINED_GLASS_PANE, closeGUILore, SpigotPrison.format("&cClose"))); gui.addButton(sellAllDelayButton); gui.addButton(autoSellButton); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllDelayGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllDelayGUI.java index eae2665d3..6275aeb63 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllDelayGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllDelayGUI.java @@ -3,6 +3,7 @@ import com.cryptomorin.xseries.XMaterial; import org.bukkit.entity.Player; import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -29,9 +30,9 @@ public void open() { int dimension = 45; PrisonGUI gui = new PrisonGUI(p, dimension, "&3SellAll -> Delay"); - ButtonLore changeDecreaseValueLore = new ButtonLore(messages.getString("Lore.ClickToDecrease"), null); - ButtonLore confirmButtonLore = new ButtonLore(createLore(messages.getString("Lore.LeftClickToConfirm"), messages.getString("Lore.RightClickToCancel")), createLore(messages.getString("Lore.DelaySellAll") + val + "s")); - ButtonLore changeIncreaseValueLore = new ButtonLore(messages.getString("Lore.ClickToIncrease"), null); + ButtonLore changeDecreaseValueLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_decrease), null); + ButtonLore confirmButtonLore = new ButtonLore(createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_left_to_confirm), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_cancel)), createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_delay) + " " + val + "s")); + ButtonLore changeIncreaseValueLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_increase), null); XMaterial decreaseMat = XMaterial.REDSTONE_BLOCK; XMaterial increaseMat = XMaterial.EMERALD_BLOCK; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPlayerGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPlayerGUI.java index 5238edd6b..fa5b2df78 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPlayerGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPlayerGUI.java @@ -4,6 +4,7 @@ import org.bukkit.entity.Player; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.SpigotUtil; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; @@ -50,7 +51,7 @@ public void open() { Set items = sellAllConfig.getConfigurationSection("Items").getKeys(false); // Global strings. - String loreValue = messages.getString("Lore.Value"); + String loreValue = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_value); int itemsAdded = 0, itemsRead = 0; for (String key : items) { @@ -59,15 +60,15 @@ public void open() { if (itemsRead >= startingItem) { if (startingItem != 0){ - gui.addButton(new Button(45, XMaterial.BOOK, new ButtonLore(messages.getString("Lore.ClickToPriorPage"), null), "&7Prior " + (startingItem - 45))); + gui.addButton(new Button(45, XMaterial.BOOK, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_prior_page), null), "&7Prior " + (startingItem - 45))); } if (itemsAdded >= 45){ - gui.addButton(new Button(53, XMaterial.BOOK, new ButtonLore(messages.getString("Lore.ClickToNextPage"), null), "&7Next " + (startingItem + itemsAdded))); + gui.addButton(new Button(53, XMaterial.BOOK, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_next_page), null), "&7Next " + (startingItem + itemsAdded))); } if (itemsAdded < 45) { - gui.addButton(new Button(null, SpigotUtil.getXMaterial(sellAllConfig.getString("Items." + key + ".ITEM_ID")), new ButtonLore(null, loreValue + sellAllConfig.getString("Items." + key + ".ITEM_VALUE")), "&3" + sellAllConfig.getString("Items." + key + ".ITEM_ID"))); + gui.addButton(new Button(null, SpigotUtil.getXMaterial(sellAllConfig.getString("Items." + key + ".ITEM_ID")), new ButtonLore(null, loreValue + " " + sellAllConfig.getString("Items." + key + ".ITEM_VALUE")), "&3" + sellAllConfig.getString("Items." + key + ".ITEM_ID"))); itemsAdded++; } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPrestigesMultiplierGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPrestigesMultiplierGUI.java index a0f219efb..c50f844ca 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPrestigesMultiplierGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPrestigesMultiplierGUI.java @@ -2,6 +2,7 @@ import com.cryptomorin.xseries.XMaterial; import org.bukkit.entity.Player; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -33,10 +34,10 @@ public void open() { int pageSize = 45; // Global strings. - String lorePrestigeName = messages.getString("Lore.PrestigeName"); - String lorePrestigeMultiplier = messages.getString("Lore.PrestigeMultiplier"); - String loreClickToEdit = messages.getString("Lore.ClickToEdit"); - String loreClickToDelete = messages.getString("Lore.RightClickToDelete"); + String lorePrestigeName = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_prestige_name); + String lorePrestigeMultiplier = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_multiplier); + String loreClickToEdit = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_edit); + String loreClickToDelete = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_delete); // Only loop over the blocks that we need to show: int i = counter; @@ -50,8 +51,8 @@ public void open() { ButtonLore loreMult = new ButtonLore(createLore( loreClickToEdit, loreClickToDelete), createLore( - lorePrestigeName + sellAllConfig.getString("Multiplier." + prestige + ".PRESTIGE_NAME"), - lorePrestigeMultiplier + sellAllConfig.getString("Multiplier." + prestige + ".MULTIPLIER"))); + lorePrestigeName + " " + sellAllConfig.getString("Multiplier." + prestige + ".PRESTIGE_NAME"), + lorePrestigeMultiplier + " " + sellAllConfig.getString("Multiplier." + prestige + ".MULTIPLIER"))); gui.addButton(new Button(null, XMaterial.PAPER, loreMult, sellAllConfig.getString("Multiplier." + prestige + ".PRESTIGE_NAME"))); } @@ -60,10 +61,10 @@ public void open() { } if (i < sellAllConfig.getConfigurationSection("Multiplier").getKeys(false).size()) { - gui.addButton(new Button(53, XMaterial.BOOK, new ButtonLore(messages.getString("Lore.ClickToNextPage"), null), "&7Next " + (i + 1))); + gui.addButton(new Button(53, XMaterial.BOOK, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_next_page), null), "&7Next " + (i + 1))); } if (i >= (pageSize * 2)) { - gui.addButton(new Button(51, XMaterial.BOOK, new ButtonLore(messages.getString("Lore.ClickToPriorPage"), null), "&7Prior " + (i - (pageSize * 2) - 1))); + gui.addButton(new Button(51, XMaterial.BOOK, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_prior_page), null), "&7Prior " + (i - (pageSize * 2) - 1))); } gui.open(); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPrestigesSetMultiplierGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPrestigesSetMultiplierGUI.java index 00fc1d507..1c2f8d649 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPrestigesSetMultiplierGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPrestigesSetMultiplierGUI.java @@ -3,6 +3,7 @@ import com.cryptomorin.xseries.XMaterial; import org.bukkit.entity.Player; import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -30,11 +31,11 @@ public void open() { int dimension = 45; PrisonGUI gui = new PrisonGUI(p, dimension, "&3Edit -> Multiplier"); - ButtonLore changeDecreaseValueLore = new ButtonLore(messages.getString("Lore.ClickToDecrease"), null); + ButtonLore changeDecreaseValueLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_decrease), null); ButtonLore confirmButtonLore = new ButtonLore(createLore( - messages.getString("Lore.LeftClickToConfirm"), - messages.getString("Lore.RightClickToCancel")), createLore(messages.getString("Lore.Multiplier") + "x" + val)); - ButtonLore changeIncreaseValueLore = new ButtonLore(messages.getString("Lore.ClickToIncrease"), null); + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_left_to_confirm), + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_cancel)), createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_multiplier) + " " + "x" + val)); + ButtonLore changeIncreaseValueLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_increase), null); XMaterial decreaseMat = XMaterial.REDSTONE_BLOCK; XMaterial increaseMat = XMaterial.EMERALD_BLOCK; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPriceGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPriceGUI.java index f50300764..b61df22d9 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPriceGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPriceGUI.java @@ -3,6 +3,7 @@ import com.cryptomorin.xseries.XMaterial; import org.bukkit.entity.Player; import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.configs.NewMessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -32,10 +33,10 @@ public void open() { int dimension = 45; PrisonGUI gui = new PrisonGUI(p, dimension, "&3SellAll -> ItemValue"); - ButtonLore changeDecreaseValueLore = new ButtonLore(messages.getString("Lore.ClickToDecrease"), null); + ButtonLore changeDecreaseValueLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_decrease), null); ButtonLore confirmButtonLore = new ButtonLore(createLore( - messages.getString("Lore.LeftClickToConfirm"), messages.getString("Lore.RightClickToCancel")), createLore(messages.getString("Lore.Price2") + val)); - ButtonLore changeIncreaseValueLore = new ButtonLore(messages.getString("Lore.ClickToIncrease"), null); + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_left_to_confirm), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_cancel)), createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_price) + " " + val)); + ButtonLore changeIncreaseValueLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_increase), null); XMaterial decreaseMat = XMaterial.REDSTONE_BLOCK; XMaterial increaseMat = XMaterial.EMERALD_BLOCK; @@ -48,7 +49,7 @@ public void open() { gui.addButton(new Button(37, decreaseMat, changeDecreaseValueLore, SpigotPrison.format("&3" + itemID + " " + val + " - 10000"))); // Create a button and set the position - gui.addButton(new Button(22, XMaterial.TRIPWIRE_HOOK, confirmButtonLore, SpigotPrison.format("&3" + "Confirm: " + itemID + " " + val))); + gui.addButton(new Button(22, XMaterial.TRIPWIRE_HOOK, confirmButtonLore, SpigotPrison.format("&3Confirm: " + itemID + " " + val))); // Increase button gui.addButton(new Button(7, increaseMat, changeIncreaseValueLore, SpigotPrison.format("&3" + itemID + " " + val + " + 1" ))); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java index 19bec56d4..c007874c2 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java @@ -1482,7 +1482,7 @@ public boolean sellAllSell(Player p, boolean isUsingSign, boolean completelySile * * Return True if success, False if error or nothing changed or Player not meeting requirements. * - * Default usage of this method: sellAllSell(p, false, false, true, false, false, true, false); + * Default usage of this method: sellAllSell(p, itemStacks, false, false, true, false, false, true, false); * * @param p - Player. * @param itemStacks - ArrayList of ItemStacks. From 981c201040f36605a558168305a912919d84d6a3 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Tue, 7 Sep 2021 20:42:57 -0400 Subject: [PATCH 049/283] Switch over to using XSeries for the actionBar. XSeries claims it works for 1.8.8 through 1.17.1. --- docs/changelog_v3.3.x.md | 6 +++++- .../prison/spigot/compat/Spigot110Player.java | 19 +++++++++---------- .../prison/spigot/compat/Spigot18Player.java | 8 ++++++-- .../prison/spigot/compat/Spigot19Player.java | 11 +++++++---- 4 files changed, 27 insertions(+), 17 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 71963d39b..c81e41fa2 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,11 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.1 2021-09-02 +# 3.2.11-alpha.1 2021-09-07 + + +* **Switch over to using XSeries for the actionBar.** +XSeries claims it works for 1.8.8 through 1.17.1. * **Moved all Lores to the new .properties Language file:** Changes to the old .yml language file about Lore messages diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot110Player.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot110Player.java index 0062bcca9..5baef8ed9 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot110Player.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot110Player.java @@ -2,9 +2,6 @@ import org.bukkit.entity.Player; -import net.md_5.bungee.api.ChatMessageType; -import net.md_5.bungee.api.chat.TextComponent; - public abstract class Spigot110Player extends Spigot19 { @@ -13,11 +10,13 @@ public void sendTitle( Player player, String title, String subtitle, int fadeIn, player.sendTitle( title, subtitle, fadeIn, stay, fadeOut ); } - @Override - public void sendActionBar( Player player, String actionBar ) { - player.spigot().sendMessage( ChatMessageType.ACTION_BAR, - new TextComponent( actionBar ) ); - -// player.sendTitle( null, actionBar ); - } + + // NOTE: Just use the Spigot19Player class's sendActionBar(): +// @Override +// public void sendActionBar( Player player, String actionBar ) { +// player.spigot().sendMessage( ChatMessageType.ACTION_BAR, +// new TextComponent( actionBar ) ); +// +//// player.sendTitle( null, actionBar ); +// } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18Player.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18Player.java index bfd4e9896..7cf95d577 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18Player.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18Player.java @@ -2,6 +2,8 @@ import org.bukkit.entity.Player; +import com.cryptomorin.xseries.messages.ActionBar; + public abstract class Spigot18Player extends CompatibilityCache implements CompatibilityPlayer @@ -50,11 +52,13 @@ public void sendTitle( Player player, String title, String subtitle, int fadeIn, * @param player * @param actionBar */ - @SuppressWarnings( "deprecation" ) @Override public void sendActionBar( Player player, String actionBar ) { - player.sendTitle( "", actionBar ); + ActionBar.sendActionBar( player, actionBar ); + + // Was using the following until it was replaced with XSeries' ActionBar: +// player.sendTitle( "", actionBar ); // The following class does not exist under spigot 1.8.8 // player.spigot().sendMessage( ChatMessageType.ACTION_BAR, diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot19Player.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot19Player.java index 52fbdfe59..e9f203d63 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot19Player.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot19Player.java @@ -4,8 +4,7 @@ import org.bukkit.attribute.AttributeInstance; import org.bukkit.entity.Player; -import net.md_5.bungee.api.ChatMessageType; -import net.md_5.bungee.api.chat.TextComponent; +import com.cryptomorin.xseries.messages.ActionBar; public abstract class Spigot19Player extends Spigot18Blocks @@ -42,8 +41,12 @@ public void sendTitle( Player player, String title, String subtitle, int fadeIn, @Override public void sendActionBar( Player player, String actionBar ) { - player.spigot().sendMessage( ChatMessageType.ACTION_BAR, - new TextComponent( actionBar ) ); + + ActionBar.sendActionBar( player, actionBar ); + + // Was using the following until it was replaced with XSeries' ActionBar: +// player.spigot().sendMessage( ChatMessageType.ACTION_BAR, +// new TextComponent( actionBar ) ); // player.sendTitle( "", actionBar ); } From 252f5cf62a5bb64c3ab5fb8fc0e4759c248b0d38 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Tue, 7 Sep 2021 20:44:33 -0400 Subject: [PATCH 050/283] For the command /mines set area the confirmation of "yes" was setup incorrectly with being negated. --- docs/changelog_v3.3.x.md | 3 +++ .../tech/mcprison/prison/mines/commands/MinesCommands.java | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index c81e41fa2..8b54b6b0d 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-09-07 +* **For the command /mines set area the confirmation of "yes" was setup incorrectly with being negated.** + + * **Switch over to using XSeries for the actionBar.** XSeries claims it works for 1.8.8 through 1.17.1. diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java index f34a8b65a..e869ea795 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java @@ -2187,7 +2187,9 @@ public void setMineRankCommand(CommandSender sender, @Command(identifier = "mines set area", permissions = "mines.set", - description = "Set the area of a mine to your current selection or a 1x1 mine under your feet.") + description = "Set the area of a mine to your current selection or a 1x1 mine under your feet. " + + "If you are using 'feet' as the location of the mine, then you can also set the " + + "increases to the width, depth, and top. ") public void redefineCommand(CommandSender sender, @Arg(name = "mineName", description = "The name of the mine to edit.") String mineName, @Arg(name = "source", description = "&3The source to use for setting the area. The &7wand&3 " + @@ -2260,7 +2262,7 @@ else if ( source == null || "wand".equalsIgnoreCase( source ) ) { return; } else if ( options.toLowerCase().contains( "confirm" ) || - !options.toLowerCase().contains( "yes" ) ) { + options.toLowerCase().contains( "yes" ) ) { options = options.replace( "(?i)confirm|yes", "" ).trim(); } From 7af5c732cc5c148f831024469c8a6be6a038acc2 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Wed, 8 Sep 2021 01:22:10 -0400 Subject: [PATCH 051/283] Adding a player messaging component to the PlayerCache. When used, this will prevent more than one of the same messages from being displayed at the same time. --- docs/changelog_v3.3.x.md | 4 + .../autofeatures/PlayerMessageData.java | 122 ++++++++++++++++++ .../prison/autofeatures/PlayerMessaging.java | 70 ++++++++++ .../mcprison/prison/cache/PlayerCache.java | 27 ++++ .../prison/cache/PlayerCachePlayerData.java | 15 +++ .../utils/tasks/PlayerMessagingTask.java | 92 +++++++++++++ 6 files changed, 330 insertions(+) create mode 100644 prison-core/src/main/java/tech/mcprison/prison/autofeatures/PlayerMessageData.java create mode 100644 prison-core/src/main/java/tech/mcprison/prison/autofeatures/PlayerMessaging.java create mode 100644 prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/tasks/PlayerMessagingTask.java diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 8b54b6b0d..7b2062ba9 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-09-07 +* **Adding a player messaging component to the PlayerCache.** +When used, this will prevent more than one of the same messages from being displayed at the same time. + + * **For the command /mines set area the confirmation of "yes" was setup incorrectly with being negated.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/PlayerMessageData.java b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/PlayerMessageData.java new file mode 100644 index 000000000..a839d4d86 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/PlayerMessageData.java @@ -0,0 +1,122 @@ +package tech.mcprison.prison.autofeatures; + +import tech.mcprison.prison.autofeatures.PlayerMessaging.MessageType; + +public class PlayerMessageData +{ + private final long startTime; + private long targetEndTime; + + private final MessageType messageType; + private final String message; + private long ticks = 20L; + + private int submitted = 0; + private int hits = -1; + + private int taskId; + + + public PlayerMessageData( MessageType messageType, String message, long ticks ) { + super(); + + this.startTime = System.currentTimeMillis(); + + this.targetEndTime = this.startTime + ( ticks * 50 ); + + this.messageType = messageType; + this.message = message; + this.ticks = ticks; + + this.hits++; + } + + + /** + *

When a new message has been submitted to be displayed to the + * player, this function will check to see if the same message is + * currently being displayed to the player by checking if the + * current system time is greater than targetEndTime. + *

+ * + *

If the current time is less than targetEndTime, then that + * indicates that the message is active and therefore can be + * ignored. + *

+ * + *

If the current time is greater than the targetEndTime then + * that indicates that the message should be displayed. The way + * it is indicated that the message needs to be displayed is + * by setting the jobId to -1, which indicates no job is currently + * running. + *

+ * + * @param ticks + */ + public void addRepeatMessage( long ticks ) { + this.hits++; + + long currentTime = System.currentTimeMillis(); + + // if currentType is greater than targetEndTime then + // needs to submit a new task, which will be indicated + // by setting the jobId to -1. + if ( currentTime > targetEndTime ) { + setTaskId( -1 ); + } + else { + // do nothing... the message is already being displayed + } + } + + public long getStartTime() { + return startTime; + } + + public long getTargetEndTime() { + return targetEndTime; + } + public void setTargetEndTime( long targetEndTime ) { + this.targetEndTime = targetEndTime; + } + + public MessageType getMessageType() { + return messageType; + } + + public String getMessage() + { + return message; + } + + public long getTicks() { + return ticks; + } + public void setTicks( long ticks ) { + this.ticks = ticks; + } + + public int getSubmitted() { + return submitted; + } + public void setSubmitted( int submitted ) { + this.submitted = submitted; + } + + public int getHits() { + return hits; + } + public void setHits( int hits ) { + this.hits = hits; + } + + public int getTaskId() { + return taskId; + } + public void setTaskId( int taskId ) { + this.taskId = taskId; + + this.submitted++; + } + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/PlayerMessaging.java b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/PlayerMessaging.java new file mode 100644 index 000000000..d23fea22c --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/PlayerMessaging.java @@ -0,0 +1,70 @@ +package tech.mcprison.prison.autofeatures; + +import java.util.TreeMap; + +public class PlayerMessaging +{ + + private final TreeMap> messages; + + + public enum MessageType { + title, + actionBar; + } + + public PlayerMessaging() { + + this.messages = new TreeMap<>(); + + // Preload all the message types and setup their TreeMaps + for ( MessageType mType : MessageType.values() ) { + + getMessages().put( mType, new TreeMap<>() ); + } + + } + + /** + *

This function adds a message to the player's PlayerCached object. It uses the + * default duration of 40 ticks (2 seconds). + *

+ * + *

If the same message is active, then the message will not be submitted. + *

+ * + * @param messageType + * @param message + * @return + */ + public PlayerMessageData addMessage( MessageType messageType, String message ) { + + return addMessage( messageType, message, 40L ); + } + + public PlayerMessageData addMessage( MessageType messageType, String message, long ticks ) { + PlayerMessageData pmData = null; + + TreeMap messagesOfType = getMessages().get( messageType ); + + if ( messagesOfType.containsKey( message ) ) { + pmData = messagesOfType.get( message ); + + // A message that was sent to the player before is requested to be sent again: + pmData.addRepeatMessage( ticks ); + } + else { + + // This message has not be sent to the player before: + pmData = new PlayerMessageData( messageType, message, ticks ); + messagesOfType.put( message, pmData ); + } + + return pmData; + } + + public TreeMap> getMessages() { + return messages; + } + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCache.java b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCache.java index eaca6f85a..67af85a63 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCache.java +++ b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCache.java @@ -206,6 +206,33 @@ public PlayerCachePlayerData removePlayerData( PlayerCachePlayerData playerData } + /** + *

This function will return a null if the player is not loaded in the cache. + * Null is a valid value even if the player is online. + * This function should NEVER be used + * for any critical data such as tracking blocks, time, earnings, or inventory. + * Examples of acceptable loss would be with messaging. Loss of a few messages is + * not that critical, and actually would be a very rare situation. Example, if a + * player is mining then their cache should already be loaded so calling this function + * should never find the situation where the player's cache entry does not exist. + *

+ * + *

Since this function will fail with the return a null if the player is not loaded, + * this function will not cause blocking on the runnable thread. + *

+ * + *

If the player is not loaded, and a null is returned, then an async task + * will be submitted to load it. + *

+ * + * @param player + * @return + */ + public PlayerCachePlayerData getOnlinePlayer( Player player ) { + PlayerCachePlayerData playerData = getPlayer( player ); + + return playerData; + } /** *

This returns the cached player object. If they have not been loaded diff --git a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java index befae9dc1..315a1a0fd 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java @@ -5,6 +5,7 @@ import java.util.Date; import java.util.TreeMap; +import tech.mcprison.prison.autofeatures.PlayerMessaging; import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.placeholders.PlaceholdersUtil; @@ -82,6 +83,11 @@ public class PlayerCachePlayerData { // sessionLastLocation is used for afk calculations: // private transient Location sessionLastLocation = null; + + private transient PlayerMessaging playerMessaging; + + + private transient boolean dirty = false; @@ -111,6 +117,8 @@ public PlayerCachePlayerData() { // this.sessionLastLocation = null; + this.playerMessaging = new PlayerMessaging(); + } public PlayerCachePlayerData( Player player, File playerFile ) { @@ -524,6 +532,13 @@ public void setEarningsByMine( TreeMap earningsByMine ) { this.earningsByMine = earningsByMine; } + public PlayerMessaging getPlayerMessaging() { + return playerMessaging; + } + public void setPlayerMessaging( PlayerMessaging playerMessaging ) { + this.playerMessaging = playerMessaging; + } + public boolean isDirty() { return dirty; } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/tasks/PlayerMessagingTask.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/tasks/PlayerMessagingTask.java new file mode 100644 index 000000000..5a30bba0c --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/tasks/PlayerMessagingTask.java @@ -0,0 +1,92 @@ +package tech.mcprison.prison.spigot.utils.tasks; + +import org.bukkit.entity.Player; + +import tech.mcprison.prison.autofeatures.PlayerMessageData; +import tech.mcprison.prison.autofeatures.PlayerMessaging; +import tech.mcprison.prison.autofeatures.PlayerMessaging.MessageType; +import tech.mcprison.prison.cache.PlayerCache; +import tech.mcprison.prison.cache.PlayerCachePlayerData; +import tech.mcprison.prison.spigot.compat.SpigotCompatibility; +import tech.mcprison.prison.spigot.game.SpigotPlayer; +import tech.mcprison.prison.tasks.PrisonRunnable; +import tech.mcprison.prison.tasks.PrisonTaskSubmitter; + +public class PlayerMessagingTask + implements PrisonRunnable +{ + private Player player; + private PlayerMessageData messageData = null; + + + public PlayerMessagingTask( Player player, PlayerMessageData messageData ) { + super(); + + this.player = player; + this.messageData = messageData; + } + + public static void submitTask( Player player, MessageType messageType, String message ) { + + SpigotPlayer bPlayer = new SpigotPlayer( player ); + + PlayerCachePlayerData playerCache = PlayerCache.getInstance().getOnlinePlayer( bPlayer ); + if ( playerCache != null ) { + + + PlayerMessaging messagingData = playerCache.getPlayerMessaging(); + + PlayerMessageData mData = messagingData.addMessage( messageType, message ); + + if ( mData.getTaskId() == -1 ) { + + PlayerMessagingTask messagingTask = new PlayerMessagingTask( player, mData ); + + int jobId = PrisonTaskSubmitter.runTaskLater( messagingTask, 0 ); + messagingTask.setTaskId( jobId ); + } + + + } + } + + public void submit() { + PrisonTaskSubmitter.runTaskLater(this, 0); + } + + + @Override + public void run() + { + switch ( messageData.getMessageType() ) + { + case actionBar: + { + + SpigotCompatibility.getInstance().sendActionBar( player, messageData.getMessage() ); + break; + } + + case title: + { + SpigotCompatibility.getInstance().sendTitle( player, messageData.getMessage(), + null, 10, 20, 10 ); + + break; + } + + default: + + // Do nothing... let the task end since the message type was not valid + } + + + } + + + private void setTaskId( int taskId ) { + if ( messageData != null ) { + messageData.setTaskId( taskId ); + } + } +} From 2b202d456d9a5db7d0fbbeeccf6c475349d1e914 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Wed, 8 Sep 2021 08:45:21 -0400 Subject: [PATCH 052/283] Hooked up XSeries' Titles to the compatibility class instead of using version specific code. XSeries says they support 1.8.8 through 1.17.1. Deleted the support for the Spigot110 classes since it was only to support the use of the ActionBar and also the Title, which are no longer needed for 1.10+. --- docs/changelog_v3.3.x.md | 7 +++++- .../prison/spigot/compat/Spigot110.java | 23 ------------------- .../prison/spigot/compat/Spigot110Player.java | 22 ------------------ .../prison/spigot/compat/Spigot113Blocks.java | 2 +- .../prison/spigot/compat/Spigot18Player.java | 7 ++++-- .../prison/spigot/compat/Spigot19Player.java | 9 ++++++-- .../spigot/compat/SpigotCompatibility.java | 10 ++++---- 7 files changed, 24 insertions(+), 56 deletions(-) delete mode 100644 prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot110.java delete mode 100644 prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot110Player.java diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 7b2062ba9..33ec1cdd5 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,12 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.1 2021-09-07 +# 3.2.11-alpha.1 2021-09-08 + + +* **Hooked up XSeries' Titles to the compatibility class instead of using version specific code.** +XSeries says they support 1.8.8 through 1.17.1. +Deleted the support for the Spigot110 classes since it was only to support the use of the ActionBar and also the Title, which are no longer needed for 1.10+. * **Adding a player messaging component to the PlayerCache.** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot110.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot110.java deleted file mode 100644 index bee66b0a8..000000000 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot110.java +++ /dev/null @@ -1,23 +0,0 @@ -package tech.mcprison.prison.spigot.compat; - -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; - -/** - * Important note: Spigot 1.10 support is represented in Spigot110 and is - * identical to Spigot19 except for two spigot 1.10 functions: sendTitle() - * and sendActionBar(). Therefore, all that needs to be done is to have - * the class Spigot110Player extend Spigot19 and then Override - * those two functons. - * - */ -public class Spigot110 - extends Spigot110Player - implements Compatibility { - - @Override - public void setItemInMainHand(Player p, ItemStack itemStack){ - p.getInventory().setItemInMainHand(itemStack); - } - -} diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot110Player.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot110Player.java deleted file mode 100644 index 5baef8ed9..000000000 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot110Player.java +++ /dev/null @@ -1,22 +0,0 @@ -package tech.mcprison.prison.spigot.compat; - -import org.bukkit.entity.Player; - -public abstract class Spigot110Player - extends Spigot19 -{ - @Override - public void sendTitle( Player player, String title, String subtitle, int fadeIn, int stay, int fadeOut ) { - player.sendTitle( title, subtitle, fadeIn, stay, fadeOut ); - } - - - // NOTE: Just use the Spigot19Player class's sendActionBar(): -// @Override -// public void sendActionBar( Player player, String actionBar ) { -// player.spigot().sendMessage( ChatMessageType.ACTION_BAR, -// new TextComponent( actionBar ) ); -// -//// player.sendTitle( null, actionBar ); -// } -} diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113Blocks.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113Blocks.java index f04001871..562e6859c 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113Blocks.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113Blocks.java @@ -21,7 +21,7 @@ import tech.mcprison.prison.util.Location; public abstract class Spigot113Blocks - extends Spigot110Player + extends Spigot19Player implements CompatibilityBlocks { @Override diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18Player.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18Player.java index 7cf95d577..4862f8e3d 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18Player.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18Player.java @@ -3,6 +3,7 @@ import org.bukkit.entity.Player; import com.cryptomorin.xseries.messages.ActionBar; +import com.cryptomorin.xseries.messages.Titles; public abstract class Spigot18Player extends CompatibilityCache @@ -39,9 +40,11 @@ public void setMaxHealth( Player player, double maxHealth ) { * @param fadeOut - parameter ignored */ @Override - @SuppressWarnings( "deprecation" ) public void sendTitle( Player player, String title, String subtitle, int fadeIn, int stay, int fadeOut ) { - player.sendTitle( title, subtitle ); + //player.sendTitle( title, subtitle ); + + Titles.sendTitle( player, fadeIn, stay, fadeOut, title, subtitle ); + } /** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot19Player.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot19Player.java index e9f203d63..71a0cdb67 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot19Player.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot19Player.java @@ -5,6 +5,7 @@ import org.bukkit.entity.Player; import com.cryptomorin.xseries.messages.ActionBar; +import com.cryptomorin.xseries.messages.Titles; public abstract class Spigot19Player extends Spigot18Blocks @@ -34,9 +35,13 @@ public double getMaxHealth( Player player ) { } @Override - @SuppressWarnings( "deprecation" ) + //@SuppressWarnings( "deprecation" ) public void sendTitle( Player player, String title, String subtitle, int fadeIn, int stay, int fadeOut ) { - player.sendTitle( title, subtitle ); + + //player.sendTitle( title, subtitle ); + + Titles.sendTitle( player, fadeIn, stay, fadeOut, title, subtitle ); + } @Override diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/SpigotCompatibility.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/SpigotCompatibility.java index c6824ed01..60381bd77 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/SpigotCompatibility.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/SpigotCompatibility.java @@ -37,14 +37,14 @@ private static synchronized void setup() { results = new Spigot18(); } - else if ( svData.compareTo( new BluesSemanticVersionData( "1.10.0" ) ) < 0 ) { - - results = new Spigot19(); - } else if ( svData.compareTo( new BluesSemanticVersionData( "1.13.0" ) ) < 0 ) { - results = new Spigot110(); + results = new Spigot19(); } +// else if ( svData.compareTo( new BluesSemanticVersionData( "1.13.0" ) ) < 0 ) { +// +// results = new Spigot110(); +// } else { results = new Spigot113(); From db2534641be20d4c352b33ba9ca9cc0deb70066e Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Wed, 8 Sep 2021 09:46:01 -0400 Subject: [PATCH 053/283] Prevented a problem when unloading players, and when a player is null. The condition that was causing a null player was that the player was unloaded when the player left the server at the same time when the server was shut down. Basically a race condition with two parallel async tasks trying to shut down the player cache object, each focusing on a different aspect (player vs. server). --- docs/changelog_v3.3.x.md | 4 ++ .../prison/cache/PlayerCacheFiles.java | 57 ++++++++++--------- 2 files changed, 34 insertions(+), 27 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 33ec1cdd5..f4f720f99 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-09-08 +* **Prevented a problem when unloading players, and when a player is null.** +The condition that was causing a null player was that the player was unloaded when the player left the server at the same time when the server was shut down. Basically a race condition with two parallel async tasks trying to shut down the player cache object, each focusing on a different aspect (player vs. server). + + * **Hooked up XSeries' Titles to the compatibility class instead of using version specific code.** XSeries says they support 1.8.8 through 1.17.1. Deleted the support for the Spigot110 classes since it was only to support the use of the ActionBar and also the Title, which are no longer needed for 1.10+. diff --git a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheFiles.java b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheFiles.java index 0241bfdef..0bfd8d57a 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheFiles.java +++ b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheFiles.java @@ -90,36 +90,39 @@ public String toJson( PlayerCachePlayerData player ) { */ public void toJsonFile( PlayerCachePlayerData player) { - File playerFile = player.getPlayerFile(); - File outTemp = createTempFile( playerFile ); - boolean success = false; - - try ( - FileWriter fw = new FileWriter( outTemp ); - ){ - getGson().toJson( player, fw ); + if ( player != null ) { - success = true; - } - catch ( JsonIOException | IOException e ) { - e.printStackTrace(); - } - - if ( success && ( !playerFile.exists() || playerFile.delete()) ) { - outTemp.renameTo( playerFile ); - } - else { - - boolean removed = false; - if ( outTemp.exists() ) { - removed = outTemp.delete(); + File playerFile = player.getPlayerFile(); + File outTemp = createTempFile( playerFile ); + boolean success = false; + + try ( + FileWriter fw = new FileWriter( outTemp ); + ){ + getGson().toJson( player, fw ); + + success = true; + } + catch ( JsonIOException | IOException e ) { + e.printStackTrace(); } - - String message = String.format( - "Unable to rename PlayerCache temp file. It was %sremoved: %s", - (removed ? "" : "not "), outTemp.getAbsolutePath() ); - Output.get().logWarn( message ); + if ( success && ( !playerFile.exists() || playerFile.delete()) ) { + outTemp.renameTo( playerFile ); + } + else { + + boolean removed = false; + if ( outTemp.exists() ) { + removed = outTemp.delete(); + } + + String message = String.format( + "Unable to rename PlayerCache temp file. It was %sremoved: %s", + (removed ? "" : "not "), outTemp.getAbsolutePath() ); + + Output.get().logWarn( message ); + } } } From 75efc240c684ca1168c02a1d57f79fad88fb550c Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Wed, 8 Sep 2021 09:56:37 -0400 Subject: [PATCH 054/283] The player cache, when being shut down Prevented a problem when unloading players, and when a player is null. The condition that was causing a null player was that the player was unloaded when the player left the server at the same time when the server was shut down. Basically a race condition with two parallel async tasks trying to shut down the player cache object, each focusing on a different aspect (player vs. server). This function was making a new collection based upon the original player cache copy of players, of which, when a few of the players are removed, then they were resulting in nulls. --- docs/changelog_v3.3.x.md | 4 +++ .../cache/PlayerCacheCheckTimersTask.java | 26 +++++++++---------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index f4f720f99..ba92fb060 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-09-08 +* **The player cache, when being shut down ran in to a problem if the players were removed when they logged off.** +This function was making a new collection based upon the original player cache copy of players, of which, when a few of the players are removed, then they were resulting in nulls. + + * **Prevented a problem when unloading players, and when a player is null.** The condition that was causing a null player was that the player was unloaded when the player left the server at the same time when the server was shut down. Basically a race condition with two parallel async tasks trying to shut down the player cache object, each focusing on a different aspect (player vs. server). diff --git a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheCheckTimersTask.java b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheCheckTimersTask.java index 84292dc31..c1efb2f4a 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheCheckTimersTask.java +++ b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheCheckTimersTask.java @@ -1,8 +1,5 @@ package tech.mcprison.prison.cache; -import java.util.ArrayList; -import java.util.List; - /** *

This periodically ran task will go through all cached players and update * their status with the timers and earnings. This is a light weight task @@ -43,21 +40,22 @@ public void run() PlayerCache pCache = PlayerCache.getInstance(); - List keys = new ArrayList<>( pCache.getPlayers().keySet() ); - - for ( String key : keys ) - { - PlayerCachePlayerData playerData = pCache.getPlayers().get( key ); + if ( pCache.getPlayers() != null && pCache.getPlayers().keySet().size() > 0 ) { - if ( playerData != null ) { + for ( String key : pCache.getPlayers().keySet() ) + { + PlayerCachePlayerData playerData = pCache.getPlayers().get( key ); - playerData.checkTimers(); + if ( playerData != null ) { + + playerData.checkTimers(); + + // By adding a zero earnings, this will force the earnings "cache" to + // progress, even if the player stopped mining. + playerData.addEarnings( 0 ); + } - // By adding a zero earnings, this will force the earnings "cache" to - // progress, even if the player stopped mining. - playerData.addEarnings( 0 ); } - } } From c99aba235785c849f41ce35ec39e05969d1b7a9f Mon Sep 17 00:00:00 2001 From: AnonymousGCA Date: Sat, 11 Sep 2021 20:55:24 +0200 Subject: [PATCH 055/283] Changelogs: - Full transition of the messages .yml file to the .properties. - Some changes all over the code. - Some fixes. --- docs/changelog_v3.3.x.md | 9 + .../resources/lang/spigot/en_US.properties | 136 ++++- .../mcprison/prison/spigot/SpigotPrison.java | 14 +- .../autofeatures/AutoManagerFeatures.java | 83 ++- .../spigot/backpacks/BackpacksUtil.java | 4 +- .../PrisonSpigotBackpackCommands.java | 63 ++- .../commands/PrisonSpigotBaseCommands.java | 5 +- .../commands/PrisonSpigotGUICommands.java | 27 +- .../PrisonSpigotPrestigeCommands.java | 19 +- .../commands/PrisonSpigotSellAllCommands.java | 150 +++--- .../prison/spigot/configs/MessagesConfig.java | 477 ++++++++++-------- .../spigot/configs/NewMessagesConfig.java | 167 ------ .../spigot/gui/ListenersPrisonManager.java | 212 ++++---- .../prison/spigot/gui/PrisonSetupGUI.java | 22 +- .../prison/spigot/gui/SpigotPrisonGUI.java | 14 +- .../gui/autofeatures/SpigotAutoBlockGUI.java | 8 +- .../autofeatures/SpigotAutoFeaturesGUI.java | 18 +- .../gui/autofeatures/SpigotAutoPickupGUI.java | 8 +- .../gui/autofeatures/SpigotAutoSmeltGUI.java | 8 +- .../gui/backpacks/BackpacksAdminGUI.java | 8 +- .../gui/backpacks/BackpacksAdminListGUI.java | 10 +- .../BackpacksAdminPlayerListGUI.java | 8 +- .../gui/backpacks/BackpacksListPlayerGUI.java | 16 +- .../gui/guiutility/SpigotGUIComponents.java | 23 +- .../spigot/gui/mine/SpigotBlocksListGUI.java | 8 +- .../gui/mine/SpigotBlocksMineListGUI.java | 8 +- .../mine/SpigotMineBlockPercentageGUI.java | 12 +- .../spigot/gui/mine/SpigotMineInfoGUI.java | 48 +- .../mine/SpigotMineNotificationRadiusGUI.java | 12 +- .../gui/mine/SpigotMineNotificationsGUI.java | 16 +- .../gui/mine/SpigotMineResetTimeGUI.java | 8 +- .../spigot/gui/mine/SpigotMinesBlocksGUI.java | 14 +- .../gui/mine/SpigotMinesConfirmGUI.java | 6 +- .../spigot/gui/mine/SpigotMinesGUI.java | 24 +- .../spigot/gui/mine/SpigotPlayerMinesGUI.java | 14 +- .../gui/rank/SpigotConfirmPrestigeGUI.java | 12 +- .../spigot/gui/rank/SpigotLaddersGUI.java | 10 +- .../gui/rank/SpigotPlayerPrestigesGUI.java | 10 +- .../spigot/gui/rank/SpigotPlayerRanksGUI.java | 10 +- .../spigot/gui/rank/SpigotRankManagerGUI.java | 18 +- .../spigot/gui/rank/SpigotRankPriceGUI.java | 8 +- .../gui/rank/SpigotRankUPCommandsGUI.java | 14 +- .../spigot/gui/rank/SpigotRanksGUI.java | 24 +- .../gui/sellall/SellAllAdminAutoSellGUI.java | 12 +- .../gui/sellall/SellAllAdminBlocksGUI.java | 17 +- .../spigot/gui/sellall/SellAllAdminGUI.java | 44 +- .../spigot/gui/sellall/SellAllDelayGUI.java | 8 +- .../spigot/gui/sellall/SellAllPlayerGUI.java | 10 +- .../SellAllPrestigesMultiplierGUI.java | 16 +- .../SellAllPrestigesSetMultiplierGUI.java | 10 +- .../spigot/gui/sellall/SellAllPriceGUI.java | 10 +- .../prison/spigot/sellall/SellAllUtil.java | 28 +- 52 files changed, 954 insertions(+), 986 deletions(-) delete mode 100644 prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/NewMessagesConfig.java diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index ba92fb060..28fcd442c 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,15 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-09-08 +* **Fixed an error about backpacks and lore transition:** A single lore was being used for the backpacks utility, if a server +was new and fresh, this would've been missing and an error could occur, this now got fixed with the full transition. + + +* **Full transition of all messages to the .properties lang:** All messages are now on the .properties file and the old +.yml one is unused from now on, you can delete it and start translating the new one. Please note that some messages may +be wrong, as it's still in a young stage and a lot of messages got transitioned. + + * **The player cache, when being shut down ran in to a problem if the players were removed when they logged off.** This function was making a new collection based upon the original player cache copy of players, of which, when a few of the players are removed, then they were resulting in nulls. diff --git a/prison-core/src/main/resources/lang/spigot/en_US.properties b/prison-core/src/main/resources/lang/spigot/en_US.properties index fba061e0e..ee4df1d54 100644 --- a/prison-core/src/main/resources/lang/spigot/en_US.properties +++ b/prison-core/src/main/resources/lang/spigot/en_US.properties @@ -49,7 +49,7 @@ ## /prison support submit. ## -messages__version=3 +messages__version=4 messages__auto_refresh=true ## Click to do something @@ -142,9 +142,9 @@ spigot_gui_lore_ranks_setup_2=If you want continue the setup. spigot_gui_lore_ranks_setup_3=All Ranks and Mines from A to Z will be made spigot_gui_lore_ranks_setup_4=With &adefault &3values! spigot_gui_lore_ranks_setup_5=You can also use: -spigot_gui_lore_ranks_setup_6=&1/ranks autoConfigure full ! -spigot_gui_lore_ranks_setup_7=&3Please replace the X with the starting price and -spigot_gui_lore_ranks_setup_8=&3multiplier, default price = 50000, multiplier = 1.5. +spigot_gui_lore_ranks_setup_6=/ranks autoConfigure full ! +spigot_gui_lore_ranks_setup_7=Please replace the X with the starting price and +spigot_gui_lore_ranks_setup_8=multiplier, default price = 50000, multiplier = 1.5. spigot_gui_lore_sellall_delay_use_1=Short delay before using again spigot_gui_lore_sellall_delay_use_2=the &3/sellall sell &8command. spigot_gui_lore_set_mine_delay_instruction_1=Set a mine's delay @@ -173,4 +173,132 @@ spigot_gui_lore_tp_to_mine=Click to teleport to Mine. ## Messages spigot_message_missing_permission=Sorry, You don't have the permission to use that! +spigot_message_chat_event_time_end=You ran out of time, event cancelled! +spigot_message_event_cancelled=Event cancelled. +spigot_message_command_wrong_format=Sorry, wrong command format. +spigot_message_console_error=Sorry, you need to be a player to use that. +## Ladder Messages +spigot_message_ladder_default_empty=Sorry, the Default Ladder's empty. + +## Mine Messages +spigot_message_mines_disabled=Sorry, Mines are disabled. +spigot_message_mines_name_chat_1=Please write the &6mineName &7you'd like to use and &6submit&7. +spigot_message_mines_name_chat_2=Input &cclose &7to cancel or wait &c30 seconds&7. +spigot_message_mines_name_chat_cancelled=Rename Mine &cclosed&7, nothing got changed! +spigot_message_mines_item_show_edit_success=Mine show item edited with success. +spigot_message_mines_or_gui_disabled=Sorry, Mines or GUIs are disabled. + +## Backpack Messages +spigot_message_backpack_cant_own=Sorry, you can't own Backpacks. +spigot_message_backpack_delete_error=Sorry, can't delete Backpack. +spigot_message_backpack_delete_success=Backpack deleted with success. +spigot_message_backpack_format_error=Sorry, the command format isn't right, maybe some arguments are missing. +spigot_message_backpack_limit_decrement_fail=The Backpack Limit can't be negative. +spigot_message_backpack_limit_edit_success=Backpack Limit edited with success. +spigot_message_backpack_limit_not_number=Sorry, the Backpack Limit isn't a number. +spigot_message_backpack_limit_reached=Sorry, you can't own more Backpacks. +spigot_message_backpack_missing_playername=Sorry, please add a valid Player name. +spigot_message_backpack_resize_success=If the Backpack exists, it got resized with success. +spigot_message_backpack_size_must_be_multiple_of_9=The Backpack size must be a multiple of 9 and not exceed 64! + + +## Prestige Messages +spigot_message_prestiges_disabled=Sorry, Prestiges are disabled. +spigot_message_prestiges_empty=Sorry, there aren't Prestiges. +spigot_message_prestiges_or_gui_disabled=Sorry, Prestiges or GUIs are disabled. +spigot_message_prestiges_confirm=Confirm&7: Type the word &aconfirm&7 to confirm. +spigot_message_prestiges_cancel=Cancel&7: Type the word &ccancel&7 to cancel, &cyou've 30 seconds. +spigot_message_prestiges_cancelled=Prestige cancelled. +spigot_message_prestiges_cancelled_wrong_keyword=Prestige &ccancelled&7, you didn't type the word: &aconfirm&7. + +## Ranks Messages +spigot_message_ranks_disabled=Sorry, Ranks are disabled. +spigot_message_ranks_or_gui_disabled=Sorry, Ranks or GUIs are disabled. +spigot_message_ranks_tag_chat_rename_1=Please write the &6tag &7you'd like to use and &6submit&7. +spigot_message_ranks_tag_chat_rename_2=Input &cclose &7to cancel or wait &c30 seconds&7. +spigot_message_ranks_tag_chat_cancelled=Rename tag &cclosed&7, nothing got changed! + +## SellAll Messages +spigot_message_sellall_auto_already_enabled=Sellall Auto already enabled. +spigot_message_sellall_auto_already_disabled=SellAll Auto already disabled. +spigot_message_sellall_auto_disabled=SellAll Auto disabled with success. +spigot_message_sellall_auto_disabled_cant_use=Sorry, you need to enable AutoSell to use this. +spigot_message_sellall_auto_enabled=SellAll Auto enabled with success. +spigot_message_sellall_auto_perusertoggleable_enabled=Sellall Auto perUserToggleable enabled with success. +spigot_message_sellall_auto_perusertoggleable_disabled=Sellall Auto perUserToggleable disabled with success. +spigot_message_sellall_auto_perusertoggleable_already_enabled=Sellall Auto perUserToggleable already enabled. +spigot_message_sellall_auto_perusertoggleable_already_disabled=Sellall Auto perUserToggleable already disabled. +spigot_message_sellall_boolean_input_invalid=The boolean value isn't valid (Valid values are True or False). +spigot_message_sellall_cant_find_item_config=Sorry, can't find your item in the config. +spigot_message_sellall_currency_chat_1=&3Started setup of new currency for SellAll! +spigot_message_sellall_currency_chat_2=Type &ccancel &7to cancel. +spigot_message_sellall_currency_chat_3=Type &3default &7to set to default currency. +spigot_message_sellall_currency_chat_4=Type the &aCurrency name &7to set the new currency. +spigot_message_sellall_currency_edit_success=SellAll Currency edited with success. +spigot_message_sellall_currency_not_found=Sorry, currency not found. +spigot_message_sellall_hand_disabled=SellAll Hand disabled with success. +spigot_message_sellall_hand_enabled=Sellall Hand enabled with success. +spigot_message_sellall_hand_is_disabled=SellAll Hand is disabled. +spigot_message_sellall_item_add_success=Item added with success. +spigot_message_sellall_item_already_added=You've already added this item, please use the edit command instead. +spigot_message_sellall_item_delete_success=Item deleted with success. +spigot_message_sellall_item_edit_success=SellAll Item edited with success. +spigot_message_sellall_item_id_not_found=Sorry, invalid Item Name/ID. +spigot_message_sellall_item_missing_name=Please add the Item Name/ID argument. +spigot_message_sellall_item_missing_price=Please add Item Value argument. +spigot_message_sellall_item_not_found=SellAll Item not found in the config. +spigot_message_sellall_default_values_success=SellAll Default values set with success. +spigot_message_sellall_delay_already_enabled=SellAll Delay already enabled. +spigot_message_sellall_delay_already_disabled=SellAll Delay already disabled. +spigot_message_sellall_delay_disabled=SellAll Delay disabled with success. +spigot_message_sellall_delay_disabled_cant_use=Sorry, please enable SellAll Delay to use this. +spigot_message_sellall_delay_edit_success=Sellall Delay edited with success. +spigot_message_sellall_delay_enabled=SellAll Delay enabled with success. +spigot_message_sellall_delay_not_number=SellAll Delay number isn't valid. +spigot_message_sellall_delay_wait=Please wait the end of the delay before using again the command. +spigot_message_sellall_gui_disabled=SellAll GUI is disabled. +spigot_message_sellall_money_earned=You got &a$ +spigot_message_sellall_multiplier_add_success=SellAll Multiplier added with success. +spigot_message_sellall_multiplier_are_disabled=Sorry, SellAll Multipliers are disabled. +spigot_message_sellall_multiplier_cant_find=Sorry, can't find SellAll Multiplier. +spigot_message_sellall_multiplier_delete_success=SellAll Multiplier deleted with success. +spigot_message_sellall_multiplier_disabled=SellAll Multipliers Disabled with success. +spigot_message_sellall_multiplier_edit_success=SellAll Multiplier edited with success. +spigot_message_sellall_multiplier_enabled=SellAll Multipliers Enabled with success. +spigot_message_sellall_sell_empty=Sorry, there aren't items in the SellAll shop. +spigot_message_sellall_sell_nothing_sellable=Sorry but you've nothing to sell. +spigot_message_sellall_sell_sign_only=You can use SellAll Sell only with Signs. +spigot_message_sellall_sell_sign_notify=You sold trough a sign with success. +spigot_message_sellall_trigger_already_disabled=SellAll Trigger already disabled. +spigot_message_sellall_trigger_already_enabled=SellAll Trigger already enabled. +spigot_message_sellall_trigger_disabled=SellAll Trigger disabled with success. +spigot_message_sellall_trigger_enabled=SellAll Trigger enabled with success. +spigot_message_sellall_trigger_is_disabled=Sorry, SellAll Trigger is disabled. +spigot_message_sellall_trigger_item_add_success=SellAll Item Trigger added with success. +spigot_message_sellall_trigger_item_cant_find=SellAll Item Trigger item not found in the config. +spigot_message_sellall_trigger_item_delete_success=SellAll Item Trigger deleted with success. +spigot_message_sellall_trigger_item_missing=Please add Item Name/ID to the command. + +## GUI Messages +spigot_message_gui_backpack_disabled=Can't open GUI, Backpacks are disabled. +spigot_message_gui_backpack_empty=Sorry, there aren't Backpacks to show. +spigot_message_gui_backpack_too_many=Sorry, there are too many Backpacks and the GUI can't show them. +spigot_message_gui_close_success=GUI closed with success. +spigot_message_gui_error=Can't open GUI, disabled or error. +spigot_message_gui_error_empty=Can't open GUI, it's empty. +spigot_message_gui_ladder_empty=Sorry, there aren't Ladders to show. +spigot_message_gui_ladder_too_many=Sorry, there are too many Ladders and the GUI can't show them. +spigot_message_gui_mines_empty=Sorry, there aren't Mines to show. +spigot_message_gui_mines_too_many=Sorry, there are too many Mines for the GUI to show. +spigot_message_gui_prestiges_empty=Sorry, there aren't Prestiges to show. +spigot_message_gui_prestiges_too_many=Sorry, there are too many Prestiges and the GUI can't show them. +spigot_message_gui_ranks_empty=Sorry, there aren't Ranks in this Ladder to show. +spigot_message_gui_ranks_rankup_commands_empty=Sorry, there aren't Rankup Commands to show. +spigot_message_gui_ranks_rankup_commands_too_many=Sorry, there are too many Rankup Commands and the GUI can't show them. +spigot_message_gui_ranks_too_many=Sorry, there are too many Ranks and the GUI can't show them. +spigot_message_gui_reload_success=GUIs reloaded with success! +spigot_message_gui_sellall_disabled=Sorry, SellAll is disabled. +spigot_message_gui_sellall_empty=Sorry, there's nothing to show. +spigot_message_gui_too_high=Sorry, but the value is too high (above maximum possible). +spigot_message_gui_too_low_value=Sorry, but the value is too low (below minimum possible). \ No newline at end of file diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPrison.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPrison.java index 70935316e..4cb55132d 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPrison.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPrison.java @@ -116,7 +116,6 @@ public class SpigotPrison private AutoManagerFeatures autoFeatures = null; // private FileConfiguration autoFeaturesConfig = null; - private NewMessagesConfig newMessagesConfig; private MessagesConfig messagesConfig; private GuiConfig guiConfig; private SellAllConfig sellAllConfig; @@ -393,19 +392,12 @@ public FileConfiguration updateSellAllConfig() { return sellAllConfig.getFileSellAllConfig(); } - public FileConfiguration getMessagesConfig() { + public MessagesConfig getMessagesConfig() { if (messagesConfig == null) { - messagesConfig = new MessagesConfig(); + messagesConfig = MessagesConfig.get(); } - return messagesConfig.getFileGuiMessagesConfig(); - } - - public NewMessagesConfig getNewMessagesConfig(){ - if (newMessagesConfig == null){ - newMessagesConfig = NewMessagesConfig.get(); - } - return newMessagesConfig; + return messagesConfig; } public FileConfiguration getBackpacksConfig() { diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java index b0b9b03e3..aa97437bc 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java @@ -40,6 +40,7 @@ import tech.mcprison.prison.spigot.commands.PrisonSpigotSellAllCommands; import tech.mcprison.prison.spigot.compat.SpigotCompatibility; import tech.mcprison.prison.spigot.game.SpigotPlayer; +import tech.mcprison.prison.spigot.sellall.SellAllUtil; import tech.mcprison.prison.spigot.spiget.BluesSpigetSemVerComparator; import tech.mcprison.prison.util.BlockType; import tech.mcprison.prison.util.Text; @@ -759,62 +760,48 @@ protected void autoBlock( boolean autoBlock, XMaterial source, XMaterial target, private void dropExtra( HashMap extra, Player player ) { if ( extra != null && extra.size() > 0 ) { + if (SpigotPrison.getInstance().isSellAllEnabled()) { - - Configuration sellAllConfig = SpigotPrison.getInstance().updateSellAllConfig(); - - if ( isBoolean( sellAllConfig, "Options.Full_Inv_AutoSell") ) { - if ( isBoolean( sellAllConfig, "Options.Full_Inv_AutoSell_perUserToggleable") ){ - - UUID playerUUID = player.getUniqueId(); + SellAllUtil sellAllUtil = SellAllUtil.get(); - if (isBoolean( sellAllConfig, "Users." + playerUUID + ".isEnabled") ) { - - if (isBoolean( sellAllConfig, "Options.Full_Inv_AutoSell_Notification") ) { - Output.get().sendInfo(new SpigotPlayer(player), SpigotPrison.format( - SpigotPrison.getInstance().getMessagesConfig().getString("Message.SellAllAutoSell"))); + if (sellAllUtil != null && sellAllUtil.isAutoSellEnabled) { + if (sellAllUtil.isAutoSellPerUserToggleable) { + if (sellAllUtil.isPlayerAutoSellEnabled(player)) { + if (sellAllUtil.isAutoSellNotificationEnabled) { + SellAllUtil.get().sellAllSell(player, false, false, true, true, false, true); + } else { + SellAllUtil.get().sellAllSell(player, false, true, false, false, false, true); } - - PrisonSpigotSellAllCommands.get().sellAllSellCommand( new SpigotPlayer( player ), "" ); - -// String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "sellall sell" ); -// Bukkit.dispatchCommand(player, registeredCmd); -// return; - } - } else { - if (isBoolean( sellAllConfig, "Options.Full_Inv_AutoSell_Notification") ) { - Output.get().sendInfo(new SpigotPlayer(player), SpigotPrison.format( - SpigotPrison.getInstance().getMessagesConfig().getString("Message.SellAllAutoSell"))); + } + } else { + if (sellAllUtil.isAutoSellNotificationEnabled) { + SellAllUtil.get().sellAllSell(player, false, false, true, true, false, true); + } else { + SellAllUtil.get().sellAllSell(player, false, true, false, false, false, true); + } } - PrisonSpigotSellAllCommands.get().sellAllSellCommand( new SpigotPlayer( player ), "" ); -// String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "sellall sell" ); -// Bukkit.dispatchCommand(player, registeredCmd); -// return; - } - - // Now that something might have been sold, try to add all the extra inventory items back to the - // player's inventory so it is not lost then pass the moreExtras along to be handled as the - // configurations require. - HashMap moreExtras = new HashMap<>(); - for ( SpigotItemStack itemStack : extra.values() ) { - moreExtras.putAll( SpigotUtil.addItemToPlayerInventory( player, itemStack )); + // Now that something might have been sold, try to add all the extra inventory items back to the + // player's inventory so it is not lost then pass the moreExtras along to be handled as the + // configurations require. + HashMap moreExtras = new HashMap<>(); + for (SpigotItemStack itemStack : extra.values()) { + moreExtras.putAll(SpigotUtil.addItemToPlayerInventory(player, itemStack)); + } + extra = moreExtras; } - extra = moreExtras; - } - - for ( SpigotItemStack itemStack : extra.values() ) { - - if ( isBoolean( AutoFeatures.dropItemsIfInventoryIsFull ) ) { - - SpigotUtil.dropPlayerItems( player, itemStack ); - notifyPlayerThatInventoryIsFull( player ); - } - else { - notifyPlayerThatInventoryIsFullLosingItems( player ); + + for (SpigotItemStack itemStack : extra.values()) { + + if (isBoolean(AutoFeatures.dropItemsIfInventoryIsFull)) { + + SpigotUtil.dropPlayerItems(player, itemStack); + notifyPlayerThatInventoryIsFull(player); + } else { + notifyPlayerThatInventoryIsFullLosingItems(player); + } } } - } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/BackpacksUtil.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/BackpacksUtil.java index c436bcf7c..d01a8cf4a 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/BackpacksUtil.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/BackpacksUtil.java @@ -27,6 +27,7 @@ import tech.mcprison.prison.spigot.compat.Compatibility; import tech.mcprison.prison.spigot.compat.SpigotCompatibility; import tech.mcprison.prison.spigot.configs.BackpacksConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; /** @@ -35,7 +36,6 @@ public class BackpacksUtil { private static BackpacksUtil instance; - private final Configuration messages = SpigotPrison.getInstance().getMessagesConfig(); private Configuration backpacksConfig = SpigotPrison.getInstance().getBackpacksConfig(); private File backpacksFile = new File(SpigotPrison.getInstance().getDataFolder() + "/backpacks/backpacksData.yml"); private FileConfiguration backpacksDataConfig = YamlConfiguration.loadConfiguration(backpacksFile); @@ -1281,7 +1281,7 @@ private void backPackItem(Player p) { ItemStack item; List itemLore = createLore( - messages.getString("Lore.ClickToOpenBackpack") + SpigotPrison.getInstance().getMessagesConfig().getString(MessagesConfig.StringID.spigot_gui_lore_click_to_open) ); item = createButton(SpigotUtil.getXMaterial(backpacksConfig.getString("Options.BackPack_Item")).parseItem(), itemLore, backpacksConfig.getString("Options.BackPack_Item_Title")); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotBackpackCommands.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotBackpackCommands.java index 92cff7af5..9913c3c4d 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotBackpackCommands.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotBackpackCommands.java @@ -1,8 +1,6 @@ package tech.mcprison.prison.spigot.commands; -import at.pcgamingfreaks.Minepacks.Bukkit.API.Backpack; import org.bukkit.Bukkit; -import org.bukkit.configuration.Configuration; import org.bukkit.entity.Player; import tech.mcprison.prison.Prison; @@ -12,6 +10,7 @@ import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.backpacks.BackpacksUtil; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.gui.backpacks.BackpacksAdminGUI; import tech.mcprison.prison.spigot.gui.backpacks.BackpacksListPlayerGUI; @@ -22,7 +21,7 @@ * */ public class PrisonSpigotBackpackCommands extends PrisonSpigotBaseCommands { - private final Configuration messages = SpigotPrison.getInstance().getMessagesConfig(); + private final MessagesConfig messages = SpigotPrison.getInstance().getMessagesConfig(); @Command(identifier = "backpack", description = "Backpacks", onlyPlayers = false) private void backpackMainCommand(CommandSender sender, @@ -49,7 +48,7 @@ private void backpackItemGive(CommandSender sender){ Player p = getSpigotPlayer(sender); if (p == null) { - Output.get().sendInfo(sender, SpigotPrison.format( getMessages().getString("Message.CantGiveItemFromConsole"))); + Output.get().sendInfo(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_console_error))); return; } @@ -64,7 +63,7 @@ private void backpacksListCommand(CommandSender sender){ Player p = getSpigotPlayer(sender); if (p == null) { - Output.get().sendInfo(sender, SpigotPrison.format( getMessages().getString("Message.CantGiveItemFromConsole"))); + Output.get().sendInfo(sender, SpigotPrison.format( messages.getString(MessagesConfig.StringID.spigot_message_console_error))); return; } @@ -81,7 +80,7 @@ private void deleteBackpackCommand(CommandSender sender, @Arg(name = "id", description = "The backpack ID optional", def = "null") String id){ if (name.equalsIgnoreCase("null")){ - Output.get().sendWarn(sender, SpigotPrison.format(getMessages().getString("Message.BackPackNeedPlayer"))); + Output.get().sendWarn(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_backpack_missing_playername))); return; } @@ -101,9 +100,9 @@ private void deleteBackpackCommand(CommandSender sender, } } if (success) { - Output.get().sendInfo(sender, SpigotPrison.format(getMessages().getString("Message.BackPackDeleteOperationSuccess"))); + Output.get().sendInfo(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_backpack_delete_success))); } else { - Output.get().sendWarn(sender, SpigotPrison.format(getMessages().getString("Message.BackPackDeleteOperationFail"))); + Output.get().sendWarn(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_backpack_delete_error))); } } @@ -114,7 +113,7 @@ private void resizeBackpackCommand(CommandSender sender, @Arg(name = "id", description = "The backpack ID optional", def = "null") String id){ if (name.equalsIgnoreCase("null")){ - Output.get().sendWarn(sender, SpigotPrison.format(getMessages().getString("Message.BackPackNeedPlayer"))); + Output.get().sendWarn(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_backpack_missing_playername))); return; } @@ -122,13 +121,13 @@ private void resizeBackpackCommand(CommandSender sender, try{ sizeInt = Integer.parseInt(size); } catch (NumberFormatException ex){ - Output.get().sendWarn(sender, SpigotPrison.format(getMessages().getString("Message.BackPackResizeNotInt"))); + Output.get().sendWarn(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_backpack_size_must_be_multiple_of_9))); return; } // Must be multiple of 9. if ((sizeInt % 9 != 0 || sizeInt > 54) && sizeInt != 0){ - Output.get().sendWarn(sender, SpigotPrison.format(getMessages().getString("Message.BackPackResizeNotMultiple9"))); + Output.get().sendWarn(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_backpack_size_must_be_multiple_of_9))); return; } @@ -155,7 +154,7 @@ private void resizeBackpackCommand(CommandSender sender, } } - Output.get().sendInfo(sender, SpigotPrison.format(getMessages().getString("Message.BackPackResizeDone"))); + Output.get().sendInfo(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_backpack_resize_success))); } @Command(identifier = "backpack limit", permissions = "prison.admin", description = "Backpacks limit for player, to use this multiple backpacks must be enabled from the backpacks config or it won't have effect.", onlyPlayers = false) @@ -169,7 +168,7 @@ private void setBackpackLimitCommand(CommandSender sender, @Arg(name = "Limit", description = "The Backpacks limit that a player can own", def = "null") String limit) { if (name.equalsIgnoreCase("null") || limit.equalsIgnoreCase("null")){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.BackPackLimitMissingParam"))); + Output.get().sendWarn(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_command_wrong_format))); return; } @@ -177,7 +176,7 @@ private void setBackpackLimitCommand(CommandSender sender, try{ limitInt = Integer.parseInt(limit); } catch (NumberFormatException ex){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.BackPackLimitNotNumber"))); + Output.get().sendWarn(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_backpack_limit_not_number))); return; } @@ -187,16 +186,16 @@ private void setBackpackLimitCommand(CommandSender sender, BackpacksUtil.get().setBackpacksLimit(BackpacksUtil.get().getBackpackOwnerOffline(name), limitInt); } - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.BackPackLimitSuccess"))); + Output.get().sendInfo(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_backpack_limit_edit_success))); } - @Command(identifier = "backpack limit add", permissions = "prison.admin", description = "Increment backpacks limit of a player, to use this multiple backpacks must be enabled or it won't have effect.", onlyPlayers = false) + @Command(identifier = "backpack limit add", permissions = "prison.admin", description = "Increment backpacks limit of a player, multiple backpacks must be enabled or this won't take effect.", onlyPlayers = false) private void addBackpackLimitCommand(CommandSender sender, @Arg(name = "Owner", description = "The backpack owner name", def = "null") String name, @Arg(name = "Limit", description = "The Backpacks increment value", def = "null") String limit) { if (name.equalsIgnoreCase("null") || limit.equalsIgnoreCase("null")){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.BackPackLimitMissingParam"))); + Output.get().sendWarn(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_command_wrong_format))); return; } @@ -204,7 +203,7 @@ private void addBackpackLimitCommand(CommandSender sender, try{ limitInt = Integer.parseInt(limit); } catch (NumberFormatException ex){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.BackPackLimitNotNumber"))); + Output.get().sendWarn(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_backpack_limit_not_number))); return; } @@ -216,7 +215,7 @@ private void addBackpackLimitCommand(CommandSender sender, BackpacksUtil.get().setBackpacksLimit(BackpacksUtil.get().getBackpackOwnerOffline(name), limitInt); } - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.BackPackLimitSuccess"))); + Output.get().sendInfo(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_backpack_limit_edit_success))); } @Command(identifier = "backpack limit decrement", permissions = "prison.admin", description = "Decrement backpacks limit of a player, to use this multiple backpacks must be enabled or it won't have effect.", onlyPlayers = false) @@ -225,7 +224,7 @@ private void decrementBackpackLimitCommand(CommandSender sender, @Arg(name = "Value", description = "The Backpacks decrement value", def = "null") String limit) { if (name.equalsIgnoreCase("null") || limit.equalsIgnoreCase("null")){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.BackPackLimitMissingParam"))); + Output.get().sendWarn(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_command_wrong_format))); return; } @@ -233,7 +232,7 @@ private void decrementBackpackLimitCommand(CommandSender sender, try{ limitInt = Integer.parseInt(limit); } catch (NumberFormatException ex){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.BackPackLimitNotNumber"))); + Output.get().sendWarn(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_backpack_limit_not_number))); return; } @@ -242,7 +241,7 @@ private void decrementBackpackLimitCommand(CommandSender sender, if (limitInt >= 0) { BackpacksUtil.get().setBackpacksLimit(Bukkit.getPlayerExact(name), limitInt); } else { - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.BackPackLimitDecrementFail"))); + Output.get().sendWarn(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_backpack_limit_decrement_fail))); return; } } else { @@ -250,12 +249,12 @@ private void decrementBackpackLimitCommand(CommandSender sender, if (limitInt >= 0) { BackpacksUtil.get().setBackpacksLimit(BackpacksUtil.get().getBackpackOwnerOffline(name), limitInt); } else { - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.BackPackLimitDecrementFail"))); + Output.get().sendWarn(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_backpack_limit_decrement_fail))); return; } } - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.BackPackLimitSuccess"))); + Output.get().sendInfo(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_backpack_limit_edit_success))); } @Command(identifier = "backpack admin", description = "Open backpack admin GUI", permissions = "prison.admin", onlyPlayers = true) @@ -264,7 +263,7 @@ private void openBackpackAdminGUI(CommandSender sender){ Player p = getSpigotPlayer(sender); if (p == null) { - Output.get().sendInfo(sender, SpigotPrison.format( getMessages().getString("Message.CantGiveItemFromConsole"))); + Output.get().sendInfo(sender, SpigotPrison.format( messages.getString(MessagesConfig.StringID.spigot_message_console_error))); return; } @@ -279,24 +278,24 @@ private void backpackGUIOpenCommand(CommandSender sender, Player p = getSpigotPlayer(sender); if (p == null) { - Output.get().sendInfo(sender, SpigotPrison.format( getMessages().getString("Message.CantRunGUIFromConsole"))); + Output.get().sendInfo(sender, SpigotPrison.format( messages.getString(MessagesConfig.StringID.spigot_message_console_error))); return; } if (isDisabledWorld(p)) return; if (getBoolean(BackpacksUtil.get().getBackpacksConfig().getString("Options.Multiple-BackPacks-For-Player-Enabled")) && (BackpacksUtil.get().reachedBackpacksLimit(p) && !BackpacksUtil.get().getBackpacksIDs(p).contains(id))){ - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.BackPackOwnLimitReached") + " [" + BackpacksUtil.get().getNumberOwnedBackpacks(p) + "]")); + Output.get().sendInfo(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_backpack_limit_reached) + " [" + BackpacksUtil.get().getNumberOwnedBackpacks(p) + "]")); return; } if (getBoolean(BackpacksUtil.get().getBackpacksConfig().getString("Options.BackPack_Use_Permission_Enabled")) && !p.hasPermission(BackpacksUtil.get().getBackpacksConfig().getString("Options.BackPack_Use_Permission"))){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.MissingPermission") + " [" + BackpacksUtil.get().getBackpacksConfig().getString("Options.BackPack_Use_Permission") + "]")); + Output.get().sendWarn(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_missing_permission) + " [" + BackpacksUtil.get().getBackpacksConfig().getString("Options.BackPack_Use_Permission") + "]")); return; } if (!BackpacksUtil.get().canOwnBackpack(p)){ - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.BackPackCantOwn"))); + Output.get().sendInfo(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_backpack_cant_own))); return; } @@ -313,7 +312,7 @@ private void backpackListGUICommand(CommandSender sender){ Player p = getSpigotPlayer(sender); if (p == null) { - Output.get().sendInfo(sender, SpigotPrison.format( getMessages().getString("Message.CantRunGUIFromConsole"))); + Output.get().sendInfo(sender, SpigotPrison.format( messages.getString(MessagesConfig.StringID.spigot_message_console_error))); return; } @@ -322,7 +321,7 @@ private void backpackListGUICommand(CommandSender sender){ // New method. if (getBoolean(BackpacksUtil.get().getBackpacksConfig().getString("Options.Multiple-BackPacks-For-Player-Enabled"))){ if (getBoolean(BackpacksUtil.get().getBackpacksConfig().getString("Options.BackPack_Use_Permission_Enabled")) && !p.hasPermission(BackpacksUtil.get().getBackpacksConfig().getString("Options.BackPack_Use_Permission"))){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.MissingPermission") + " [" + BackpacksUtil.get().getBackpacksConfig().getString("Options.BackPack_Use_Permission") + "]")); + Output.get().sendWarn(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_missing_permission) + " [" + BackpacksUtil.get().getBackpacksConfig().getString("Options.BackPack_Use_Permission") + "]")); return; } BackpacksListPlayerGUI gui = new BackpacksListPlayerGUI(p); @@ -336,7 +335,7 @@ private void openBackpackAdminCommandGUI(CommandSender sender){ Player p = getSpigotPlayer(sender); if (p == null) { - Output.get().sendInfo(sender, SpigotPrison.format( getMessages().getString("Message.CantGiveItemFromConsole"))); + Output.get().sendInfo(sender, SpigotPrison.format( messages.getString(MessagesConfig.StringID.spigot_message_console_error))); return; } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotBaseCommands.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotBaseCommands.java index 699e3b90e..729a9b43b 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotBaseCommands.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotBaseCommands.java @@ -5,6 +5,7 @@ import tech.mcprison.prison.internal.CommandSender; import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.game.SpigotCommandSender; /** @@ -12,9 +13,9 @@ */ public class PrisonSpigotBaseCommands { - private final Configuration messages = SpigotPrison.getInstance().getMessagesConfig(); + private final MessagesConfig messages = SpigotPrison.getInstance().getMessagesConfig(); - public Configuration getMessages() { + public MessagesConfig getMessages() { return messages; } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotGUICommands.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotGUICommands.java index e89db1c57..65d94a4bd 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotGUICommands.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotGUICommands.java @@ -8,6 +8,7 @@ import tech.mcprison.prison.internal.CommandSender; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.SpigotGUIComponents; import tech.mcprison.prison.spigot.gui.SpigotPrisonGUI; import tech.mcprison.prison.spigot.gui.mine.SpigotPlayerMinesGUI; @@ -20,7 +21,7 @@ */ public class PrisonSpigotGUICommands extends PrisonSpigotBaseCommands { - private final Configuration messages = getMessages(); + private final MessagesConfig messages = getMessages(); /** * NOTE: onlyPlayers needs to be false so players can use /gui help on the command, even from console. @@ -37,7 +38,7 @@ private void prisonManagerGUI(CommandSender sender) { Player player = getSpigotPlayer(sender); if (player == null) { - Output.get().sendInfo(sender, SpigotPrison.format( getMessages().getString("Message.CantRunGUIFromConsole"))); + Output.get().sendInfo(sender, SpigotPrison.format( getMessages().getString(MessagesConfig.StringID.spigot_message_console_error))); return; } @@ -55,13 +56,13 @@ private void prisonManagerGUI(CommandSender sender) { private void prisonManagerPrestiges( CommandSender sender ) { if ( !isPrisonConfig("prestiges") && !isPrisonConfig( "prestige.enabled" ) ) { - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.PrestigesAreDisabled"))); + Output.get().sendInfo(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_prestiges_disabled))); return; } if ( !isPrisonConfig("prison-gui-enabled") || !isConfig("Options.Prestiges.GUI_Enabled")){ - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.GuiOrPrestigesDisabled"))); + Output.get().sendInfo(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_prestiges_or_gui_disabled))); return; } @@ -69,7 +70,7 @@ private void prisonManagerPrestiges( CommandSender sender ) { String perm = getConfig( "Options.Prestiges.Permission_GUI"); if ( !sender.hasPermission( perm ) ){ - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.missingGuiPrestigesPermission") + " [" + + Output.get().sendInfo(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_missing_permission) + " [" + perm + "]")); return; } @@ -78,7 +79,7 @@ private void prisonManagerPrestiges( CommandSender sender ) { Player player = getSpigotPlayer( sender ); if (player == null) { - Output.get().sendInfo(sender, SpigotPrison.format( getMessages().getString("Message.CantRunGUIFromConsole"))); + Output.get().sendInfo(sender, SpigotPrison.format( getMessages().getString(MessagesConfig.StringID.spigot_message_console_error))); return; } @@ -93,12 +94,12 @@ private void prisonManagerMines(CommandSender sender) { Player player = getSpigotPlayer(sender); if (player == null) { - Output.get().sendInfo(sender, SpigotPrison.format( getMessages().getString("Message.CantRunGUIFromConsole"))); + Output.get().sendInfo(sender, SpigotPrison.format( getMessages().getString(MessagesConfig.StringID.spigot_message_console_error))); return; } if ( !isPrisonConfig("prison-gui-enabled") || !isConfig("Options.Mines.GUI_Enabled") ){ - Output.get().sendInfo(sender, SpigotPrison.format( getMessages().getString("Message.mineOrGuiDisabled"))); + Output.get().sendInfo(sender, SpigotPrison.format( getMessages().getString(MessagesConfig.StringID.spigot_message_mines_or_gui_disabled))); return; } @@ -107,7 +108,7 @@ private void prisonManagerMines(CommandSender sender) { String perm = getConfig( "Options.Mines.Permission_GUI"); if ( !sender.hasPermission( perm ) ){ - Output.get().sendInfo(sender, SpigotPrison.format( getMessages().getString("Message.mineMissingGuiPermission") + " [" + + Output.get().sendInfo(sender, SpigotPrison.format( getMessages().getString(MessagesConfig.StringID.spigot_message_missing_permission) + " [" + perm + "]")); return; } @@ -124,13 +125,13 @@ private void prisonManagerRanks(CommandSender sender) { Player player = getSpigotPlayer(sender); if (player == null) { - Output.get().sendInfo(sender, SpigotPrison.format( getMessages().getString("Message.CantRunGUIFromConsole"))); + Output.get().sendInfo(sender, SpigotPrison.format( getMessages().getString(MessagesConfig.StringID.spigot_message_console_error))); return; } if (!isPrisonConfig("prison-gui-enabled") || !isConfig("Options.Ranks.GUI_Enabled")) { Output.get().sendInfo(sender, SpigotPrison.format(String.format(String.format( - getMessages().getString("Message.rankGuiDisabledOrAllGuiDisabled"), + getMessages().getString(MessagesConfig.StringID.spigot_message_ranks_or_gui_disabled), getPrisonConfig("prison-gui-enabled"), getConfig("Options.Ranks.GUI_Enabled") )))); return; } @@ -139,7 +140,7 @@ private void prisonManagerRanks(CommandSender sender) { String perm = getConfig( "Options.Ranks.Permission_GUI"); if (!sender.hasPermission(perm)) { - Output.get().sendInfo(sender, SpigotPrison.format( getMessages().getString("Message.rankGuiMissingPermission") + " [" + + Output.get().sendInfo(sender, SpigotPrison.format( getMessages().getString(MessagesConfig.StringID.spigot_message_missing_permission) + " [" + perm + "]")); return; } @@ -163,6 +164,6 @@ public void reloadGUICommand(CommandSender sender){ SpigotGUIComponents.updateMessages(); SpigotGUIComponents.updateSellAllConfig(); SpigotGUIComponents.updateGUIConfig(); - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.GUIReloadSuccess"))); + Output.get().sendInfo(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_gui_reload_success))); } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotPrestigeCommands.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotPrestigeCommands.java index 9200d6062..3e6048ffe 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotPrestigeCommands.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotPrestigeCommands.java @@ -14,7 +14,7 @@ import tech.mcprison.prison.ranks.data.RankLadder; import tech.mcprison.prison.ranks.managers.LadderManager; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.gui.ListenersPrisonManager; import tech.mcprison.prison.spigot.gui.rank.SpigotConfirmPrestigeGUI; @@ -24,13 +24,13 @@ public class PrisonSpigotPrestigeCommands extends PrisonSpigotBaseCommands { - private final Configuration messages = SpigotPrison.getInstance().getMessagesConfig(); + private final MessagesConfig messages = SpigotPrison.getInstance().getMessagesConfig(); @Command(identifier = "prestiges", onlyPlayers = true) public void prestigesGUICommand(CommandSender sender) { if ( !isPrisonConfig( "prestiges") && !isPrisonConfig( "prestige.enabled" ) ) { - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.PrestigesDisabledDefault"))); + Output.get().sendInfo(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_prestiges_disabled))); return; } @@ -76,7 +76,7 @@ public void prisonManagerPrestige(CommandSender sender ) { if ( ( ladderDefault == null || !(ladderDefault.getLowestRank().isPresent()) || ladderDefault.getLowestRank().get().getName() == null)) { - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.DefaultLadderEmpty"))); + Output.get().sendInfo(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_ladder_default_empty))); return; } @@ -84,7 +84,7 @@ public void prisonManagerPrestige(CommandSender sender ) { if ( ( ladderPrestiges == null || !(ladderPrestiges.getLowestRank().isPresent()) || ladderPrestiges.getLowestRank().get().getName() == null)) { - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.CantFindPrestiges"))); + Output.get().sendInfo(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_prestiges_empty))); return; } } @@ -119,13 +119,12 @@ private void prestigeByChat(CommandSender sender) { ListenersPrisonManager listenersPrisonManager = ListenersPrisonManager.get(); listenersPrisonManager.chatEventActivator(); - NewMessagesConfig newMessages = SpigotPrison.getInstance().getNewMessagesConfig(); - Output.get().sendInfo(sender, newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_prestige_warning_1) + " " - + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_prestige_warning_2) + " " + newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_prestige_warning_3)); + Output.get().sendInfo(sender, messages.getString(MessagesConfig.StringID.spigot_gui_lore_prestige_warning_1) + " " + + messages.getString(MessagesConfig.StringID.spigot_gui_lore_prestige_warning_2) + " " + messages.getString(MessagesConfig.StringID.spigot_gui_lore_prestige_warning_3)); - Output.get().sendInfo(sender, messages.getString("Message.ConfirmPrestige")); - Output.get().sendInfo(sender, messages.getString("Message.CancelPrestige")); + Output.get().sendInfo(sender, "&a" + messages.getString(MessagesConfig.StringID.spigot_message_prestiges_confirm)); + Output.get().sendInfo(sender, "&c" + messages.getString(MessagesConfig.StringID.spigot_message_prestiges_cancel)); final Player player = getSpigotPlayer( sender ); listenersPrisonManager.chatInteractData(player, ListenersPrisonManager.ChatMode.Prestige); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotSellAllCommands.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotSellAllCommands.java index 022843241..d635719b4 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotSellAllCommands.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotSellAllCommands.java @@ -17,6 +17,7 @@ import tech.mcprison.prison.spigot.SpigotPlatform; import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.compat.Compatibility; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.sellall.SellAllBlockData; import tech.mcprison.prison.spigot.sellall.SellAllUtil; @@ -30,7 +31,7 @@ public class PrisonSpigotSellAllCommands extends PrisonSpigotBaseCommands { private static PrisonSpigotSellAllCommands instance; - private final Configuration messages = SpigotPrison.getInstance().getMessagesConfig(); + private final MessagesConfig messages = SpigotPrison.getInstance().getMessagesConfig(); private final Compatibility compat = SpigotPrison.getInstance().getCompatibility(); /** @@ -59,7 +60,7 @@ private void sellAllCurrency(CommandSender sender, EconomyCurrencyIntegration currencyEcon = PrisonAPI.getIntegrationManager().getEconomyForCurrency(currency); if (currencyEcon == null && !currency.equalsIgnoreCase("default")) { - Output.get().sendError(sender, SpigotPrison.format(messages.getString("Message.SellAllCurrencyNotFound")), currency); + Output.get().sendError(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_currency_not_found), currency); return; } @@ -69,7 +70,7 @@ private void sellAllCurrency(CommandSender sender, } if (sellAllUtil.setCurrency(currency)){ - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllCurrencyEditedSuccess") + " [" + currency + "]")); + Output.get().sendInfo(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_currency_edit_success) + " [" + currency + "]"); } } @@ -94,7 +95,7 @@ private void sellAllDelay(CommandSender sender, if (!isEnabled()) return; if (!(enable.equalsIgnoreCase("true") || enable.equalsIgnoreCase("false"))){ - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.InvalidBooleanInput"))); + Output.get().sendInfo(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_boolean_input_invalid)); return; } @@ -107,18 +108,18 @@ private void sellAllDelay(CommandSender sender, boolean enableBoolean = getBoolean(enable); if (sellAllUtil.isSellAllDelayEnabled == enableBoolean){ if (enableBoolean){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllDelayAlreadyEnabled"))); + Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_delay_already_enabled)); } else { - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllDelayAlreadyDisabled"))); + Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_delay_already_disabled)); } return; } if (sellAllUtil.setDelayEnable(enableBoolean)){ if (enableBoolean){ - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllDelayEnabled"))); + Output.get().sendInfo(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_delay_enabled)); } else { - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllDelayDisabled"))); + Output.get().sendInfo(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_delay_disabled)); } } } @@ -138,12 +139,12 @@ private void sellAllDelaySet(CommandSender sender, try { delayValue = Integer.parseInt(delay); } catch (NumberFormatException ex){ - Output.get().sendError(sender, SpigotPrison.format(messages.getString("Message.SellAllDelayNotNumber"))); + Output.get().sendError(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_delay_not_number)); return; } if (sellAllUtil.setDelay(delayValue)){ - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllDelayEditedWithSuccess") + " [" + delayValue + "s]")); + Output.get().sendInfo(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_delay_edit_success) + " [" + delayValue + "s]"); } } @@ -159,7 +160,7 @@ private void sellAllAutoSell(CommandSender sender, } if (!(enable.equalsIgnoreCase("true") || enable.equalsIgnoreCase("false"))){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.InvalidBooleanInput"))); + Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_boolean_input_invalid)); return; } @@ -171,18 +172,18 @@ private void sellAllAutoSell(CommandSender sender, boolean enableBoolean = getBoolean(enable); if (sellAllUtil.isAutoSellEnabled == enableBoolean){ if (enableBoolean){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllAutoSellAlreadyEnabled"))); + Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_auto_already_enabled)); } else { - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllAutoSellAlreadyDisabled"))); + Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_auto_already_disabled)); } return; } if (sellAllUtil.setAutoSell(enableBoolean)){ if (enableBoolean){ - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllAutoSellEnabled"))); + Output.get().sendInfo(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_auto_enabled)); } else { - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllAutoSellDisabled"))); + Output.get().sendInfo(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_auto_disabled)); } } } @@ -194,7 +195,7 @@ private void sellAllAutoSellPerUserToggleable(CommandSender sender, if (!isEnabled()) return; if (!(enable.equalsIgnoreCase("true") || enable.equalsIgnoreCase("false"))){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.InvalidBooleanInput"))); + Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_boolean_input_invalid)); return; } @@ -206,18 +207,18 @@ private void sellAllAutoSellPerUserToggleable(CommandSender sender, boolean enableBoolean = getBoolean(enable); if (sellAllUtil.isAutoSellPerUserToggleable == enableBoolean){ if (enableBoolean){ - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllAutoPerUserToggleableAlreadyEnabled"))); + Output.get().sendInfo(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_auto_perusertoggleable_already_enabled)); } else { - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllAutoPerUserToggleableAlreadyDisabled"))); + Output.get().sendInfo(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_auto_perusertoggleable_already_disabled)); } return; } if (sellAllUtil.setAutoSellPerUserToggleable(enableBoolean)){ if (enableBoolean){ - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllAutoPerUserToggleableEnabled"))); + Output.get().sendInfo(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_auto_perusertoggleable_enabled)); } else { - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllAutoPerUserToggleableDisabled"))); + Output.get().sendInfo(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_auto_perusertoggleable_disabled)); } } } @@ -233,7 +234,7 @@ public void sellAllSellCommand(CommandSender sender, Player p = getSpigotPlayer(sender); if (p == null){ - Output.get().sendInfo(sender, SpigotPrison.format("&cSorry but you can't use that from the console!")); + Output.get().sendInfo(sender, "&cSorry but you can't use that from the console!"); return; } @@ -247,7 +248,7 @@ public void sellAllSellCommand(CommandSender sender, if (sellAllUtil.isSellAllSellPermissionEnabled){ String permission = sellAllUtil.permissionSellAllSell; if (permission == null || !p.hasPermission(permission)){ - Output.get().sendWarn(new SpigotPlayer(p), SpigotPrison.format(messages.getString("Message.SellAllMissingPermission") + " [" + permission + "]")); + Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_missing_permission) + " [" + permission + "]"); return; } } @@ -276,7 +277,7 @@ public void sellAllSellHandCommand(CommandSender sender){ Player p = getSpigotPlayer(sender); if (p == null){ - Output.get().sendInfo(sender, SpigotPrison.format("&cSorry but you can't use that from the console!")); + Output.get().sendInfo(sender, "&cSorry but you can't use that from the console!"); return; } @@ -285,7 +286,7 @@ public void sellAllSellHandCommand(CommandSender sender){ if (sellAllUtil.isSellAllSellPermissionEnabled){ String permission = sellAllUtil.permissionSellAllSell; if (permission == null || !p.hasPermission(permission)){ - Output.get().sendWarn(new SpigotPlayer(p), SpigotPrison.format(messages.getString("Message.SellAllMissingPermission") + " [" + permission + "]")); + Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_missing_permission) + " [" + permission + "]"); return; } } @@ -305,7 +306,7 @@ public void sellAllSell(Player p){ if (!isEnabled()) return; if (p == null){ - Output.get().sendInfo(new SpigotPlayer(p), SpigotPrison.format("&cSorry but you can't use that from the console!")); + Output.get().sendInfo(new SpigotPlayer(p), "&cSorry but you can't use that from the console!"); return; } @@ -319,7 +320,7 @@ public void sellAllSell(Player p){ if (sellAllUtil.isSellAllSellPermissionEnabled){ String permission = sellAllUtil.permissionSellAllSell; if (permission == null || !p.hasPermission(permission)){ - Output.get().sendWarn(new SpigotPlayer(p), SpigotPrison.format(messages.getString("Message.SellAllMissingPermission") + " [" + permission + "]")); + Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_missing_permission) + " [" + permission + "]"); return; } } @@ -339,7 +340,7 @@ public void sellAllSellWithDelayCommand(CommandSender sender){ Player p = getSpigotPlayer(sender); if (p == null){ - Output.get().sendInfo(sender, SpigotPrison.format("&cSorry but you can't use that from the console!")); + Output.get().sendInfo(sender, "&cSorry but you can't use that from the console!"); return; } @@ -353,7 +354,7 @@ public void sellAllSellWithDelayCommand(CommandSender sender){ if (sellAllUtil.isSellAllSellPermissionEnabled){ String permission = sellAllUtil.permissionSellAllSell; if (permission == null || !p.hasPermission(permission)){ - Output.get().sendWarn(new SpigotPlayer(p), SpigotPrison.format(messages.getString("Message.SellAllMissingPermission") + " [" + permission + "]")); + Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_missing_permission) + " [" + permission + "]"); return; } } @@ -376,7 +377,7 @@ private void sellAllAutoEnableUser(CommandSender sender){ // Sender must be a Player, not something else like the Console. if (p == null) { - Output.get().sendError(sender, SpigotPrison.format(getMessages().getString("Message.CantRunGUIFromConsole"))); + Output.get().sendError(sender, getMessages().getString(MessagesConfig.StringID.spigot_message_console_error)); return; } @@ -393,15 +394,15 @@ private void sellAllAutoEnableUser(CommandSender sender){ String permission = sellAllUtil.permissionAutoSellPerUserToggleable; if (sellAllUtil.isAutoSellPerUserToggleablePermEnabled && (permission != null && !p.hasPermission(permission))){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllMissingPermissionToToggleAutoSell") + " [" + permission + "]")); + Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_missing_permission) + " [" + permission + "]"); return; } if (sellAllUtil.setAutoSellPlayer(p, !sellAllUtil.isPlayerAutoSellEnabled(p))){ if (sellAllUtil.isPlayerAutoSellEnabled(p)){ - Output.get().sendInfo(new SpigotPlayer(p), SpigotPrison.format(messages.getString("Message.SellAllAutoEnabled"))); + Output.get().sendInfo(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_sellall_auto_enabled)); } else { - Output.get().sendInfo(new SpigotPlayer(p), SpigotPrison.format(messages.getString("Message.SellAllAutoDisabled"))); + Output.get().sendInfo(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_sellall_auto_disabled)); } } } @@ -415,7 +416,7 @@ private void sellAllGuiCommand(CommandSender sender){ // Sender must be a Player, not something else like the Console. if (p == null) { - Output.get().sendError(sender, SpigotPrison.format(getMessages().getString("Message.CantRunGUIFromConsole"))); + Output.get().sendError(sender, getMessages().getString(MessagesConfig.StringID.spigot_message_console_error)); return; } @@ -427,7 +428,7 @@ private void sellAllGuiCommand(CommandSender sender){ if (!sellAllUtil.openSellAllGUI(p)){ // If the sender's an admin (OP or have the prison.admin permission) it'll send an error message. if (p.hasPermission("prison.admin")) { - Output.get().sendError(sender, SpigotPrison.format(messages.getString("Message.SellAllGUIDisabled"))); + Output.get().sendError(sender, messages.getString(MessagesConfig.StringID.spigot_message_gui_sellall_disabled)); } } } @@ -440,13 +441,13 @@ private void sellAllAddCommand(CommandSender sender, if (!isEnabled()) return; if (itemID == null){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllPleaseAddItem"))); + Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_missing_name)); return; } itemID = itemID.toUpperCase(); if (value == null){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllAddPrice"))); + Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_missing_price)); return; } @@ -456,7 +457,7 @@ private void sellAllAddCommand(CommandSender sender, } if (sellAllUtil.sellAllConfig.getConfigurationSection("Items." + itemID) != null){ - Output.get().sendWarn(sender, SpigotPrison.format(itemID + messages.getString("Message.SellAllAlreadyAdded"))); + Output.get().sendWarn(sender, itemID + " " + messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_already_added)); return; } @@ -465,16 +466,16 @@ private void sellAllAddCommand(CommandSender sender, try { blockAdd = XMaterial.valueOf(itemID); } catch (IllegalArgumentException ex){ - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllWrongID") + " [" + itemID + "]")); + Output.get().sendInfo(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_id_not_found) + " [" + itemID + "]"); return; } if (sellAllUtil.addSellAllBlock(blockAdd, value)){ - Output.get().sendInfo(sender, SpigotPrison.format("&3 ITEM [" + itemID + ", " + value + messages.getString("Message.SellAllAddSuccess"))); + Output.get().sendInfo(sender, "&3 ITEM [" + itemID + ", " + value + " " + messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_add_success)); } } catch (IllegalArgumentException ex){ - Output.get().sendError(sender, SpigotPrison.format(messages.getString("Message.SellAllWrongID") + " [" + itemID + "]")); + Output.get().sendError(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_id_not_found) + " [" + itemID + "]"); } } @@ -502,7 +503,7 @@ public void sellAllAddCommand(XMaterial blockAdd, Double value){ if (sellAllUtil.addSellAllBlock(blockAdd, value)) return; - Output.get().logInfo(SpigotPrison.format("&3 ITEM [" + itemID + ", " + value + messages.getString("Message.SellAllAddSuccess"))); + Output.get().logInfo("&3 ITEM [" + itemID + ", " + value + " " + messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_add_success)); } @Command(identifier = "sellall delete", description = "SellAll delete command, remove an item from shop.", permissions = "prison.admin", onlyPlayers = false) @@ -511,7 +512,7 @@ private void sellAllDeleteCommand(CommandSender sender, @Arg(name = "Item_ID", d if (!isEnabled()) return; if (itemID == null){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllMissingID"))); + Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_missing_name)); return; } itemID = itemID.toUpperCase(); @@ -522,13 +523,13 @@ private void sellAllDeleteCommand(CommandSender sender, @Arg(name = "Item_ID", d } if (sellAllUtil.sellAllConfig.getConfigurationSection("Items." + itemID) == null){ - Output.get().sendWarn(sender, SpigotPrison.format(itemID + messages.getString("Message.SellAllNotFoundStringConfig"))); + Output.get().sendWarn(sender, itemID + " " + messages.getString(MessagesConfig.StringID.spigot_message_sellall_cant_find_item_config)); return; } if (XMaterial.matchXMaterial(itemID).isPresent()) { if (sellAllUtil.removeSellAllBlock(XMaterial.matchXMaterial(itemID).get())) { - Output.get().sendInfo(sender, SpigotPrison.format(itemID + messages.getString("Message.SellAllDeletedSuccess"))); + Output.get().sendInfo(sender, itemID + " " + messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_delete_success)); } } } @@ -541,13 +542,13 @@ private void sellAllEditCommand(CommandSender sender, if (!isEnabled()) return; if (itemID == null){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllPleaseAddItem"))); + Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_missing_name)); return; } itemID = itemID.toUpperCase(); if (value == null){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllAddPrice"))); + Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_missing_price)); return; } @@ -557,7 +558,7 @@ private void sellAllEditCommand(CommandSender sender, } if (sellAllUtil.sellAllConfig.getConfigurationSection("Items." + itemID) == null){ - Output.get().sendWarn(sender, SpigotPrison.format(itemID + messages.getString("Message.SellAllNotFoundEdit"))); + Output.get().sendWarn(sender, itemID + " " + messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_not_found)); return; } @@ -566,16 +567,16 @@ private void sellAllEditCommand(CommandSender sender, try{ blockAdd = XMaterial.valueOf(itemID); } catch (IllegalArgumentException ex){ - Output.get().sendError(sender, SpigotPrison.format(messages.getString("Message.SellAllWrongID") + " [" + itemID + "]")); + Output.get().sendError(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_id_not_found) + " [" + itemID + "]"); return; } if (sellAllUtil.editPrice(blockAdd, value)){ - Output.get().sendInfo(sender, SpigotPrison.format("&3ITEM [" + itemID + ", " + value + messages.getString("Message.SellAllCommandEditSuccess"))); + Output.get().sendInfo(sender, "&3ITEM [" + itemID + ", " + value + " " + messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_edit_success)); } } catch (IllegalArgumentException ex){ - Output.get().sendError(sender, SpigotPrison.format(messages.getString("Message.SellAllWrongID") + " [" + itemID + "]")); + Output.get().sendError(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_id_not_found) + " [" + itemID + "]"); } } @@ -590,7 +591,7 @@ private void sellAllMultiplierCommand(CommandSender sender){ } if (!sellAllUtil.isSellAllMultiplierEnabled){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllMultipliersAreDisabled"))); + Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_multiplier_are_disabled)); return; } @@ -614,12 +615,12 @@ private void sellAllAddMultiplierCommand(CommandSender sender, } if (!sellAllUtil.isSellAllMultiplierEnabled){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllMultipliersAreDisabled"))); + Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_multiplier_are_disabled)); return; } if (sellAllUtil.addPrestigeMultiplier(prestige, multiplier)){ - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllMultiplierEditSaveSuccess"))); + Output.get().sendInfo(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_multiplier_add_success)); } } @@ -635,22 +636,22 @@ private void sellAllDeleteMultiplierCommand(CommandSender sender, } if (!sellAllUtil.isSellAllMultiplierEnabled){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllMultipliersAreDisabled"))); + Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_multiplier_are_disabled)); return; } if (prestige == null){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllMultiplierFormat"))); + Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_command_wrong_format)); return; } if (sellAllUtil.sellAllConfig.getConfigurationSection("Multiplier." + prestige) == null){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllCantFindMultiplier") + prestige + messages.getString("Message.SellAllCantFindMultiplier2"))); + Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_multiplier_cant_find) + " [" + prestige + "]"); return; } if (sellAllUtil.removePrestigeMultiplier(prestige)){ - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllMultiplierDeleteSuccess"))); + Output.get().sendInfo(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_multiplier_delete_success)); } } @@ -667,7 +668,7 @@ private void sellAllToolsTriggerToggle(CommandSender sender, } if (!enable.equalsIgnoreCase("true") && !enable.equalsIgnoreCase("false")){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.InvalidBooleanInput"))); + Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_boolean_input_invalid)); return; } @@ -679,18 +680,18 @@ private void sellAllToolsTriggerToggle(CommandSender sender, boolean enableInput = getBoolean(enable); if (sellAllUtil.isSellAllItemTriggerEnabled == enableInput) { if (sellAllUtil.isSellAllItemTriggerEnabled) { - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllTriggerAlreadyEnabled"))); + Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_trigger_already_enabled)); } else { - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllTriggerAlreadyDisabled"))); + Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_trigger_already_disabled)); } return; } if (sellAllUtil.setItemTrigger(enableInput)){ if (enableInput){ - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllTriggerEnabled"))); + Output.get().sendInfo(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_trigger_enabled)); } else { - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllTriggerDisabled"))); + Output.get().sendInfo(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_trigger_disabled)); } } } @@ -707,12 +708,12 @@ private void sellAllTriggerAdd(CommandSender sender, } if (!sellAllUtil.isSellAllItemTriggerEnabled){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllTriggerIsDisabled"))); + Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_trigger_is_disabled)); return; } if (itemID == null){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllTriggerMissingItem"))); + Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_missing_name)); return; } itemID = itemID.toUpperCase(); @@ -722,15 +723,15 @@ private void sellAllTriggerAdd(CommandSender sender, try{ blockAdd = XMaterial.valueOf(itemID); } catch (IllegalArgumentException ex){ - Output.get().sendError(sender, SpigotPrison.format(messages.getString("Message.SellAllWrongID") + " [" + itemID + "]")); + Output.get().sendError(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_id_not_found) + " [" + itemID + "]"); return; } if (sellAllUtil.addItemTrigger(blockAdd)){ - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllTriggerItemAddSuccess") + " [" + itemID + "]")); + Output.get().sendInfo(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_trigger_item_add_success) + " [" + itemID + "]"); } } catch (IllegalArgumentException ex){ - Output.get().sendError(sender, SpigotPrison.format(messages.getString("Message.SellAllWrongID") + " [" + itemID + "]")); + Output.get().sendError(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_id_not_found) + " [" + itemID + "]"); } } @@ -746,29 +747,29 @@ private void sellAllTriggerDelete(CommandSender sender, } if (!sellAllUtil.isSellAllItemTriggerEnabled){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllTriggerIsDisabled"))); + Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_trigger_is_disabled)); return; } if (itemID == null){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllTriggerMissingItem"))); + Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_missing_name)); return; } itemID = itemID.toUpperCase(); if (!XMaterial.matchXMaterial(itemID).isPresent()){ - Output.get().sendError(sender, SpigotPrison.format(messages.getString("Message.SellAllWrongID") + " [" + itemID + "]")); + Output.get().sendError(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_id_not_found) + " [" + itemID + "]"); return; } XMaterial xMaterial = XMaterial.matchXMaterial(itemID).get(); if (!sellAllUtil.getItemTriggerXMaterials().contains(xMaterial)){ - Output.get().sendWarn(sender, SpigotPrison.format(messages.getString("Message.SellAllTriggerMissingItem"))); + Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_missing_name)); return; } if (sellAllUtil.removeItemTrigger(xMaterial)) { - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllTriggerItemDeleteSuccess") + " [" + itemID + "]")); + Output.get().sendInfo(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_trigger_item_delete_success) + " [" + itemID + "]"); } } @@ -785,7 +786,6 @@ private void sellAllSetDefaultCommand(CommandSender sender){ sellAllAddCommand(sender, xMatCost.getBlock().name(), xMatCost.getPrice() ); } - Output.get().sendInfo(sender, SpigotPrison.format(messages.getString("Message.SellAllDefaultSuccess"))); + Output.get().sendInfo(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_default_values_success)); } -} - +} \ No newline at end of file diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/MessagesConfig.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/MessagesConfig.java index f6473f621..4035b6d67 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/MessagesConfig.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/MessagesConfig.java @@ -1,228 +1,289 @@ package tech.mcprison.prison.spigot.configs; -import java.io.File; -import java.io.IOException; - -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; - -import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.SpigotPrison; -/** - * @author GABRYCA - **/ -public class MessagesConfig extends SpigotConfigComponents{ +import java.io.*; +import java.util.Properties; - // Initialize parameters and variables - private FileConfiguration conf; - private int changeCount = 0; - - public MessagesConfig() { - initialize(); - } +public class MessagesConfig { - public void initialize() { + private static MessagesConfig instance; + private Properties properties = new Properties(); + private final String defaultLanguage = SpigotPrison.getInstance().getConfig().getString("default-language"); + private final String path = "/module_conf/spigot/lang/"; - // Filepath - File file = new File(SpigotPrison.getInstance().getDataFolder() + "/module_conf/lang/" + SpigotPrison.getInstance().getConfig().getString("default-language") + ".yml"); + /** + * Get MessagesConfig class and initialize it if necessary. + * */ + public static MessagesConfig get(){ + if (instance == null){ + instance = new MessagesConfig(); + instance.initConfig(); + } + return instance; + } - // Check if the config exists - fileMaker(file); + /** + * Initialize the config, reading and caching data. + * */ + private void initConfig(){ + try(FileInputStream data = new FileInputStream(SpigotPrison.getInstance().getDataFolder() + path + defaultLanguage + ".properties")){ - // Get the config - conf = YamlConfiguration.loadConfiguration(file); - - // Call method - values(); + Properties temp = new Properties(); + temp.load(new InputStreamReader(data)); + properties = temp; - if (changeCount > 0) { - try { - conf.save(file); - Output.get().logInfo("&aThere were &b%d &anew values added for the language files " + "used by the GuiConfig.yml file located at &b%s", changeCount, file.getAbsoluteFile()); - } - catch (IOException e) { - Output.get().logInfo("&4Failed to save &b%d &4new values for the language files " + "used by the GuiConfig.yml file located at &b%s&4. " + "&a %s", changeCount, file.getAbsoluteFile(), e.getMessage()); - } + } catch (IOException ex){ + ex.printStackTrace(); } - - conf = YamlConfiguration.loadConfiguration(file); } - private void dataConfig(String key, String value){ - if (conf.get(key) == null) { - conf.set(key, value); - changeCount++; - } + /** + * Get String. + * */ + public String getString(StringID message){ + return properties.getProperty(message.toString()); } - private void dataConfig(String key, boolean value){ - if (conf.get(key) == null) { - conf.set(key, value); - changeCount++; - } + public void reload(){ + initConfig(); } - // All the strings should be here - private void values(){ - dataConfig("Message.BackPackIsDisabled", "Backpacks are disabled in the config.yml, you can't use this!"); - dataConfig("Message.BackPackNeedPlayer", "Please add a playername."); - dataConfig("Message.BackPackDeleteOperationSuccess", "The backpack should've been deleted with success!"); - dataConfig("Message.BackPackDeleteOperationFail", "Can't find the backpack or something went wrong...?"); - dataConfig("Message.BackPackPlayerNotFound", "Player not found."); - dataConfig("Message.BackPackDoNotOwnAny", "Sorry but you don't own any inventory, please use /backpack to make one."); - dataConfig("Message.BackPackOwnLimitReached", "Sorry but you already have the max amount of backpacks allowed for Player!"); - dataConfig("Message.BackPackResizeNotInt", "Backpack's size value isn't a number."); - dataConfig("Message.BackPackResizeNotMultiple9", "Backpack's size must be a multiple of 9 and max 54."); - dataConfig("Message.BackPackResizeDone", "If the Backpack wasn't missing, it got resized with success!"); - dataConfig("Message.BackPackLimitMissingParam", "You're missing some arguments required to set the backpacks limit!"); - dataConfig("Message.BackPackLimitNotNumber", "The Backpacks Limit number isn't a number!"); - dataConfig("Message.BackPackLimitSuccess", "The Backpacks Limit got edited with success!"); - dataConfig("Message.BackPackLimitDecrementFail", "The Backpacks limit decremented of that value would be negative, operation canceled!"); - dataConfig("Message.BackPackListEmpty", "There aren't backpacks in this server."); - dataConfig("Message.BackPackCantOwn", "Sorry but looks like you can't own Backpacks!"); - dataConfig("Message.CantGetRanksAdmin", "Can't get Ranks, there might be &cno ranks&7 or the Ranks module's &cdisabled&7."); - dataConfig("Message.CantRunGUIFromConsole", "You cannot run the GUI from the console."); - dataConfig("Message.CantGiveItemFromConsole", "You can't get an item as the console."); - dataConfig("Message.DefaultLadderEmpty", "The default ladder is &cempty&7."); - dataConfig("Message.NoSellAllItems", "Sorry but &cthere aren't&7 SellAll Items to show."); - dataConfig("Message.EmptyGui", "Sorry, the GUI's &cempty."); - dataConfig("Message.EnableAutoSellToUse", "Sorry, but AutoSell's &cdisabled&7, please enable it!"); - dataConfig("Message.EnableSellDelayToUse", "Sorry, but the SellAll Delay's &cdisabled&7, please enable it!"); - dataConfig("Message.EventCancelled", "&cEvent cancelled."); - dataConfig("Message.InvalidBooleanInput", "Sorry, you should type &a-true-&7 or &c-false-&7 here."); - dataConfig("Message.MissingPermission", "Sorry but you don't have the &cpermission&7 to use that!"); - dataConfig("Message.NoBlocksMine", "Sorry but this Mine's &cempty&7."); - dataConfig("Message.NoMines", "Sorry but &cthere aren't &7Mines to show."); - dataConfig("Message.NoRankupCommands", "Sorry, but there &caren't rankUpCommands&7 for this Rank!"); - dataConfig("Message.NoLadders", "Sorry but &cthere aren't &7ladders to show."); - dataConfig("Message.NoRanksPrestigesLadder", "There &caren't ranks&7 in the -prestiges- ladder!"); - dataConfig("Message.NoRanksFoundAdmin", "Sorry, the Ladder's &cempty&7!"); - dataConfig("Message.NoRanksFound", "Sorry, but this Ladder's &cempty&7!"); - dataConfig("Message.NoRanksFoundHelp1", "Sorry, the Ladder's &cempty&7 or &7["); - dataConfig("Message.NoRanksFoundHelp2", "] &cdoesn't exists!"); - dataConfig("Message.LadderPrestigesNotFound", "Ladder -prestiges- &cnot found&7!"); - dataConfig("Message.TooManyBlocks", "Sorry, but there're &ctoo many&7 Blocks and the max's 54 for the GUI"); - dataConfig("Message.TooManyLadders", "Sorry, but there're &ctoo many&7 Ladders and the max's 54 for the GUI"); - dataConfig("Message.TooManyMines", "Sorry, but there're &ctoo many&7 Mines and the max's 54 for the GUI"); - dataConfig("Message.TooManyRankupCommands", "Sorry, but there're &ctoo many&7 RankupCommands and the max's 54 for the GUI"); - dataConfig("Message.TooManyRanks", "Sorry, but there're &ctoo many&7 Ranks and the max's 54 for the GUI"); - dataConfig("Message.TooManySellAllItems", "There are &ctoo many&7 Items and the MAX for the GUI's 54!"); - dataConfig("Message.mineNameRename", "Please write the &6mineName &7you'd like to use and &6submit&7."); - dataConfig("Message.mineNameRenameClose", "Input &cclose &7to cancel or wait &c30 seconds&7."); - dataConfig("Message.mineNameRenameClosed", "Rename Mine &cclosed&7, nothing got changed!"); - dataConfig("Message.mineOrGuiDisabled", "GUI and/or GUI Mines is &cdisabled&7. Check GuiConfig.yml."); - dataConfig("Message.mineMissingGuiPermission", "You lack the &cpermissions&7 to use GUI Mines"); - dataConfig("Message.MineShowItemEditSuccess", "Mine show item edited with success."); - dataConfig("Message.OutOfTimeNoChanges", "You ran out of time, &cnothing changed&7."); - dataConfig("Message.PrestigeCancelled", "Prestige &ccancelled&7!"); - dataConfig("Message.PrestigeCancelledWrongKeyword", "Prestige &ccancelled&7, you didn't type the word: &aconfirm&7."); - dataConfig("Message.PrestigeRanOutOfTime", "You ran out of time, &cPrestige cancelled&7."); - dataConfig("Message.PrestigesDisabledDefault", "Prestiges are &cdisabled&7 by default, please edit it in your config.yml!"); - dataConfig("Message.ConfirmPrestige", "&aConfirm&7: Type the word &aconfirm&7 to confirm"); - dataConfig("Message.CancelPrestige", "&cCancel&7: Type the word &ccancel&7 to cancel, &cyou've 30 seconds."); - dataConfig("Message.PrestigesAreDisabled", "Prestiges are &cdisabled&7. Check config.yml."); - dataConfig("Message.GuiOrPrestigesDisabled", "GUI and/or GUI Prestiges is &cdisabled&7. Check GuiConfig.yml."); - dataConfig("Message.GuiClosedWithSuccess", "The GUI got closed."); - dataConfig("Message.CantFindPrestiges", "The prestige ladder has &cno prestiges&7!"); - dataConfig("Message.missingGuiPrestigesPermission", "You lack the &cpermissions&7 to use GUI prestiges"); - dataConfig("Message.rankTagRename", "Please write the &6tag &7you'd like to use and &6submit&7."); - dataConfig("Message.rankTagRenameClose", "Input &cclose &7to cancel or wait &c30 seconds&7."); - dataConfig("Message.rankTagRenameClosed", "Rename tag &cclosed&7, nothing got changed!"); - dataConfig("Message.rankGuiDisabledOrAllGuiDisabled", "GUI and/or GUI Ranks is &cdisabled&7. Check GuiConfig.yml (%s %s)"); - dataConfig("Message.rankGuiMissingPermission", "You lack the &cpermissions&7 to use the Ranks GUI."); - dataConfig("Message.SellAllAutoSellEarnedMoney", "You earned with AutoSell: "); - dataConfig("Message.SellAllAutoSellEarnedMoneyCurrency", "$"); - dataConfig("Message.SellAllAutoSellMissingPermission", "You don't have the &cpermission&7 to edit AutoSell."); - dataConfig("Message.SellAllAutoSellEnabled", "Autosell has been &aenabled&7."); - dataConfig("Message.SellAllAutoSellDisabled", "Autosell has been &cdisabled&7."); - dataConfig("Message.SellAllAutoSellAlreadyEnabled", "AutoSell has already been &aenabled&7!"); - dataConfig("Message.SellAllAutoSellAlreadyDisabled", "AutoSell has already been &cdisabled&7!"); - dataConfig("Message.SellAllAutoPerUserToggleableAlreadyEnabled", "AutoSell perUserToggleable's already &aenabled&7!"); - dataConfig("Message.SellAllAutoPerUserToggleableAlreadyDisabled", "AutoSell perUserToggleable's already &cdisabled&7!"); - dataConfig("Message.SellAllAutoPerUserToggleableEnabled", "SellAll PerUserToggleable &aEnabled&7!"); - dataConfig("Message.SellAllAutoPerUserToggleableDisabled", "SellAll PerUserToggleable &cDisabled&7!"); - dataConfig("Message.SellAllCurrencyChat1", "&3Started setup of new currency for SellAll!"); - dataConfig("Message.SellAllCurrencyChat2", "Type &ccancel &7to cancel."); - dataConfig("Message.SellAllCurrencyChat3", "Type &3default &7to set to default currency."); - dataConfig("Message.SellAllCurrencyChat4", "Type the &aCurrency name &7to set the new currency."); - dataConfig("Message.SellAllCurrencyEditedSuccess", "SellAll Currency edited with success!"); - dataConfig("Message.SellAllCurrencyEditCancelled", "SellAll edit currency &ccancelled&7."); - dataConfig("Message.SellAllCurrencyNotFound", "No active economy supports the currency named '%s'."); - dataConfig("Message.SellAllDefaultSuccess", "Default Values added with &asuccess&7!"); - dataConfig("Message.SellAllDefaultMissingPermission", "Sorry but you're missing the &cpermission!"); - dataConfig("Message.SellAllIsDisabled", "Sorry but the SellAll Feature's &cdisabled&7 in the config.yml"); - dataConfig("Message.SellAllEditedWithSuccess", "&7] edited with &asuccess&7!"); - dataConfig("Message.SellAllSubCommandNotFound", "Sub-command &cnot found&7, please use /sellall help for help!"); - dataConfig("Message.SellAllMultipliersAreDisabled", "Multipliers are &cdisabled&7 in the SellAll config!"); - dataConfig("Message.SellAllMultiplierWrongFormat", "&cWrong format&7, please use /sellall multiplier add/delete "); - dataConfig("Message.SellAllMissingPermission", "Sorry, but you don't have the &cpermission&7"); - dataConfig("Message.SellAllMissingPermissionToToggleAutoSell", "Sorry but you're missing the &cpermission&7 to use that! "); - dataConfig("Message.SellAllRanksDisabled", "The Ranks module's &cdisabled&7 or not found!"); - dataConfig("Message.SellAllPrestigeLadderNotFound", "&cCan't find&7 the Prestiges Ladder, they might be &cdisabled&7 in the config.yml!"); - dataConfig("Message.SellAllCantFindPrestigeOrRank", "&cCan't find&7 the Prestige/Rank: "); - dataConfig("Message.SellAllRankNotFoundInPrestigeLadder", "The -prestiges- ladder &cdoesn't contain&7 the Rank: "); - dataConfig("Message.SellAllMultiplierNotANumber", "Sorry but the multiplier &cisn't a number&7!"); - dataConfig("Message.SellAllMultiplierNotNumber2", " Here-> "); - dataConfig("Message.SellAllConfigSaveFail", "Sorry, &csomething went wrong&7 while saving the config!"); - dataConfig("Message.SellAllMultiplierEditSaveSuccess", "Multiplier got added or edited with &asuccess&7!"); - dataConfig("Message.SellAllMultiplierFormat", "Please use this format: /sellall multiplier delete ."); - dataConfig("Message.SellAllCantFindMultiplier", "&cCan't find&7 the Multiplier of the prestige "); - dataConfig("Message.SellAllCantFindMultiplier2", " &7in the sellallconfig.yml"); - dataConfig("Message.SellAllMultiplierDeleteSuccess", "Multiplier &cdeleted&7 with &asuccess&7!"); - dataConfig("Message.SellAllWrongFormatCommand", "&cWrong format&7, use /sellall help for help."); - dataConfig("Message.SellAllPleaseAddItem", "Please &aadd&7 an ITEM_ID [example: /sellall add COAL_ORE ]"); - dataConfig("Message.SellAllAddPrice", "Please &aadd&7 a price or value for the item [example: /sellall add COAL_ORE 100]"); - dataConfig("Message.SellAllWrongID", "Sorry but the &cITEM_ID's wrong&7, please check it!"); - dataConfig("Message.SellAllValueNotNumber", "Sorry but the value &cisn't a number&7!"); - dataConfig("Message.SellAllMissingID", "Please &aadd&7 an ITEM_ID [example: /sellall delete COAL_ORE]"); - dataConfig("Message.SellAllNotFoundStringConfig", " not found in the config or got already &cdeleted&7."); - dataConfig("Message.SellAllNotFoundEdit", " not found in the config!"); - dataConfig("Message.SellAllDeletedSuccess", " &cDeleted&7 with &asuccess&7!"); - dataConfig("Message.SellAllAddSuccess", "] &aadded&7 with &asuccess&7!"); - dataConfig("Message.SellAllAlreadyAdded", " &cgot already added before&7, to edit it please use the /sellall edit command!"); - dataConfig("Message.SellAllCommandEditSuccess", "] &aedited&7 with &asuccess&7!"); - dataConfig("Message.SellAllYouArentPlayer", "You &caren't&a a player"); - dataConfig("Message.SellAllNothingToSell", "You have &cnothing&7 to sell!"); - dataConfig("Message.SellAllYouGotMoney", "You got &a$"); - dataConfig("Message.SellAllGUIDisabled", "Sorry but the GUI's &cdisabled&7 in the SellAllConfig.yml."); - dataConfig("Message.SellAllAutoSell", "Your inventory's full, &aAutoSell activated&7!"); - dataConfig("Message.SellAllSignOnly", "Sorry but you can use SellAll only by touching a sign (or with the ByPass permission)."); - dataConfig("Message.SellAllSignNotify", "Using &aSellAll&7 from a Sign with &asuccess&7!"); - dataConfig("Message.SellAllSignMissingPermission", "Sorry, but you don't have the &cpermission&7 to use this!"); - dataConfig("Message.SellAllEmpty", "&cThere aren't&7 items in the sellall config,\n please add one and/or restart the server!"); - dataConfig("Message.SellAllAutoEnabled", "SellAll-Auto &aenabled &7with &asuccess&7!"); - dataConfig("Message.SellAllAutoDisabled", "SellAll-Auto &cdisabled &7with &asuccess&7!"); - dataConfig("Message.SellAllWaitDelay", "Please &cwait&7 before using this command again!"); - dataConfig("Message.SellAllDelayAlreadyEnabled", "SellAll Delay already &aenabled&7!"); - dataConfig("Message.SellAllDelayAlreadyDisabled", "SellAll Delay already &cdisabled&7!"); - dataConfig("Message.SellAllDelayEnabled", "SellAll Delay &aenabled &7with &asuccess&7!"); - dataConfig("Message.SellAllDelayDisabled", "SellAll Delay &cdisabled &7with &asuccess&7!"); - dataConfig("Message.SellAllDelayEditedWithSuccess", "SellAll Delay edited with &asuccess&7!"); - dataConfig("Message.SellAllDelayNotNumber", "Delay value &cisn't&7 a number!"); - dataConfig("Message.SellAllGUIEmpty", "Sorry but there &caren't&7 Blocks in the SellAll Shop!"); - dataConfig("Message.SellAllGUIEmpty2", "&7[&cTIP&7] &7You can &aadd&7 one using the command /sellall add!"); - dataConfig("Message.SellAllTriggerAlreadyEnabled", "SellAll trigger's already &aenabled&7."); - dataConfig("Message.SellAllTriggerAlreadyDisabled", "SellAll trigger's already &cdisabled&7."); - dataConfig("Message.SellAllTriggerEnabled", "SellAll trigger &aEnabled&7."); - dataConfig("Message.SellAllTriggerDisabled", "SellAll trigger &cDisabled&7."); - dataConfig("Message.SellAllTriggerIsDisabled", "SellAll trigger's &cdisabled&7 in the SellAllConfig.yml."); - dataConfig("Message.SellAllTriggerMissingItem", "Please add a valid Item ID for SellAll Shift+Right Click Trigger."); - dataConfig("Message.SellAllTriggerItemAddSuccess", "SellAll trigger Item added with &asuccess&7!"); - dataConfig("Message.SellAllTriggerItemEditSuccess", "SellAll trigger Item edited with &asuccess&7!"); - dataConfig("Message.SellAllTriggerItemDeleteSuccess", "SellAll trigger Item deleted with &asuccess&7!"); - dataConfig("Message.SellAllTriggerMissingItem", "There isn't an item in the SellAllConfig.yml trigger like that."); - dataConfig("Message.TooLowValue", "&cToo low value."); - dataConfig("Message.TooHighValue", "&cToo high value."); - dataConfig("Message.GUIReloadSuccess", "GUIs reloaded with success!"); - dataConfig("Setup.Message.MissingPermission", "Sorry but you don't have the &cpermission&7 [-prison.setup- or -prison.admin-]!"); - dataConfig("Setup.Message.WrongFormat", "You're &cmissing&7 the last argument -mines- or -ranks-, / setup -mines- or -ranks- !"); - dataConfig("Setup.Message.WelcomeToRanksSetup", "Hi and welcome to the Ranks Setup, please &cwait&7 until it'll be completed!"); - dataConfig("Setup.Message.SuccessRanksSetup", "The Ranks Setup got &acompleted&7 with &asuccess&7 and the Ranks got &aadded&7 to the default ladder, please check the logs if something's missing!"); - dataConfig("Setup.Message.Aborted", "Prison Setup &cCancelled&7."); - } + public enum StringID { + + spigot_gui_lore_click_to_add, + spigot_gui_lore_click_to_add_backpack, + spigot_gui_lore_click_to_cancel, + spigot_gui_lore_click_to_close, + spigot_gui_lore_click_to_confirm, + spigot_gui_lore_click_to_decrease, + spigot_gui_lore_click_to_delete, + spigot_gui_lore_click_to_disable, + spigot_gui_lore_click_to_edit, + spigot_gui_lore_click_to_enable, + spigot_gui_lore_click_to_increase, + spigot_gui_lore_click_to_manage_rank, + spigot_gui_lore_click_to_open, + spigot_gui_lore_click_to_rankup, + spigot_gui_lore_click_to_rename, + spigot_gui_lore_click_to_select, + spigot_gui_lore_click_to_start_block_setup, + spigot_gui_lore_click_to_teleport, + spigot_gui_lore_click_to_use, + + spigot_gui_lore_click_left_to_confirm, + spigot_gui_lore_click_left_to_edit, + spigot_gui_lore_click_left_to_open, + spigot_gui_lore_click_left_to_reset, + + spigot_gui_lore_click_right_to_cancel, + spigot_gui_lore_click_right_to_delete, + spigot_gui_lore_click_right_to_disable, + spigot_gui_lore_click_right_to_enable, + spigot_gui_lore_click_right_to_toggle, + + spigot_gui_lore_click_right_and_shift_to_delete, + spigot_gui_lore_click_right_and_shift_to_disable, + spigot_gui_lore_click_right_and_shift_to_toggle, + + spigot_gui_lore_backpack_id, + spigot_gui_lore_blocks, + spigot_gui_lore_blocktype, + spigot_gui_lore_chance, + spigot_gui_lore_command, + spigot_gui_lore_currency, + spigot_gui_lore_delay, + spigot_gui_lore_id, + spigot_gui_lore_info, + spigot_gui_lore_minename, + spigot_gui_lore_multiplier, + spigot_gui_lore_name, + spigot_gui_lore_owner, + spigot_gui_lore_percentage, + spigot_gui_lore_permission, + spigot_gui_lore_players_at_rank, + spigot_gui_lore_prestige_name, + spigot_gui_lore_price, + spigot_gui_lore_radius, + spigot_gui_lore_rank_tag, + spigot_gui_lore_reset_time, + spigot_gui_lore_show_item, + spigot_gui_lore_size, + spigot_gui_lore_spawnpoint, + spigot_gui_lore_volume, + spigot_gui_lore_value, + spigot_gui_lore_world, + + spigot_gui_lore_disabled, + spigot_gui_lore_enabled, + spigot_gui_lore_locked, + spigot_gui_lore_next_page, + spigot_gui_lore_prior_page, + spigot_gui_lore_rankup, + spigot_gui_lore_selected, + spigot_gui_lore_unlocked, + + spigot_gui_lore_add_backpack_instruction_1, + spigot_gui_lore_add_backpack_instruction_2, + spigot_gui_lore_add_backpack_instruction_3, + spigot_gui_lore_prestige_warning_1, + spigot_gui_lore_prestige_warning_2, + spigot_gui_lore_prestige_warning_3, + spigot_gui_lore_ranks_setup_1, + spigot_gui_lore_ranks_setup_2, + spigot_gui_lore_ranks_setup_3, + spigot_gui_lore_ranks_setup_4, + spigot_gui_lore_ranks_setup_5, + spigot_gui_lore_ranks_setup_6, + spigot_gui_lore_ranks_setup_7, + spigot_gui_lore_ranks_setup_8, + spigot_gui_lore_sellall_delay_use_1, + spigot_gui_lore_sellall_delay_use_2, + spigot_gui_lore_set_mine_delay_instruction_1, + spigot_gui_lore_set_mine_delay_instruction_2, + spigot_gui_lore_set_mine_delay_instruction_3, + spigot_gui_lore_show_item_description_1, + spigot_gui_lore_show_item_description_2, + spigot_gui_lore_show_item_description_3, + spigot_gui_lore_skip_reset_instruction_1, + spigot_gui_lore_skip_reset_instruction_2, + spigot_gui_lore_skip_reset_instruction_3, + + spigot_gui_lore_autofeatures_button_description, + spigot_gui_lore_backpacks_button_description, + spigot_gui_lore_disable_notifications, + spigot_gui_lore_enable_radius_mode, + spigot_gui_lore_enable_within_mode, + spigot_gui_lore_mines_button_description, + spigot_gui_lore_no_multipliers, + spigot_gui_lore_ranks_button_description, + spigot_gui_lore_rankup_if_enough_money, + spigot_gui_lore_sellall_button_description, + spigot_gui_lore_sellall_edit_info, + spigot_gui_lore_tp_to_mine, + + + spigot_message_missing_permission, + spigot_message_chat_event_time_end, + spigot_message_event_cancelled, + spigot_message_command_wrong_format, + spigot_message_console_error, + + spigot_message_ladder_default_empty, + + spigot_message_mines_disabled, + spigot_message_mines_name_chat_1, + spigot_message_mines_name_chat_2, + spigot_message_mines_name_chat_cancelled, + spigot_message_mines_item_show_edit_success, + spigot_message_mines_or_gui_disabled, + + spigot_message_backpack_cant_own, + spigot_message_backpack_delete_error, + spigot_message_backpack_delete_success, + spigot_message_backpack_format_error, + spigot_message_backpack_limit_decrement_fail, + spigot_message_backpack_limit_edit_success, + spigot_message_backpack_limit_not_number, + spigot_message_backpack_limit_reached, + spigot_message_backpack_missing_playername, + spigot_message_backpack_resize_success, + spigot_message_backpack_size_must_be_multiple_of_9, + + spigot_message_prestiges_disabled, + spigot_message_prestiges_empty, + spigot_message_prestiges_or_gui_disabled, + spigot_message_prestiges_confirm, + spigot_message_prestiges_cancel, + spigot_message_prestiges_cancelled, + spigot_message_prestiges_cancelled_wrong_keyword, + + spigot_message_ranks_disabled, + spigot_message_ranks_or_gui_disabled, + spigot_message_ranks_tag_chat_rename_1, + spigot_message_ranks_tag_chat_rename_2, + spigot_message_ranks_tag_chat_cancelled, + + spigot_message_sellall_auto_already_enabled, + spigot_message_sellall_auto_already_disabled, + spigot_message_sellall_auto_disabled, + spigot_message_sellall_auto_disabled_cant_use, + spigot_message_sellall_auto_enabled, + spigot_message_sellall_auto_perusertoggleable_enabled, + spigot_message_sellall_auto_perusertoggleable_disabled, + spigot_message_sellall_auto_perusertoggleable_already_enabled, + spigot_message_sellall_auto_perusertoggleable_already_disabled, + spigot_message_sellall_boolean_input_invalid, + spigot_message_sellall_cant_find_item_config, + spigot_message_sellall_currency_chat_1, + spigot_message_sellall_currency_chat_2, + spigot_message_sellall_currency_chat_3, + spigot_message_sellall_currency_chat_4, + spigot_message_sellall_currency_edit_success, + spigot_message_sellall_currency_not_found, + spigot_message_sellall_hand_disabled, + spigot_message_sellall_hand_enabled, + spigot_message_sellall_hand_is_disabled, + spigot_message_sellall_item_add_success, + spigot_message_sellall_item_already_added, + spigot_message_sellall_item_delete_success, + spigot_message_sellall_item_edit_success, + spigot_message_sellall_item_id_not_found, + spigot_message_sellall_item_missing_name, + spigot_message_sellall_item_missing_price, + spigot_message_sellall_item_not_found, + spigot_message_sellall_default_values_success, + spigot_message_sellall_delay_already_enabled, + spigot_message_sellall_delay_already_disabled, + spigot_message_sellall_delay_disabled, + spigot_message_sellall_delay_disabled_cant_use, + spigot_message_sellall_delay_edit_success, + spigot_message_sellall_delay_enabled, + spigot_message_sellall_delay_not_number, + spigot_message_sellall_delay_wait, + spigot_message_sellall_gui_disabled, + spigot_message_sellall_money_earned, + spigot_message_sellall_multiplier_add_success, + spigot_message_sellall_multiplier_are_disabled, + spigot_message_sellall_multiplier_cant_find, + spigot_message_sellall_multiplier_delete_success, + spigot_message_sellall_multiplier_disabled, + spigot_message_sellall_multiplier_edit_success, + spigot_message_sellall_multiplier_enabled, + spigot_message_sellall_sell_empty, + spigot_message_sellall_sell_nothing_sellable, + spigot_message_sellall_sell_sign_only, + spigot_message_sellall_sell_sign_notify, + spigot_message_sellall_trigger_already_disabled, + spigot_message_sellall_trigger_already_enabled, + spigot_message_sellall_trigger_disabled, + spigot_message_sellall_trigger_enabled, + spigot_message_sellall_trigger_is_disabled, + spigot_message_sellall_trigger_item_add_success, + spigot_message_sellall_trigger_item_cant_find, + spigot_message_sellall_trigger_item_delete_success, + spigot_message_sellall_trigger_item_missing, - public FileConfiguration getFileGuiMessagesConfig(){ - return conf; + spigot_message_gui_backpack_disabled, + spigot_message_gui_backpack_empty, + spigot_message_gui_backpack_too_many, + spigot_message_gui_close_success, + spigot_message_gui_error, + spigot_message_gui_error_empty, + spigot_message_gui_ladder_empty, + spigot_message_gui_ladder_too_many, + spigot_message_gui_mines_empty, + spigot_message_gui_mines_too_many, + spigot_message_gui_prestiges_empty, + spigot_message_gui_prestiges_too_many, + spigot_message_gui_ranks_empty, + spigot_message_gui_ranks_rankup_commands_empty, + spigot_message_gui_ranks_rankup_commands_too_many, + spigot_message_gui_ranks_too_many, + spigot_message_gui_reload_success, + spigot_message_gui_sellall_disabled, + spigot_message_gui_sellall_empty, + spigot_message_gui_too_high, + spigot_message_gui_too_low_value, } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/NewMessagesConfig.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/NewMessagesConfig.java deleted file mode 100644 index e613c1fed..000000000 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/NewMessagesConfig.java +++ /dev/null @@ -1,167 +0,0 @@ -package tech.mcprison.prison.spigot.configs; - -import tech.mcprison.prison.spigot.SpigotPrison; - -import java.io.*; -import java.util.Properties; - -public class NewMessagesConfig { - - private static NewMessagesConfig instance; - private Properties properties = new Properties(); - private final String defaultLanguage = SpigotPrison.getInstance().getConfig().getString("default-language"); - private final String path = "/module_conf/spigot/lang/"; - - /** - * Get MessagesConfig class and initialize it if necessary. - * */ - public static NewMessagesConfig get(){ - if (instance == null){ - instance = new NewMessagesConfig(); - instance.initConfig(); - } - return instance; - } - - /** - * Initialize the config, reading and caching data. - * */ - private void initConfig(){ - try(FileInputStream data = new FileInputStream(SpigotPrison.getInstance().getDataFolder() + path + defaultLanguage + ".properties")){ - - Properties temp = new Properties(); - temp.load(new InputStreamReader(data)); - properties = temp; - - } catch (IOException ex){ - ex.printStackTrace(); - } - } - - /** - * Get String. - * */ - public String getString(StringID message){ - return properties.getProperty(message.toString()); - } - - public void reload(){ - initConfig(); - } - - public enum StringID { - - spigot_gui_lore_click_to_add, - spigot_gui_lore_click_to_add_backpack, - spigot_gui_lore_click_to_cancel, - spigot_gui_lore_click_to_close, - spigot_gui_lore_click_to_confirm, - spigot_gui_lore_click_to_decrease, - spigot_gui_lore_click_to_delete, - spigot_gui_lore_click_to_disable, - spigot_gui_lore_click_to_edit, - spigot_gui_lore_click_to_enable, - spigot_gui_lore_click_to_increase, - spigot_gui_lore_click_to_manage_rank, - spigot_gui_lore_click_to_open, - spigot_gui_lore_click_to_rankup, - spigot_gui_lore_click_to_rename, - spigot_gui_lore_click_to_select, - spigot_gui_lore_click_to_start_block_setup, - spigot_gui_lore_click_to_teleport, - spigot_gui_lore_click_to_use, - - spigot_gui_lore_click_left_to_confirm, - spigot_gui_lore_click_left_to_edit, - spigot_gui_lore_click_left_to_open, - spigot_gui_lore_click_left_to_reset, - - spigot_gui_lore_click_right_to_cancel, - spigot_gui_lore_click_right_to_delete, - spigot_gui_lore_click_right_to_disable, - spigot_gui_lore_click_right_to_enable, - spigot_gui_lore_click_right_to_toggle, - - spigot_gui_lore_click_right_and_shift_to_delete, - spigot_gui_lore_click_right_and_shift_to_disable, - spigot_gui_lore_click_right_and_shift_to_toggle, - - spigot_gui_lore_backpack_id, - spigot_gui_lore_blocks, - spigot_gui_lore_blocktype, - spigot_gui_lore_chance, - spigot_gui_lore_command, - spigot_gui_lore_currency, - spigot_gui_lore_delay, - spigot_gui_lore_id, - spigot_gui_lore_info, - spigot_gui_lore_minename, - spigot_gui_lore_multiplier, - spigot_gui_lore_name, - spigot_gui_lore_owner, - spigot_gui_lore_percentage, - spigot_gui_lore_permission, - spigot_gui_lore_players_at_rank, - spigot_gui_lore_prestige_name, - spigot_gui_lore_price, - spigot_gui_lore_radius, - spigot_gui_lore_rank_tag, - spigot_gui_lore_reset_time, - spigot_gui_lore_show_item, - spigot_gui_lore_size, - spigot_gui_lore_spawnpoint, - spigot_gui_lore_volume, - spigot_gui_lore_value, - spigot_gui_lore_world, - - spigot_gui_lore_disabled, - spigot_gui_lore_enabled, - spigot_gui_lore_locked, - spigot_gui_lore_next_page, - spigot_gui_lore_prior_page, - spigot_gui_lore_rankup, - spigot_gui_lore_selected, - spigot_gui_lore_unlocked, - - spigot_gui_lore_add_backpack_instruction_1, - spigot_gui_lore_add_backpack_instruction_2, - spigot_gui_lore_add_backpack_instruction_3, - spigot_gui_lore_prestige_warning_1, - spigot_gui_lore_prestige_warning_2, - spigot_gui_lore_prestige_warning_3, - spigot_gui_lore_ranks_setup_1, - spigot_gui_lore_ranks_setup_2, - spigot_gui_lore_ranks_setup_3, - spigot_gui_lore_ranks_setup_4, - spigot_gui_lore_ranks_setup_5, - spigot_gui_lore_ranks_setup_6, - spigot_gui_lore_ranks_setup_7, - spigot_gui_lore_ranks_setup_8, - spigot_gui_lore_sellall_delay_use_1, - spigot_gui_lore_sellall_delay_use_2, - spigot_gui_lore_set_mine_delay_instruction_1, - spigot_gui_lore_set_mine_delay_instruction_2, - spigot_gui_lore_set_mine_delay_instruction_3, - spigot_gui_lore_show_item_description_1, - spigot_gui_lore_show_item_description_2, - spigot_gui_lore_show_item_description_3, - spigot_gui_lore_skip_reset_instruction_1, - spigot_gui_lore_skip_reset_instruction_2, - spigot_gui_lore_skip_reset_instruction_3, - - spigot_gui_lore_autofeatures_button_description, - spigot_gui_lore_backpacks_button_description, - spigot_gui_lore_disable_notifications, - spigot_gui_lore_enable_radius_mode, - spigot_gui_lore_enable_within_mode, - spigot_gui_lore_mines_button_description, - spigot_gui_lore_no_multipliers, - spigot_gui_lore_ranks_button_description, - spigot_gui_lore_rankup_if_enough_money, - spigot_gui_lore_sellall_button_description, - spigot_gui_lore_sellall_edit_info, - spigot_gui_lore_tp_to_mine, - - spigot_general_missing_permission - } -} diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java index 7b74cc0b7..a5d8cf9ed 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java @@ -42,10 +42,9 @@ import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.SpigotUtil; import tech.mcprison.prison.spigot.backpacks.BackpacksUtil; -import tech.mcprison.prison.spigot.commands.PrisonSpigotSellAllCommands; import tech.mcprison.prison.spigot.compat.Compatibility; import tech.mcprison.prison.spigot.compat.SpigotCompatibility; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.autofeatures.SpigotAutoBlockGUI; import tech.mcprison.prison.spigot.gui.autofeatures.SpigotAutoFeaturesGUI; @@ -94,10 +93,8 @@ public class ListenersPrisonManager implements Listener { private String tempChatVariable; private final Configuration config = SpigotPrison.getInstance().getConfig(); private final Configuration guiConfig = SpigotPrison.getInstance().getGuiConfig(); - - private final Configuration messages = SpigotPrison.getInstance().getMessagesConfig(); - private final NewMessagesConfig newMessages = SpigotPrison.getInstance().getNewMessagesConfig(); - boolean guiNotEnabled = !(config.getString("prison-gui-enabled").equalsIgnoreCase("true")); + private final MessagesConfig messages = SpigotPrison.getInstance().getMessagesConfig(); + boolean guiNotEnabled = !getBoolean(config.getString("prison-gui-enabled")); private Optional ladder; public ChatMode mode; @@ -186,93 +183,92 @@ public void onPlayerInteractEvent(PlayerInteractEvent e){ SellAllUtil sellAllUtil = SpigotPrison.getInstance().getSellAllUtil(); - // Check if SellAll Shift + Right Click is enabled. - if (sellAllUtil.isSellAllItemTriggerEnabled) { - // Check if the action if Shift + Right Click. - Player p = e.getPlayer(); - if (e.getAction().equals(Action.RIGHT_CLICK_AIR) && p.isSneaking()) { + if (sellAllUtil != null) { + // Check if SellAll Shift + Right Click is enabled. + if (sellAllUtil.isSellAllItemTriggerEnabled) { + // Check if the action if Shift + Right Click. + Player p = e.getPlayer(); + if (e.getAction().equals(Action.RIGHT_CLICK_AIR) && p.isSneaking()) { - // Check if a permission's required. - if (sellAllUtil.isSellAllItemTriggerPermissionEnabled) { - String permission = sellAllUtil.permissionItemTrigger; - if (permission != null && !p.hasPermission(permission)) { - return; + // Check if a permission's required. + if (sellAllUtil.isSellAllItemTriggerPermissionEnabled) { + String permission = sellAllUtil.permissionItemTrigger; + if (permission != null && !p.hasPermission(permission)) { + return; + } } - } - // Get the Items config section - ArrayList items = sellAllUtil.getItemTriggerXMaterials(); + // Get the Items config section + ArrayList items = sellAllUtil.getItemTriggerXMaterials(); - if (items != null && items.size() != 0) { - XMaterial inHandXMaterial = null; - if (e.getItem() != null){ - inHandXMaterial = SpigotUtil.getXMaterial(e.getItem().getType()); - } - if (inHandXMaterial != null) { - for (XMaterial xMaterialConf : items) { - if (xMaterialConf == inHandXMaterial) { - String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand("sellall sell"); - Bukkit.dispatchCommand(p, registeredCmd); - return; - } else if (xMaterialConf == SpigotUtil.getXMaterial(p.getInventory().getItemInMainHand().getType())) { - String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand("sellall sell"); - Bukkit.dispatchCommand(p, registeredCmd); - return; + if (items != null && items.size() != 0) { + XMaterial inHandXMaterial = null; + if (e.getItem() != null) { + inHandXMaterial = SpigotUtil.getXMaterial(e.getItem().getType()); + } + if (inHandXMaterial != null) { + for (XMaterial xMaterialConf : items) { + if (xMaterialConf == inHandXMaterial) { + sellAllUtil.sellAllSell(p, false, false, true, false, false, true); + return; + } else if (xMaterialConf == SpigotUtil.getXMaterial(p.getInventory().getItemInMainHand().getType())) { + sellAllUtil.sellAllSell(p, false, false, true, false, false, true); + return; + } } } } } } - } - // Check if the feature's enabled. - if (sellAllUtil.isSellAllSignEnabled) { + // Check if the feature's enabled. + if (sellAllUtil.isSellAllSignEnabled) { - // Get clicked block. - Material clickedBlock = null; - if (e.getClickedBlock() != null){ - clickedBlock = e.getClickedBlock().getType(); - } + // Get clicked block. + Material clickedBlock = null; + if (e.getClickedBlock() != null) { + clickedBlock = e.getClickedBlock().getType(); + } - // Check if the clicked block's a sign - if (clickedBlock == Material.SIGN || clickedBlock == Material.WALL_SIGN) { + // Check if the clicked block's a sign + if (clickedBlock == Material.SIGN || clickedBlock == Material.WALL_SIGN) { - // Get the player - Player p = e.getPlayer(); - String signTag = sellAllUtil.sellAllSignTag; - if (signTag == null) { - signTag = "&7[&3SellAll&7]"; - } + // Get the player + Player p = e.getPlayer(); + String signTag = sellAllUtil.sellAllSignTag; + if (signTag == null) { + signTag = "&7[&3SellAll&7]"; + } - // Get the action - Action action = e.getAction(); + // Get the action + Action action = e.getAction(); - // Check if the action's a click - if (action == Action.RIGHT_CLICK_BLOCK || action == Action.LEFT_CLICK_BLOCK) { + // Check if the action's a click + if (action == Action.RIGHT_CLICK_BLOCK || action == Action.LEFT_CLICK_BLOCK) { - // Get sign - Sign sign = (Sign) e.getClickedBlock().getState(); + // Get sign + Sign sign = (Sign) e.getClickedBlock().getState(); - // If there aren't lines in the sign this will void an error - try { + // If there aren't lines in the sign this will void an error + try { - // Check if the first like of the sign have the right tag - if (sign.getLine(0).equalsIgnoreCase(SpigotPrison.format(signTag))) { - String permissionUseSign = sellAllUtil.permissionUseSign; - if (sellAllUtil.isSellAllSignPermissionToUseEnabled && !p.hasPermission(permissionUseSign)) { - Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.SellAllSignMissingPermission") + " [&3" + permissionUseSign + "&7]"); - return; - } + // Check if the first like of the sign have the right tag + if (sign.getLine(0).equalsIgnoreCase(SpigotPrison.format(signTag))) { + String permissionUseSign = sellAllUtil.permissionUseSign; + if (sellAllUtil.isSellAllSignPermissionToUseEnabled && !p.hasPermission(permissionUseSign)) { + Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_missing_permission) + " [&3" + permissionUseSign + "&7]"); + return; + } - if (sellAllUtil.isSellAllSignNotifyEnabled) { - Output.get().sendInfo(new SpigotPlayer(p), messages.getString("Message.SellAllSignNotify")); - } + if (sellAllUtil.isSellAllSignNotifyEnabled) { + Output.get().sendInfo(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_sellall_sell_sign_notify)); + } - if (PrisonSpigotSellAllCommands.get() != null){ - PrisonSpigotSellAllCommands.get().sellAllSell(p); + sellAllUtil.sellAllSell(p, true, false, true, false, false, true); } + } catch (IndexOutOfBoundsException ignored) { } - } catch (IndexOutOfBoundsException ignored) {} + } } } } @@ -352,7 +348,7 @@ public void chatInteractData(Player p, ChatMode activeMode) { id = Bukkit.getScheduler().scheduleSyncDelayedTask(SpigotPrison.getInstance(), () -> { if (isChatEventActive) { removeChatEventPlayer(p); - Output.get().sendInfo(new SpigotPlayer(p), messages.getString("Message.OutOfTimeNoChanges")); + Output.get().sendInfo(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_chat_event_time_end)); isChatEventActive = false; } mode = null; @@ -412,7 +408,7 @@ public void onClick(InventoryClickEvent e){ // Close GUI button globally. if (buttonNameMain.equalsIgnoreCase("Close")) { - Output.get().sendInfo(new SpigotPlayer(p), messages.getString("Message.GuiClosedWithSuccess")); + Output.get().sendInfo(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_gui_close_success)); p.closeInventory(); return; } @@ -816,12 +812,11 @@ private void showBlock(InventoryClickEvent e, Player p, String[] parts) { conf.set("Options.Mines.MaterialType." + parts[1], parts[0]); conf.save(sellAllFile); } catch (IOException ex){ - Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.SellAllConfigSaveFail")); ex.printStackTrace(); return; } - Output.get().sendInfo(new SpigotPlayer(p), messages.getString("Message.MineShowItemEditSuccess") + " [" + parts[0] + "]"); + Output.get().sendInfo(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_mines_item_show_edit_success) + " [" + parts[0] + "]"); p.closeInventory(); } @@ -894,7 +889,7 @@ private void setSellAllPrestigeMultiplier(InventoryClickEvent e, Player p, Strin } else { // Tell to the player that the value's too low - Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.TooLowValue")); + Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_gui_too_low_value)); e.setCancelled(true); @@ -920,7 +915,7 @@ private void setSellAllPrestigeMultiplier(InventoryClickEvent e, Player p, Strin } else { // Close the GUI and tell it to the player - Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.TooHighValue")); + Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_gui_too_high)); e.setCancelled(true); p.closeInventory(); return; @@ -1006,7 +1001,7 @@ private void sellAllDelayGUI(InventoryClickEvent e, Player p, String[] parts) { } else if (e.isRightClick()){ // Send a message to the player - Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.EventCancelled")); + Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_event_cancelled)); e.setCancelled(true); @@ -1038,7 +1033,7 @@ private void sellAllDelayGUI(InventoryClickEvent e, Player p, String[] parts) { } else { // Tell to the player that the value's too low - Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.TooLowValue")); + Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_gui_too_low_value)); e.setCancelled(true); @@ -1064,7 +1059,7 @@ private void sellAllDelayGUI(InventoryClickEvent e, Player p, String[] parts) { } else { // Close the GUI and tell it to the player - Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.TooHighValue")); + Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_gui_too_high)); e.setCancelled(true); p.closeInventory(); return; @@ -1158,7 +1153,7 @@ private void sellAllAdminGUI(InventoryClickEvent e, Player p, String buttonNameM SellAllAdminGUI gui = new SellAllAdminGUI(p); gui.open(); } else { - Output.get().sendInfo(new SpigotPlayer(p), messages.getString("Message.EnableAutoSellToUse")); + Output.get().sendInfo(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_sellall_auto_disabled_cant_use)); } break; } @@ -1200,7 +1195,7 @@ private void sellAllAdminGUI(InventoryClickEvent e, Player p, String buttonNameM SellAllAdminGUI gui = new SellAllAdminGUI(p); gui.open(); } else { - Output.get().sendInfo(new SpigotPlayer(p), messages.getString("Message.EnableSellDelayToUse")); + Output.get().sendInfo(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_sellall_delay_disabled_cant_use)); } break; } @@ -1208,10 +1203,10 @@ private void sellAllAdminGUI(InventoryClickEvent e, Player p, String buttonNameM case "SellAll-Currency":{ // Send messages to the player - Output.get().sendInfo(new SpigotPlayer(p), messages.getString("Message.SellAllCurrencyChat1")); - Output.get().sendInfo(new SpigotPlayer(p), messages.getString("Message.SellAllCurrencyChat2")); - Output.get().sendInfo(new SpigotPlayer(p), messages.getString("Message.SellAllCurrencyChat3")); - Output.get().sendInfo(new SpigotPlayer(p), messages.getString("Message.SellAllCurrencyChat4")); + Output.get().sendInfo(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_sellall_currency_chat_1)); + Output.get().sendInfo(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_sellall_currency_chat_2)); + Output.get().sendInfo(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_sellall_currency_chat_3)); + Output.get().sendInfo(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_sellall_currency_chat_4)); chatInteractData(p, ChatMode.SellAll_Currency); p.closeInventory(); @@ -1224,13 +1219,13 @@ private void sellAllAdminGUI(InventoryClickEvent e, Player p, String buttonNameM boolean multiplierEnabled = getBoolean(sellAllConfig.getString("Options.Multiplier_Enabled")); if (!multiplierEnabled){ - Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.SellAllMultipliersAreDisabled")); + Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_sellall_multiplier_are_disabled)); return; } else { if (sellAllConfig.getConfigurationSection("Multiplier").getKeys(false).size() == 0) { - Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.EmptyGui")); + Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_gui_error_empty)); e.setCancelled(true); return; } else { @@ -1273,7 +1268,7 @@ private void prisonSetupConfirmGUI(InventoryClickEvent e, Player p, String[] par if (parts[0].equalsIgnoreCase("Confirm:")){ Bukkit.dispatchCommand(p, "ranks autoConfigure"); } else if (parts[0].equalsIgnoreCase("Cancel:")){ - Output.get().sendInfo(new SpigotPlayer(p), messages.getString("Setup.Message.Aborted")); + Output.get().sendInfo(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_event_cancelled)); } p.closeInventory(); e.setCancelled(true); @@ -1327,25 +1322,6 @@ private void mineBlockPercentage(InventoryClickEvent e, Player p, String[] parts return; } - // If Close, part 4 won't be defined so handle the close first. - - // What? - /*if (part1.equalsIgnoreCase( "Close" )) { - - int pos = 0; - try { - pos = Integer.parseInt( part3 ); - } - catch(NumberFormatException ignored) {} - - SpigotBlocksListGUI gui = new SpigotBlocksListGUI(p, part2, pos); - - p.closeInventory(); - - gui.open(); - return; - }*/ - String part4 = null; try{ part4 = parts[3]; @@ -1833,8 +1809,8 @@ private void rankManagerGUI(InventoryClickEvent e, Player p, String[] parts) { } else if (buttonName.equalsIgnoreCase("RankTag")){ // Send messages to the player. - Output.get().sendInfo(new SpigotPlayer(p), messages.getString("Message.rankTagRename")); - Output.get().sendInfo(new SpigotPlayer(p), messages.getString("Message.rankTagRenameClose")); + Output.get().sendInfo(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_ranks_tag_chat_rename_1)); + Output.get().sendInfo(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_ranks_tag_chat_rename_2)); // Start the async task. tempChatVariable = rankName; chatInteractData(p, ChatMode.RankName); @@ -1848,7 +1824,7 @@ private void rankManagerGUI(InventoryClickEvent e, Player p, String[] parts) { private void playerRanksGUI(InventoryClickEvent e, Player p, String buttonNameMain) { // Check the buttonName and do the actions. - if (buttonNameMain.equals(SpigotPrison.format(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_rankup).substring(2)))){ + if (buttonNameMain.equals(SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_gui_lore_rankup).substring(2)))){ Bukkit.dispatchCommand(p, "rankup " + guiConfig.getString("Options.Ranks.Ladder")); p.closeInventory(); } @@ -2121,8 +2097,8 @@ private void mineInfoGUI(InventoryClickEvent e, Player p, String[] parts) { case "Mine_Name:": { // Send messages to the player - Output.get().sendInfo(new SpigotPlayer(p), messages.getString("Message.mineNameRename")); - Output.get().sendInfo(new SpigotPlayer(p), messages.getString("Message.mineNameRenameClose")); + Output.get().sendInfo(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_mines_name_chat_1)); + Output.get().sendInfo(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_mines_name_chat_2)); // Start the async task tempChatVariable = mineName; @@ -2809,7 +2785,7 @@ private void sellAllCurrencyChat(AsyncPlayerChatEvent e, Player p, String messag // Check message and do the action String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "sellall set currency" ); if (message.equalsIgnoreCase("cancel")){ - Output.get().sendInfo(new SpigotPlayer(p), messages.getString("Message.SellAllCurrencyEditCancelled")); + Output.get().sendInfo(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_event_cancelled)); } else if (message.equalsIgnoreCase("default")){ Bukkit.getScheduler().runTask(SpigotPrison.getInstance(), () -> Bukkit.getServer().dispatchCommand(p, registeredCmd + " default")); } else { @@ -2826,11 +2802,11 @@ private void prestigeAction(AsyncPlayerChatEvent e, Player p, String message) { // Check the chat message and do the actions if (message.equalsIgnoreCase("cancel")) { - Output.get().sendInfo(new SpigotPlayer(p), messages.getString("Message.PrestigeCancelled")); + Output.get().sendInfo(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_prestiges_cancelled)); } else if (message.equalsIgnoreCase("confirm")) { Bukkit.getScheduler().runTask(SpigotPrison.getInstance(), () -> Bukkit.getServer().dispatchCommand(p, "rankup prestiges")); } else { - Output.get().sendInfo(new SpigotPlayer(p), messages.getString("Message.PrestigeCancelledWrongKeyword")); + Output.get().sendInfo(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_prestiges_cancelled_wrong_keyword)); } // Cancel the event e.setCancelled(true); @@ -2842,7 +2818,7 @@ private void mineAction(AsyncPlayerChatEvent e, Player p, String message) { // Check the chat message and do the action if (message.equalsIgnoreCase("close")) { - Output.get().sendInfo(new SpigotPlayer(p), messages.getString("Message.mineNameRenameClosed")); + Output.get().sendInfo(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_mines_name_chat_cancelled)); } else { Bukkit.getScheduler().runTask(SpigotPrison.getInstance(), () -> Bukkit.getServer().dispatchCommand(p, "mines rename " + tempChatVariable + " " + message)); } @@ -2854,7 +2830,7 @@ private void mineAction(AsyncPlayerChatEvent e, Player p, String message) { private void rankAction(AsyncPlayerChatEvent e, Player p, String message) { // Check the chat message and do the action if (message.equalsIgnoreCase("close")) { - Output.get().sendInfo(new SpigotPlayer(p), messages.getString("Message.rankTagRenameClosed")); + Output.get().sendInfo(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_ranks_tag_chat_cancelled)); } else { Bukkit.getScheduler().runTask(SpigotPrison.getInstance(), () -> Bukkit.getServer().dispatchCommand(p, "ranks set tag " + tempChatVariable + " " + message)); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/PrisonSetupGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/PrisonSetupGUI.java index 483a423f2..ed4227bd8 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/PrisonSetupGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/PrisonSetupGUI.java @@ -2,7 +2,7 @@ import com.cryptomorin.xseries.XMaterial; import org.bukkit.entity.Player; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -25,22 +25,22 @@ public void open(){ PrisonGUI gui = new PrisonGUI(p, 9, "&3Prison Setup -> Confirmation"); // Create lore. - ButtonLore lore = new ButtonLore(createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_confirm)), createLore( - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_ranks_setup_1), - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_ranks_setup_2), - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_ranks_setup_3), - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_ranks_setup_4), - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_ranks_setup_5), - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_ranks_setup_6), - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_ranks_setup_7), - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_ranks_setup_8))); + ButtonLore lore = new ButtonLore(createLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_confirm)), createLore( + messages.getString(MessagesConfig.StringID.spigot_gui_lore_ranks_setup_1), + messages.getString(MessagesConfig.StringID.spigot_gui_lore_ranks_setup_2), + messages.getString(MessagesConfig.StringID.spigot_gui_lore_ranks_setup_3), + messages.getString(MessagesConfig.StringID.spigot_gui_lore_ranks_setup_4), + messages.getString(MessagesConfig.StringID.spigot_gui_lore_ranks_setup_5), + messages.getString(MessagesConfig.StringID.spigot_gui_lore_ranks_setup_6), + messages.getString(MessagesConfig.StringID.spigot_gui_lore_ranks_setup_7), + messages.getString(MessagesConfig.StringID.spigot_gui_lore_ranks_setup_8))); // Add button. gui.addButton(new Button(2, XMaterial.EMERALD_BLOCK, lore, "&3Confirm: Setup")); // Add button. gui.addButton(new Button(6, XMaterial.REDSTONE_BLOCK, createLore( - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_cancel)), "&3Cancel: Setup")); + messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_cancel)), "&3Cancel: Setup")); // Open Prison GUI. gui.open(); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/SpigotPrisonGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/SpigotPrisonGUI.java index ff44db784..c9a7b3e35 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/SpigotPrisonGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/SpigotPrisonGUI.java @@ -3,7 +3,7 @@ import com.cryptomorin.xseries.XMaterial; import org.bukkit.entity.Player; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -27,12 +27,12 @@ public void open() { PrisonGUI gui = new PrisonGUI(p, dimension, "&3PrisonManager"); // Create and add buttons. - gui.addButton(new Button(10, XMaterial.TRIPWIRE_HOOK, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_ranks_button_description)), "&3Ranks - Ladders")); - gui.addButton(new Button(13, XMaterial.IRON_PICKAXE, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_autofeatures_button_description)), SpigotPrison.format("&3AutoManager"))); - gui.addButton(new Button(16, XMaterial.DIAMOND_ORE, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_mines_button_description)), SpigotPrison.format("&3Mines"))); - gui.addButton(new Button(29, XMaterial.CHEST, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_sellall_button_description)), SpigotPrison.format("&3SellAll"))); - gui.addButton(new Button(33, XMaterial.CHEST_MINECART, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_backpacks_button_description)), SpigotPrison.format("&3Backpacks"))); - gui.addButton(new Button(44, XMaterial.RED_STAINED_GLASS_PANE, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_close), null), SpigotPrison.format("&cClose"))); + gui.addButton(new Button(10, XMaterial.TRIPWIRE_HOOK, new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_open), messages.getString(MessagesConfig.StringID.spigot_gui_lore_ranks_button_description)), "&3Ranks - Ladders")); + gui.addButton(new Button(13, XMaterial.IRON_PICKAXE, new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_open), messages.getString(MessagesConfig.StringID.spigot_gui_lore_autofeatures_button_description)), SpigotPrison.format("&3AutoManager"))); + gui.addButton(new Button(16, XMaterial.DIAMOND_ORE, new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_open), messages.getString(MessagesConfig.StringID.spigot_gui_lore_mines_button_description)), SpigotPrison.format("&3Mines"))); + gui.addButton(new Button(29, XMaterial.CHEST, new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_open), messages.getString(MessagesConfig.StringID.spigot_gui_lore_sellall_button_description)), SpigotPrison.format("&3SellAll"))); + gui.addButton(new Button(33, XMaterial.CHEST_MINECART, new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_open), messages.getString(MessagesConfig.StringID.spigot_gui_lore_backpacks_button_description)), SpigotPrison.format("&3Backpacks"))); + gui.addButton(new Button(44, XMaterial.RED_STAINED_GLASS_PANE, new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_close), null), SpigotPrison.format("&cClose"))); gui.open(); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoBlockGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoBlockGUI.java index f74105fcb..68ebf3934 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoBlockGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoBlockGUI.java @@ -6,7 +6,7 @@ import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig; import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -30,9 +30,9 @@ public void open() { PrisonGUI gui = new PrisonGUI(p, 36, "&3AutoFeatures -> AutoBlock"); // Lores - ButtonLore enabledLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_and_shift_to_disable), null); - ButtonLore disabledLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_enable), null); - gui.addButton(new Button(35, XMaterial.RED_STAINED_GLASS_PANE, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_close), null), "&cClose")); + ButtonLore enabledLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_right_and_shift_to_disable), null); + ButtonLore disabledLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_right_to_enable), null); + gui.addButton(new Button(35, XMaterial.RED_STAINED_GLASS_PANE, new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_close), null), "&cClose")); if (afConfig != null) { diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoFeaturesGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoFeaturesGUI.java index 17d1bd20c..b7998b3e3 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoFeaturesGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoFeaturesGUI.java @@ -7,7 +7,7 @@ import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig; import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -31,12 +31,12 @@ public void open() { PrisonGUI gui; - ButtonLore closeGUILore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_close), null); + ButtonLore closeGUILore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_close), null); if (afConfig != null && afConfig.isFeatureBoolean(AutoFeatures.isAutoManagerEnabled)) { - ButtonLore disable = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_and_shift_to_disable), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_enabled)); - ButtonLore enable = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_enable), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_disabled)); + ButtonLore disable = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_right_and_shift_to_disable), messages.getString(MessagesConfig.StringID.spigot_gui_lore_enabled)); + ButtonLore enable = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_right_to_enable), messages.getString(MessagesConfig.StringID.spigot_gui_lore_disabled)); gui = new PrisonGUI(p, dimension, "&3PrisonManager -> AutoFeatures"); gui.addButton(new Button(dimension -1,XMaterial.RED_STAINED_GLASS_PANE, closeGUILore, SpigotPrison.format("&cClose"))); @@ -60,13 +60,13 @@ public void open() { } disable.setLoreAction(createLore( - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_left_to_open), - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_disable) + messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_left_to_open), + messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_right_to_disable) )); enable.setLoreAction(createLore( - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_left_to_open), - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_enable) + messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_left_to_open), + messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_right_to_enable) )); if (afConfig.isFeatureBoolean(AutoFeatures.autoPickupEnabled)) { @@ -93,7 +93,7 @@ public void open() { gui = new PrisonGUI(p, 9, "&3PrisonManager -> AutoFeatures"); - ButtonLore lore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_enable), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_disabled)); + ButtonLore lore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_right_to_enable), messages.getString(MessagesConfig.StringID.spigot_gui_lore_disabled)); Button enabledOrDisabled = new Button(2, XMaterial.LIME_STAINED_GLASS_PANE, lore, SpigotPrison.format("&cAll Disabled")); gui.addButton(enabledOrDisabled); gui.addButton(new Button(6,XMaterial.RED_STAINED_GLASS_PANE, closeGUILore, SpigotPrison.format("&cClose"))); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoPickupGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoPickupGUI.java index b1a668281..8f46a98eb 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoPickupGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoPickupGUI.java @@ -7,7 +7,7 @@ import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; @@ -31,9 +31,9 @@ public void open() { int dimension = 36; PrisonGUI gui = new PrisonGUI(p, dimension, "&3AutoFeatures -> AutoPickup"); - ButtonLore enabledLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_and_shift_to_disable), null); - ButtonLore disabledLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_enable), null); - ButtonLore closeGUILore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_close), null); + ButtonLore enabledLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_right_and_shift_to_disable), null); + ButtonLore disabledLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_right_to_enable), null); + ButtonLore closeGUILore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_close), null); gui.addButton(new Button(35, XMaterial.RED_STAINED_GLASS_PANE, closeGUILore, SpigotPrison.format("&cClose"))); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoSmeltGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoSmeltGUI.java index 059a4fa2d..5c9147ace 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoSmeltGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoSmeltGUI.java @@ -7,7 +7,7 @@ import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; @@ -31,9 +31,9 @@ public void open() { int dimension = 36; PrisonGUI gui = new PrisonGUI(p, dimension, "&3AutoFeatures -> AutoSmelt"); - ButtonLore enabledLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_and_shift_to_disable), null); - ButtonLore disabledLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_enable), null); - ButtonLore closeGUILore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_close), null); + ButtonLore enabledLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_right_and_shift_to_disable), null); + ButtonLore disabledLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_right_to_enable), null); + ButtonLore closeGUILore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_close), null); gui.addButton(new Button(35, XMaterial.RED_STAINED_GLASS_PANE, closeGUILore, SpigotPrison.format("&cClose"))); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksAdminGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksAdminGUI.java index 9ba2b3417..107aef8dd 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksAdminGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksAdminGUI.java @@ -4,7 +4,7 @@ import org.bukkit.entity.Player; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.backpacks.BackpacksUtil; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; @@ -25,7 +25,7 @@ public BackpacksAdminGUI(Player p) { public void open(){ if (!BackpacksUtil.isEnabled()){ - Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.BackPackIsDisabled")); + Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_gui_backpack_disabled)); p.closeInventory(); return; } @@ -33,11 +33,11 @@ public void open(){ int dimension = 27; PrisonGUI gui = new PrisonGUI(p, dimension, "&3Backpacks-Admin"); - ButtonLore lore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open), null); + ButtonLore lore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_open), null); gui.addButton(new Button(11, XMaterial.CHEST, lore, "&3Backpacks-List")); gui.addButton(new Button(15, XMaterial.PAPER, lore, "&3Backpack-Settings")); - gui.addButton(new Button(dimension -1, XMaterial.RED_STAINED_GLASS_PANE, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_close), null), "&cClose")); + gui.addButton(new Button(dimension -1, XMaterial.RED_STAINED_GLASS_PANE, new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_close), null), "&cClose")); gui.open(); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksAdminListGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksAdminListGUI.java index eee18f5d1..52671fa96 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksAdminListGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksAdminListGUI.java @@ -4,7 +4,7 @@ import org.bukkit.configuration.Configuration; import org.bukkit.entity.Player; import tech.mcprison.prison.spigot.backpacks.BackpacksUtil; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -20,10 +20,10 @@ public class BackpacksAdminListGUI extends SpigotGUIComponents { private final Player p; private final String playerBackpackName; private final Configuration backpacksData = BackpacksUtil.get().getBackpacksData(); - private final String loreShiftAndRightClickToDelete = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_and_shift_to_delete); - private final String loreInfo = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_info); - private final String lorePlayerOwner = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_owner); - private final String loreBackpackID = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_backpack_id); + private final String loreShiftAndRightClickToDelete = messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_right_and_shift_to_delete); + private final String loreInfo = messages.getString(MessagesConfig.StringID.spigot_gui_lore_info); + private final String lorePlayerOwner = messages.getString(MessagesConfig.StringID.spigot_gui_lore_owner); + private final String loreBackpackID = messages.getString(MessagesConfig.StringID.spigot_gui_lore_backpack_id); public BackpacksAdminListGUI(Player p, String playerBackpackName){ this.p = p; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksAdminPlayerListGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksAdminPlayerListGUI.java index 09e7fc459..d536adef9 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksAdminPlayerListGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksAdminPlayerListGUI.java @@ -5,7 +5,7 @@ import org.bukkit.entity.Player; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.backpacks.BackpacksUtil; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; @@ -21,7 +21,7 @@ public class BackpacksAdminPlayerListGUI extends SpigotGUIComponents { private final Player p; private final Configuration backpacksData = BackpacksUtil.get().getBackpacksData(); - private final String clickToOpen = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open); + private final String clickToOpen = messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_open); public BackpacksAdminPlayerListGUI(Player p){ this.p = p; @@ -33,7 +33,7 @@ public void open(){ PrisonGUI gui = new PrisonGUI(p, dimension, "&3Backpacks-Admin-Players"); if (backpacksData.getConfigurationSection("Inventories") == null){ - Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.BackPackListEmpty")); + Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_gui_backpack_empty)); return; } @@ -41,7 +41,7 @@ public void open(){ try { playerUUID = backpacksData.getConfigurationSection("Inventories").getKeys(false); } catch (NullPointerException ex){ - Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.BackPackListEmpty")); + Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_gui_backpack_empty)); return; } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksListPlayerGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksListPlayerGUI.java index 11037a97a..01a894136 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksListPlayerGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksListPlayerGUI.java @@ -5,7 +5,7 @@ import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.backpacks.BackpacksUtil; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; @@ -26,20 +26,20 @@ public BackpacksListPlayerGUI(Player p) { public void open(){ if (BackpacksUtil.get().getBackpacksLimit(p) == 0){ - Output.get().sendInfo(new SpigotPlayer(p), messages.getString("Message.BackPackCantOwn")); + Output.get().sendInfo(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_backpack_cant_own)); return; } int dimension = 54; PrisonGUI gui = new PrisonGUI(p, dimension, "&3" + p.getName() + " -> Backpacks"); - ButtonLore loreAddBackpackButton = new ButtonLore(createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_add_backpack)), createLore( - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_add_backpack_instruction_1), - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_add_backpack_instruction_2), - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_add_backpack_instruction_3))); + ButtonLore loreAddBackpackButton = new ButtonLore(createLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_add_backpack)), createLore( + messages.getString(MessagesConfig.StringID.spigot_gui_lore_add_backpack_instruction_1), + messages.getString(MessagesConfig.StringID.spigot_gui_lore_add_backpack_instruction_2), + messages.getString(MessagesConfig.StringID.spigot_gui_lore_add_backpack_instruction_3))); // Global Strings. - String loreClickToOpen = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open); + String loreClickToOpen = messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_open); if (!BackpacksUtil.get().getBackpacksIDs(p).isEmpty()) { int slot = 0; @@ -64,7 +64,7 @@ public void open(){ gui.addButton(new Button(49, XMaterial.EMERALD_BLOCK, loreAddBackpackButton, "&aNew Backpack")); } - gui.addButton(new Button(dimension-1, XMaterial.RED_STAINED_GLASS_PANE, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_close), null), "&cClose")); + gui.addButton(new Button(dimension-1, XMaterial.RED_STAINED_GLASS_PANE, new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_close), null), "&cClose")); gui.open(); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/guiutility/SpigotGUIComponents.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/guiutility/SpigotGUIComponents.java index 3d3b30bfb..3e6cb0480 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/guiutility/SpigotGUIComponents.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/guiutility/SpigotGUIComponents.java @@ -20,7 +20,7 @@ import tech.mcprison.prison.output.Output; import tech.mcprison.prison.ranks.PrisonRanks; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.ListenersPrisonManager; import tech.mcprison.prison.spigot.sellall.SellAllUtil; @@ -31,8 +31,7 @@ */ public abstract class SpigotGUIComponents { - public static NewMessagesConfig newMessages = getNewMessages(); - public static Configuration messages = getMessages(); + public static MessagesConfig messages = getMessages(); public static Configuration guiConfig = getGuiConfig(); public static Configuration sellAllConfig = getSellAll(); @@ -130,14 +129,14 @@ protected boolean checkRanks(Player p){ /** * Get new Messages config. * */ - protected static NewMessagesConfig getNewMessages(){ - return SpigotPrison.getInstance().getNewMessagesConfig(); + protected static MessagesConfig getmessages(){ + return SpigotPrison.getInstance().getMessagesConfig(); } /** * Get Messages config. * */ - protected static Configuration getMessages(){ + protected static MessagesConfig getMessages(){ return SpigotPrison.getInstance().getMessagesConfig(); } @@ -171,20 +170,12 @@ public static AutoFeaturesFileConfig afConfig() { return AutoFeaturesWrapper.getInstance().getAutoFeaturesConfig(); } - /** - * Reload new Messages config for GUIs. - * */ - public static void updateNewMessages(){ - NewMessagesConfig.get().reload(); - newMessages = NewMessagesConfig.get(); - } - /** * Reload messages config for GUIs. * */ public static void updateMessages(){ - File file = new File(SpigotPrison.getInstance().getDataFolder() + "/module_conf/lang/" + SpigotPrison.getInstance().getConfig().getString("default-language") + ".yml"); - messages = YamlConfiguration.loadConfiguration(file); + MessagesConfig.get().reload(); + messages = MessagesConfig.get(); } /** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotBlocksListGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotBlocksListGUI.java index 448c75b38..e9e49b0cd 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotBlocksListGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotBlocksListGUI.java @@ -10,7 +10,7 @@ import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.internal.block.PrisonBlockTypes; import tech.mcprison.prison.spigot.SpigotUtil; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -40,7 +40,7 @@ public void open(){ // Create the inventory PrisonGUI gui = new PrisonGUI(p, dimension, "&3Mines -> BlocksList"); - ButtonLore lore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_start_block_setup), null); + ButtonLore lore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_start_block_setup), null); // This will skip all BlockTypes that are invalid for the versions of MC that the server is running: PrisonBlockTypes prisonBlockTypes = Prison.get().getPlatform().getPrisonBlockTypes(); @@ -64,10 +64,10 @@ public void open(){ prisonBlock.getBlockName().toUpperCase() + " &0" + mineName + " " + counter)); } if ( i < blockTypes.size() ) { - gui.addButton(new Button(53, XMaterial.BOOK, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_next_page), null), "&7Next &0" + mineName + " " + (i + 1))); + gui.addButton(new Button(53, XMaterial.BOOK, new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_next_page), null), "&7Next &0" + mineName + " " + (i + 1))); } if ( i >= (pageSize * 2) ) { - gui.addButton(new Button(51, XMaterial.BOOK, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_prior_page), null), "&7Prior &0" + mineName + " " + (i - (pageSize * 2) - 1))); + gui.addButton(new Button(51, XMaterial.BOOK, new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_prior_page), null), "&7Prior &0" + mineName + " " + (i - (pageSize * 2) - 1))); } // Open the inventory diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotBlocksMineListGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotBlocksMineListGUI.java index 7709696c7..32abe6b10 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotBlocksMineListGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotBlocksMineListGUI.java @@ -6,7 +6,7 @@ import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.internal.block.PrisonBlockTypes; import tech.mcprison.prison.spigot.SpigotUtil; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -38,7 +38,7 @@ public void open(){ // Create the inventory PrisonGUI gui = new PrisonGUI(p, dimension, "&3Select -> ShowBlock"); - ButtonLore lore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_select), null); + ButtonLore lore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_select), null); // This will skip all BlockTypes that are invalid for the versions of MC that the server is running: PrisonBlockTypes prisonBlockTypes = Prison.get().getPlatform().getPrisonBlockTypes(); @@ -62,10 +62,10 @@ public void open(){ prisonBlock.getBlockName().toUpperCase() + " " + mineName + " " + counter)); } if ( i < blockTypes.size() ) { - gui.addButton(new Button(53, XMaterial.BOOK, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_next_page), null), "&7Next " + mineName + " " + (i + 1))); + gui.addButton(new Button(53, XMaterial.BOOK, new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_next_page), null), "&7Next " + mineName + " " + (i + 1))); } if ( i >= (pageSize * 2) ) { - gui.addButton(new Button(51, XMaterial.BOOK, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_prior_page), null), "&7Prior " + mineName + " " + (i - (pageSize * 2) - 1))); + gui.addButton(new Button(51, XMaterial.BOOK, new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_prior_page), null), "&7Prior " + mineName + " " + (i - (pageSize * 2) - 1))); } // Open the inventory diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineBlockPercentageGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineBlockPercentageGUI.java index 16a16350d..4a3395b3c 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineBlockPercentageGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineBlockPercentageGUI.java @@ -6,14 +6,12 @@ import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.spigot.SpigotUtil; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; import tech.mcprison.prison.spigot.gui.guiutility.SpigotGUIComponents; -import java.util.List; - /** * @author GABRYCA (AnonymousGCA) */ @@ -37,9 +35,9 @@ public void open() { int dimension = 45; PrisonGUI gui = new PrisonGUI(p, dimension, "&3MineInfo -> BlockPercentage"); - ButtonLore changeDecreaseValueLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_decrease), null); - ButtonLore confirmButtonLore = new ButtonLore(createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_confirm), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_cancel)), createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_percentage) + " " + val)); - ButtonLore changeIncreaseValueLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_decrease), null); + ButtonLore changeDecreaseValueLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_decrease), null); + ButtonLore confirmButtonLore = new ButtonLore(createLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_confirm), messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_right_to_cancel)), createLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_percentage) + " " + val)); + ButtonLore changeIncreaseValueLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_decrease), null); XMaterial decreaseMaterial = XMaterial.REDSTONE_BLOCK; @@ -62,7 +60,7 @@ public void open() { gui.addButton(new Button(43, increaseMat, changeIncreaseValueLore, "&3" + mineName + " " + blockName + " " + val + " + 100 &0" + counter)); // Close gui: - gui.addButton(new Button(40, XMaterial.RED_STAINED_GLASS_PANE, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_close), null), "&cClose &0" + mineName + " " + counter)); + gui.addButton(new Button(40, XMaterial.RED_STAINED_GLASS_PANE, new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_close), null), "&cClose &0" + mineName + " " + counter)); // Show the selected block at the top center position: XMaterial xMat = SpigotUtil.getXMaterial( blockName ); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineInfoGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineInfoGUI.java index c13203450..37a3aaf7c 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineInfoGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineInfoGUI.java @@ -1,14 +1,12 @@ package tech.mcprison.prison.spigot.gui.mine; -import java.util.List; - import com.cryptomorin.xseries.XMaterial; import org.bukkit.entity.Player; import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.SpigotUtil; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -35,25 +33,25 @@ public void open(){ PrisonGUI gui = new PrisonGUI(p, dimension, SpigotPrison.format("&3Mines -> MineInfo")); ButtonLore resetMineLore = new ButtonLore(createLore( - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_left_to_reset), - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_toggle), - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_and_shift_to_toggle)), - createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_skip_reset_instruction_1), - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_skip_reset_instruction_2), - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_skip_reset_instruction_3), + messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_left_to_reset), + messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_right_to_toggle), + messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_right_and_shift_to_toggle)), + createLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_skip_reset_instruction_1), + messages.getString(MessagesConfig.StringID.spigot_gui_lore_skip_reset_instruction_2), + messages.getString(MessagesConfig.StringID.spigot_gui_lore_skip_reset_instruction_3), "", - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_set_mine_delay_instruction_1), - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_set_mine_delay_instruction_2), - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_set_mine_delay_instruction_3))); + messages.getString(MessagesConfig.StringID.spigot_gui_lore_set_mine_delay_instruction_1), + messages.getString(MessagesConfig.StringID.spigot_gui_lore_set_mine_delay_instruction_2), + messages.getString(MessagesConfig.StringID.spigot_gui_lore_set_mine_delay_instruction_3))); - ButtonLore mineSpawnLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_use), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_spawnpoint)); - ButtonLore minesNotificationsLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_edit)); - ButtonLore minesTpLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_teleport), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_tp_to_mine)); - ButtonLore blocksOfTheMineLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_blocks)); - ButtonLore mineResetTimeLore = new ButtonLore(createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open)), createLore( - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_reset_time) + " &7" + mine.getResetTime())); - ButtonLore mineRenameLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_rename), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_minename) + " " + mineName); - ButtonLore closeGUILore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_close), null); + ButtonLore mineSpawnLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_use), messages.getString(MessagesConfig.StringID.spigot_gui_lore_spawnpoint)); + ButtonLore minesNotificationsLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_open), messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_edit)); + ButtonLore minesTpLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_teleport), messages.getString(MessagesConfig.StringID.spigot_gui_lore_tp_to_mine)); + ButtonLore blocksOfTheMineLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_open), messages.getString(MessagesConfig.StringID.spigot_gui_lore_blocks)); + ButtonLore mineResetTimeLore = new ButtonLore(createLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_open)), createLore( + messages.getString(MessagesConfig.StringID.spigot_gui_lore_reset_time) + " &7" + mine.getResetTime())); + ButtonLore mineRenameLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_rename), messages.getString(MessagesConfig.StringID.spigot_gui_lore_minename) + " " + mineName); + ButtonLore closeGUILore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_close), null); // Create the button, set the material, amount, lore and name gui.addButton(new Button(dimension-1, XMaterial.RED_STAINED_GLASS_PANE, closeGUILore, SpigotPrison.format("&cClose"))); @@ -76,11 +74,11 @@ public void open(){ } // Lore - ButtonLore mineShowItemLore = new ButtonLore(createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_edit)), createLore( - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_show_item) + " &7" + xMaterial.name(), - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_show_item_description_1), - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_show_item_description_2), - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_show_item_description_3) + ButtonLore mineShowItemLore = new ButtonLore(createLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_edit)), createLore( + messages.getString(MessagesConfig.StringID.spigot_gui_lore_show_item) + " &7" + xMaterial.name(), + messages.getString(MessagesConfig.StringID.spigot_gui_lore_show_item_description_1), + messages.getString(MessagesConfig.StringID.spigot_gui_lore_show_item_description_2), + messages.getString(MessagesConfig.StringID.spigot_gui_lore_show_item_description_3) )); // ItemStack diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineNotificationRadiusGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineNotificationRadiusGUI.java index 88dc77b01..8cc8453dc 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineNotificationRadiusGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineNotificationRadiusGUI.java @@ -2,7 +2,7 @@ import com.cryptomorin.xseries.XMaterial; import org.bukkit.entity.Player; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -31,11 +31,11 @@ public void open() { int dimension = 45; PrisonGUI gui = new PrisonGUI(p, dimension, "&3MineNotifications -> Radius"); - ButtonLore changeDecreaseValueLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_decrease), null); - ButtonLore confirmButtonLore = new ButtonLore(createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_left_to_confirm)), createLore( - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_radius) + " " + val, - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_cancel))); - ButtonLore changeIncreaseValueLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_increase), null); + ButtonLore changeDecreaseValueLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_decrease), null); + ButtonLore confirmButtonLore = new ButtonLore(createLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_left_to_confirm)), createLore( + messages.getString(MessagesConfig.StringID.spigot_gui_lore_radius) + " " + val, + messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_right_to_cancel))); + ButtonLore changeIncreaseValueLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_increase), null); // XMaterials. XMaterial decreaseMat = XMaterial.REDSTONE_BLOCK; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineNotificationsGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineNotificationsGUI.java index f5afba8d9..5c626ed13 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineNotificationsGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineNotificationsGUI.java @@ -6,7 +6,7 @@ import tech.mcprison.prison.mines.PrisonMines; import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -36,10 +36,10 @@ public void open() { Mine m = pMines.getMine(mineName); String enabledOrDisabled = m.getNotificationMode().name(); - ButtonLore modeWithinLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_select), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_enable_within_mode)); - ButtonLore modeRadiusLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_select), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_enable_radius_mode)); - ButtonLore disabledModeLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_select), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_disable_notifications)); - ButtonLore closeGUILore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_close), null); + ButtonLore modeWithinLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_select), messages.getString(MessagesConfig.StringID.spigot_gui_lore_enable_within_mode)); + ButtonLore modeRadiusLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_select), messages.getString(MessagesConfig.StringID.spigot_gui_lore_enable_radius_mode)); + ButtonLore disabledModeLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_select), messages.getString(MessagesConfig.StringID.spigot_gui_lore_disable_notifications)); + ButtonLore closeGUILore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_close), null); // Add button. gui.addButton(new Button(26, XMaterial.RED_STAINED_GLASS_PANE, closeGUILore, "&cClose")); @@ -48,17 +48,17 @@ public void open() { if (enabledOrDisabled.equalsIgnoreCase("disabled")){ // Add the selected lore - disabledModeLore.addLineLoreDescription(SpigotPrison.format(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_selected))); + disabledModeLore.addLineLoreDescription(SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_gui_lore_selected))); } else if (enabledOrDisabled.equalsIgnoreCase("within")){ // Add the selected lore - modeWithinLore.addLineLoreDescription(SpigotPrison.format(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_selected))); + modeWithinLore.addLineLoreDescription(SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_gui_lore_selected))); } else if (enabledOrDisabled.equalsIgnoreCase("radius")){ // Add the selected lore - modeRadiusLore.addLineLoreDescription(SpigotPrison.format(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_selected))); + modeRadiusLore.addLineLoreDescription(SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_gui_lore_selected))); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineResetTimeGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineResetTimeGUI.java index 3f43c71f8..eb82c9cf9 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineResetTimeGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMineResetTimeGUI.java @@ -2,7 +2,7 @@ import com.cryptomorin.xseries.XMaterial; import org.bukkit.entity.Player; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -30,9 +30,9 @@ public void open() { PrisonGUI gui = new PrisonGUI(p, dimension, "&3MineInfo -> ResetTime"); - ButtonLore changeDecreaseValueLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_decrease), null); - ButtonLore confirmButtonLore = new ButtonLore(createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_left_to_confirm), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_cancel)), createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_reset_time) + " " + val)); - ButtonLore changeIncreaseValueLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_increase), null); + ButtonLore changeDecreaseValueLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_decrease), null); + ButtonLore confirmButtonLore = new ButtonLore(createLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_left_to_confirm), messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_right_to_cancel)), createLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_reset_time) + " " + val)); + ButtonLore changeIncreaseValueLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_increase), null); // XMaterials. XMaterial decreaseMat = XMaterial.REDSTONE_BLOCK; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesBlocksGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesBlocksGUI.java index 492bdeb6c..b5443b669 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesBlocksGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesBlocksGUI.java @@ -9,7 +9,7 @@ import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.SpigotUtil; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -25,11 +25,11 @@ public class SpigotMinesBlocksGUI extends SpigotGUIComponents { private final String mineName; // Global Strings. - private final String loreShiftRightClickToDelete = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_and_shift_to_delete); - private final String loreClickToEditBlock = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_edit); - private final String loreInfo = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_info); - private final String loreChance = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_chance); - private final String loreBlockType = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_blocktype); + private final String loreShiftRightClickToDelete = messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_right_and_shift_to_delete); + private final String loreClickToEditBlock = messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_edit); + private final String loreInfo = messages.getString(MessagesConfig.StringID.spigot_gui_lore_info); + private final String loreChance = messages.getString(MessagesConfig.StringID.spigot_gui_lore_chance); + private final String loreBlockType = messages.getString(MessagesConfig.StringID.spigot_gui_lore_blocktype); public SpigotMinesBlocksGUI(Player p, String mineName){ this.p = p; @@ -45,7 +45,7 @@ public void open(){ Mine m = PrisonMines.getInstance().getMine(mineName); boolean useNewBlockModel = Prison.get().getPlatform().isUseNewPrisonBlockModel(); - ButtonLore addBlockLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_add), null); + ButtonLore addBlockLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_add), null); // Add the button to the GUI. gui.addButton(new Button(dimension - 1, XMaterial.LIME_STAINED_GLASS_PANE, addBlockLore, "&aAdd " + mineName)); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesConfirmGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesConfirmGUI.java index 1d95b3ebc..0b4355ae4 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesConfirmGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesConfirmGUI.java @@ -2,7 +2,7 @@ import com.cryptomorin.xseries.XMaterial; import org.bukkit.entity.Player; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -27,8 +27,8 @@ public void open(){ int dimension = 9; PrisonGUI gui = new PrisonGUI(p, dimension, "&3Mines -> Delete"); - ButtonLore confirmLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_confirm), null); - ButtonLore cancelLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_cancel), null); + ButtonLore confirmLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_confirm), null); + ButtonLore cancelLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_cancel), null); // Position of the button diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesGUI.java index aab8b94cf..fdf07c89b 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotMinesGUI.java @@ -9,7 +9,7 @@ import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.mines.data.PrisonSortableResults; import tech.mcprison.prison.mines.managers.MineManager.MineSortOrder; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.gui.PrisonSetupGUI; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; @@ -54,15 +54,15 @@ public void open(){ PrisonGUI gui = new PrisonGUI(p, dimension, "&3MinesManager -> Mines"); // Global Strings. - String loreLeftClickOpen = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_left_to_open); - String loreShiftRightClickToDelete = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_and_shift_to_delete); - String loreInfo = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_info); - String loreWorld = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_world); - String loreSpawnPoint = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_spawnpoint); - String loreResetTime = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_reset_time); - String loreSizeOfMine = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_size); - String loreVolume = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_volume); - String loreBlocks = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_blocks); + String loreLeftClickOpen = messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_left_to_open); + String loreShiftRightClickToDelete = messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_right_and_shift_to_delete); + String loreInfo = messages.getString(MessagesConfig.StringID.spigot_gui_lore_info); + String loreWorld = messages.getString(MessagesConfig.StringID.spigot_gui_lore_world); + String loreSpawnPoint = messages.getString(MessagesConfig.StringID.spigot_gui_lore_spawnpoint); + String loreResetTime = messages.getString(MessagesConfig.StringID.spigot_gui_lore_reset_time); + String loreSizeOfMine = messages.getString(MessagesConfig.StringID.spigot_gui_lore_size); + String loreVolume = messages.getString(MessagesConfig.StringID.spigot_gui_lore_volume); + String loreBlocks = messages.getString(MessagesConfig.StringID.spigot_gui_lore_blocks); // Global boolean. boolean useNewBlockModel = Prison.get().getPlatform().isUseNewPrisonBlockModel(); @@ -126,10 +126,10 @@ public void open(){ } if (i < mines.getSortedList().size()) { - gui.addButton(new Button(53, XMaterial.BOOK, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_next_page), null), "&7Next " + (i + 1))); + gui.addButton(new Button(53, XMaterial.BOOK, new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_next_page), null), "&7Next " + (i + 1))); } if (i >= (pageSize * 2)) { - gui.addButton(new Button(51, XMaterial.BOOK, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_prior_page), null), "&7Prior " + (i - (pageSize * 2) - 1))); + gui.addButton(new Button(51, XMaterial.BOOK, new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_prior_page), null), "&7Prior " + (i - (pageSize * 2) - 1))); } // Open the GUI. diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotPlayerMinesGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotPlayerMinesGUI.java index 97531b68b..9c12936d8 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotPlayerMinesGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/mine/SpigotPlayerMinesGUI.java @@ -13,7 +13,7 @@ import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.SpigotUtil; import tech.mcprison.prison.spigot.configs.GuiConfig; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; @@ -29,9 +29,9 @@ public class SpigotPlayerMinesGUI extends SpigotGUIComponents { private final Player p; private final SpigotPlayer spigotPlayer; private final String permissionWarpPlugin = guiConfig.getString("Options.Mines.PermissionWarpPlugin"); - private final String statusUnlockedMine = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_unlocked); - private final String clickToTeleport = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_teleport); - private final String statusLockedMine = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_locked); + private final String statusUnlockedMine = messages.getString(MessagesConfig.StringID.spigot_gui_lore_unlocked); + private final String clickToTeleport = messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_teleport); + private final String statusLockedMine = messages.getString(MessagesConfig.StringID.spigot_gui_lore_locked); public SpigotPlayerMinesGUI(Player p) { this.p = p; @@ -49,14 +49,14 @@ public void open(){ // If the inventory is empty if (dimension == 0){ - Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.NoMines")); + Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_gui_mines_empty)); p.closeInventory(); return; } // If the dimension's too big, don't open the GUI if (dimension > 54){ - Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.TooManyMines")); + Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_gui_mines_too_many)); p.closeInventory(); return; } @@ -107,7 +107,7 @@ public void open(){ p.hasPermission(permission.substring(0, permission.length() - 1))){ material = ( mineMaterial == null ? Material.COAL_ORE : mineMaterial); minesLore.addLineLoreDescription(SpigotPrison.format(statusUnlockedMine)); - minesLore.addLineLoreDescription(SpigotPrison.format(clickToTeleport)); + minesLore.addLineLoreAction(SpigotPrison.format(clickToTeleport)); } else { material = XMaterial.REDSTONE_BLOCK.parseMaterial(); minesLore.addLineLoreDescription(SpigotPrison.format(statusLockedMine)); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotConfirmPrestigeGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotConfirmPrestigeGUI.java index c6df32492..3e95cce1e 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotConfirmPrestigeGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotConfirmPrestigeGUI.java @@ -3,7 +3,7 @@ import com.cryptomorin.xseries.XMaterial; import org.bukkit.entity.Player; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -26,12 +26,12 @@ public void open(){ int dimension = 9; PrisonGUI gui = new PrisonGUI(p, dimension, "&3Prestige -> Confirmation"); - ButtonLore confirmLore = new ButtonLore(createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_confirm)), createLore( - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_prestige_warning_1), - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_prestige_warning_2), - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_prestige_warning_3))); + ButtonLore confirmLore = new ButtonLore(createLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_confirm)), createLore( + messages.getString(MessagesConfig.StringID.spigot_gui_lore_prestige_warning_1), + messages.getString(MessagesConfig.StringID.spigot_gui_lore_prestige_warning_2), + messages.getString(MessagesConfig.StringID.spigot_gui_lore_prestige_warning_3))); - ButtonLore cancelLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_cancel), null); + ButtonLore cancelLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_cancel), null); // Create the button, set up the material, amount, lore and name diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotLaddersGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotLaddersGUI.java index 49015eecf..68f05b4b8 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotLaddersGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotLaddersGUI.java @@ -7,7 +7,7 @@ import tech.mcprison.prison.ranks.data.RankLadder; import tech.mcprison.prison.ranks.managers.LadderManager; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; @@ -39,7 +39,7 @@ public void open(){ // If the inventory is empty if (lm.getLadders().size() == 0){ - Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.NoLadders")); + Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_gui_ladder_empty)); p.closeInventory(); return; } @@ -50,7 +50,7 @@ public void open(){ PrisonGUI gui = new PrisonGUI(p, dimension, "&3RanksManager -> Ladders"); - ButtonLore laddersLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_and_shift_to_delete)); + ButtonLore laddersLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_open), messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_right_and_shift_to_delete)); // Only loop over the blocks that we need to show: int i = counter; @@ -63,10 +63,10 @@ public void open(){ } if (i < lm.getLadders().size()) { - gui.addButton(new Button(53, XMaterial.BOOK, 1, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_next_page), null), "&7Next " + (i + 1))); + gui.addButton(new Button(53, XMaterial.BOOK, 1, new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_next_page), null), "&7Next " + (i + 1))); } if (i >= (pageSize * 2)) { - gui.addButton(new Button(51, XMaterial.BOOK, 1, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_prior_page), null), + gui.addButton(new Button(51, XMaterial.BOOK, 1, new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_prior_page), null), "&7Prior " + (i - (pageSize * 2) - 1))); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerPrestigesGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerPrestigesGUI.java index 281094c69..de6ad766c 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerPrestigesGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerPrestigesGUI.java @@ -21,7 +21,7 @@ import tech.mcprison.prison.ranks.managers.LadderManager; import tech.mcprison.prison.ranks.managers.PlayerManager; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; @@ -127,7 +127,7 @@ public void open() { // } if (!ladder.getLowestRank().isPresent()){ - Output.get().sendWarn(new SpigotPlayer(player), messages.getString("Message.NoRanksPrestigesLadder")); + Output.get().sendWarn(new SpigotPlayer(player), messages.getString(MessagesConfig.StringID.spigot_message_prestiges_empty)); return; } @@ -146,8 +146,8 @@ public void open() { int hackyCounterEnchant = 0; // Global strings. - String loreInfo = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_info); - String lorePrice3 = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_price); + String loreInfo = messages.getString(MessagesConfig.StringID.spigot_gui_lore_info); + String lorePrice3 = messages.getString(MessagesConfig.StringID.spigot_gui_lore_price); // Global boolean. boolean enchantmentEffectEnabled = getBoolean(guiConfig.getString("Options.Ranks.Enchantment_effect_current_rank")); @@ -186,7 +186,7 @@ public void open() { rank = rank.getRankNext(); } - ButtonLore rankupLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_rankup), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_rankup_if_enough_money)); + ButtonLore rankupLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_rankup), messages.getString(MessagesConfig.StringID.spigot_gui_lore_rankup_if_enough_money)); // Add button to GUI. gui.addButton(new Button(dimension - 5, XMaterial.EMERALD_BLOCK, rankupLore, SpigotPrison.format("&aPrestige"))); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerRanksGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerRanksGUI.java index c8145878f..4b7b320fa 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerRanksGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerRanksGUI.java @@ -25,7 +25,7 @@ import tech.mcprison.prison.ranks.managers.LadderManager; import tech.mcprison.prison.ranks.managers.PlayerManager; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; @@ -110,14 +110,14 @@ public void open() { // Ensure ladder is present and that it has a rank: if ( ladder == null || !ladder.getLowestRank().isPresent()){ - Output.get().sendWarn(new SpigotPlayer(getPlayer()), messages.getString("Message.NoRanksFoundHelp1") + guiConfig.getString("Options.Ranks.Ladder") + messages.getString("Message.NoRanksFoundHelp2")); + Output.get().sendWarn(new SpigotPlayer(getPlayer()), messages.getString(MessagesConfig.StringID.spigot_message_gui_ladder_empty) + " [" + guiConfig.getString("Options.Ranks.Ladder") + "]"); getPlayer().closeInventory(); return; } // Get the dimensions and if needed increases them if (ladder.getRanks().size() == 0) { - Output.get().sendWarn(new SpigotPlayer(getPlayer()), messages.getString("Message.NoRanksFound")); + Output.get().sendWarn(new SpigotPlayer(getPlayer()), messages.getString(MessagesConfig.StringID.spigot_message_gui_ranks_empty)); return; } @@ -184,10 +184,10 @@ public void open() { rank = rank.getRankNext(); } - ButtonLore rankupLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_rankup), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_rankup_if_enough_money)); + ButtonLore rankupLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_rankup), messages.getString(MessagesConfig.StringID.spigot_gui_lore_rankup_if_enough_money)); // Add button. - gui.addButton(new Button(dimension - 5, XMaterial.EMERALD_BLOCK, rankupLore, SpigotPrison.format(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_rankup)))); + gui.addButton(new Button(dimension - 5, XMaterial.EMERALD_BLOCK, rankupLore, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_gui_lore_rankup)))); // Open GUI. gui.open(); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankManagerGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankManagerGUI.java index e9a4f612c..c8a1a034d 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankManagerGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankManagerGUI.java @@ -12,7 +12,7 @@ import tech.mcprison.prison.ranks.data.Rank; import tech.mcprison.prison.ranks.data.RankPlayer; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; @@ -42,7 +42,7 @@ public void open() { int dimension = 27; PrisonGUI gui = new PrisonGUI(p, dimension, "&3Ranks -> RankManager"); - ButtonLore rankupCommandsLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open), null); + ButtonLore rankupCommandsLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_open), null); // Decimal Rank cost format. DecimalFormat formatDecimal = new DecimalFormat("###,##0.00"); @@ -58,16 +58,16 @@ public void open() { rankCost = "Can't get"; } - ButtonLore editPriceLore = new ButtonLore(createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open)), createLore( - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_info), - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_price) + " " + rankCost)); + ButtonLore editPriceLore = new ButtonLore(createLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_open)), createLore( + messages.getString(MessagesConfig.StringID.spigot_gui_lore_info), + messages.getString(MessagesConfig.StringID.spigot_gui_lore_price) + " " + rankCost)); - ButtonLore editTagLore = new ButtonLore(createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open)), createLore( - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_info), - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_rank_tag) + " " + rank.getTag())); + ButtonLore editTagLore = new ButtonLore(createLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_open)), createLore( + messages.getString(MessagesConfig.StringID.spigot_gui_lore_info), + messages.getString(MessagesConfig.StringID.spigot_gui_lore_rank_tag) + " " + rank.getTag())); - ButtonLore closeGUILore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_close), null); + ButtonLore closeGUILore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_close), null); // Create the button gui.addButton(new Button(26, XMaterial.RED_STAINED_GLASS_PANE, closeGUILore, SpigotPrison.format("&cClose"))); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankPriceGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankPriceGUI.java index 9af9b042e..cd79f8a7c 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankPriceGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankPriceGUI.java @@ -3,7 +3,7 @@ import com.cryptomorin.xseries.XMaterial; import org.bukkit.entity.Player; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -34,9 +34,9 @@ public void open() { int dimension = 45; PrisonGUI gui = new PrisonGUI(p, dimension, "&3RankManager -> RankPrice"); - ButtonLore changeDecreaseValueLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_decrease), null); - ButtonLore confirmButtonLore = new ButtonLore(createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_left_to_confirm), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_cancel)), createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_price) + " " + val)); - ButtonLore changeIncreaseValueLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_increase), null); + ButtonLore changeDecreaseValueLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_decrease), null); + ButtonLore confirmButtonLore = new ButtonLore(createLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_left_to_confirm), messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_right_to_cancel)), createLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_price) + " " + val)); + ButtonLore changeIncreaseValueLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_increase), null); XMaterial decreaseMat = XMaterial.REDSTONE_BLOCK; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankUPCommandsGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankUPCommandsGUI.java index e5dc8cf02..876d66491 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankUPCommandsGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankUPCommandsGUI.java @@ -6,7 +6,7 @@ import tech.mcprison.prison.output.Output; import tech.mcprison.prison.ranks.data.Rank; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; @@ -22,9 +22,9 @@ public class SpigotRankUPCommandsGUI extends SpigotGUIComponents { private final Rank rank; // Global Strings. - private final String shiftRightClickToDelete = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_and_shift_to_delete); - private final String loreInfo = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_info); - private final String loreCommand = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_command); + private final String shiftRightClickToDelete = messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_right_and_shift_to_delete); + private final String loreInfo = messages.getString(MessagesConfig.StringID.spigot_gui_lore_info); + private final String loreCommand = messages.getString(MessagesConfig.StringID.spigot_gui_lore_command); public SpigotRankUPCommandsGUI(Player p, Rank rank) { this.p = p; @@ -39,7 +39,7 @@ public void open() { } if (rank.getRankUpCommands().size() == 0){ - Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.NoRankupCommands")); + Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_gui_ranks_rankup_commands_empty)); return; } @@ -48,14 +48,14 @@ public void open() { // If the inventory is empty if (dimension == 0){ - Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.EmptyGui")); + Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_gui_error_empty)); p.closeInventory(); return; } // If the dimension's too big, don't open the GUI if (dimension > 54){ - Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.TooManyRankupCommands")); + Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_gui_ranks_rankup_commands_too_many)); p.closeInventory(); return; } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRanksGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRanksGUI.java index 9e647048d..d9fff77be 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRanksGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRanksGUI.java @@ -14,7 +14,7 @@ import tech.mcprison.prison.ranks.data.Rank; import tech.mcprison.prison.ranks.data.RankLadder; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; @@ -45,7 +45,7 @@ public void open(){ // Get the dimensions and if needed increases them if (!ladder.isPresent() || ladder.get().getRanks().size() == 0) { - Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.NoRanksFoundAdmin")); + Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_gui_ranks_empty)); return; } @@ -56,14 +56,14 @@ public void open(){ PrisonGUI gui = new PrisonGUI(p, dimension, "&3Ladders -> Ranks"); // Global Strings. - String loreShiftRightClickDelete = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_and_shift_to_delete); - String loreClickToManageRank = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_manage_rank); - String loreInfo = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_info); - String loreId = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_id); - String loreName = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_name); - String loreTag2 = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_rank_tag); - String lorePrice3 = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_price); - String lorePlayersWithRank = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_players_at_rank); + String loreShiftRightClickDelete = messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_right_and_shift_to_delete); + String loreClickToManageRank = messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_manage_rank); + String loreInfo = messages.getString(MessagesConfig.StringID.spigot_gui_lore_info); + String loreId = messages.getString(MessagesConfig.StringID.spigot_gui_lore_id); + String loreName = messages.getString(MessagesConfig.StringID.spigot_gui_lore_name); + String loreTag2 = messages.getString(MessagesConfig.StringID.spigot_gui_lore_rank_tag); + String lorePrice3 = messages.getString(MessagesConfig.StringID.spigot_gui_lore_price); + String lorePlayersWithRank = messages.getString(MessagesConfig.StringID.spigot_gui_lore_players_at_rank); // Decimal Rank cost format. DecimalFormat formatDecimal = new DecimalFormat("###,##0.00"); @@ -105,10 +105,10 @@ public void open(){ } if (i < ladder.get().getRanks().size()) { - gui.addButton(new Button(53, XMaterial.BOOK, 1, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_next_page), null), "&7Next " + (i + 1))); + gui.addButton(new Button(53, XMaterial.BOOK, 1, new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_next_page), null), "&7Next " + (i + 1))); } if (i >= (pageSize * 2)) { - gui.addButton(new Button(51, XMaterial.BOOK, 1, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_prior_page), null), + gui.addButton(new Button(51, XMaterial.BOOK, 1, new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_prior_page), null), "&7Prior " + (i - (pageSize * 2) - 1))); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllAdminAutoSellGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllAdminAutoSellGUI.java index be95a8507..f57604ca7 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllAdminAutoSellGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllAdminAutoSellGUI.java @@ -3,7 +3,7 @@ import com.cryptomorin.xseries.XMaterial; import org.bukkit.entity.Player; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -27,7 +27,7 @@ public void open() { PrisonGUI gui = new PrisonGUI(p, dimension, "&3SellAll -> AutoSell"); - ButtonLore closeGUILore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_close), null); + ButtonLore closeGUILore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_close), null); ButtonLore perUserToggleableLore = new ButtonLore(); ButtonLore enableDisableLore = new ButtonLore(); @@ -35,18 +35,18 @@ public void open() { Button enableDisableButton; if (sellAllConfig.getString("Options.Full_Inv_AutoSell_perUserToggleable").equalsIgnoreCase("true")){ - perUserToggleableLore.setLoreAction(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_disable)); + perUserToggleableLore.setLoreAction(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_disable)); perUserToggleableButton = new Button(11, XMaterial.LIME_STAINED_GLASS_PANE, perUserToggleableLore, "&3PerUserToggleable"); } else { - perUserToggleableLore.setLoreAction(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_enable)); + perUserToggleableLore.setLoreAction(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_enable)); perUserToggleableButton = new Button(11, XMaterial.RED_STAINED_GLASS_PANE, perUserToggleableLore, "&cPerUserToggleable-Disabled"); } if (sellAllConfig.getString("Options.Full_Inv_AutoSell").equalsIgnoreCase("true")){ - enableDisableLore.setLoreAction(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_disable)); + enableDisableLore.setLoreAction(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_disable)); enableDisableButton = new Button(15, XMaterial.LIME_STAINED_GLASS_PANE, enableDisableLore, "&3AutoSell"); } else { - enableDisableLore.setLoreAction(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_enable)); + enableDisableLore.setLoreAction(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_enable)); enableDisableButton = new Button(15, XMaterial.RED_STAINED_GLASS_PANE, enableDisableLore, "&cAutoSell-Disabled"); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllAdminBlocksGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllAdminBlocksGUI.java index d232d4824..a4e00ba9d 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllAdminBlocksGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllAdminBlocksGUI.java @@ -5,7 +5,7 @@ import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.SpigotUtil; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; @@ -48,8 +48,7 @@ public void open() { if (emptyInv){ SpigotPlayer spigotPlayer = new SpigotPlayer(p); - Output.get().sendWarn(spigotPlayer, messages.getString("Message.SellAllGUIEmpty")); - Output.get().sendWarn(spigotPlayer, messages.getString("Message.SellAllGUIEmpty2")); + Output.get().sendWarn(spigotPlayer, messages.getString(MessagesConfig.StringID.spigot_message_gui_sellall_empty)); return; } @@ -57,11 +56,11 @@ public void open() { Set items = sellAllConfig.getConfigurationSection("Items").getKeys(false); // Global strings. - String loreLine1 = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_delete); - String loreLine2 = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_left_to_edit); - String lorePermission = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_permission); + String loreLine1 = messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_right_to_delete); + String loreLine2 = messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_left_to_edit); + String lorePermission = messages.getString(MessagesConfig.StringID.spigot_gui_lore_permission); String permissionSellAllBlock = sellAllConfig.getString("Options.Sell_Per_Block_Permission"); - String loreValue = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_value); + String loreValue = messages.getString(MessagesConfig.StringID.spigot_gui_lore_value); boolean sellAllPerBlockPermissionEnabled = getBoolean(sellAllConfig.getString("Options.Sell_Per_Block_Permission_Enabled")); @@ -72,11 +71,11 @@ public void open() { if (itemsRead >= startingItem) { if (startingItem != 0){ - gui.addButton(new Button(45, XMaterial.BOOK, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_prior_page), null), "&7Prior " + (startingItem - 45))); + gui.addButton(new Button(45, XMaterial.BOOK, new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_prior_page), null), "&7Prior " + (startingItem - 45))); } if (itemsAdded >= 45){ - gui.addButton(new Button(53, XMaterial.BOOK, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_next_page), null), "&7Next " + (startingItem + itemsAdded))); + gui.addButton(new Button(53, XMaterial.BOOK, new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_next_page), null), "&7Next " + (startingItem + itemsAdded))); } if (itemsAdded < 45) { diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllAdminGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllAdminGUI.java index ef6eb9154..4f498d549 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllAdminGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllAdminGUI.java @@ -4,7 +4,7 @@ import org.bukkit.entity.Player; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; @@ -26,7 +26,7 @@ public SellAllAdminGUI(Player p) { public void open() { if (!SpigotPrison.getInstance().getConfig().getString("sellall").equalsIgnoreCase("true")){ - Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.SellAllIsDisabled")); + Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_gui_sellall_disabled)); return; } @@ -34,12 +34,12 @@ public void open() { PrisonGUI gui = new PrisonGUI(p, dimension, "&3Prison -> SellAll-Admin"); - ButtonLore blocksLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open), null); - ButtonLore closeGUILore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_close), null); - ButtonLore setCurrencyLore = new ButtonLore(createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_edit)), createLore( - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_currency) + sellAllConfig.getString("Options.SellAll_Currency"), - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_edit))); - ButtonLore multipliersLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_edit)); + ButtonLore blocksLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_open), null); + ButtonLore closeGUILore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_close), null); + ButtonLore setCurrencyLore = new ButtonLore(createLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_edit)), createLore( + messages.getString(MessagesConfig.StringID.spigot_gui_lore_currency) + " " + sellAllConfig.getString("Options.SellAll_Currency"), + messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_edit))); + ButtonLore multipliersLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_open), messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_edit)); ButtonLore autoSellLore = new ButtonLore(); ButtonLore sellAllDelayLore = new ButtonLore(); @@ -48,45 +48,45 @@ public void open() { if (sellAllConfig.getString("Options.Full_Inv_AutoSell").equalsIgnoreCase("true")){ autoSellLore.setLoreAction(createLore( - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open), - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_disable) + messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_open), + messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_right_to_disable) )); autoSellButton = new Button(13, XMaterial.CHEST, autoSellLore, "&3AutoSell"); } else { - autoSellLore.setLoreAction(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_enable)); + autoSellLore.setLoreAction(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_right_to_enable)); autoSellButton = new Button(13, XMaterial.CHEST, autoSellLore, "&cAutoSell-Disabled"); } if (sellAllConfig.getString("Options.Sell_Delay_Enabled").equalsIgnoreCase("true")){ sellAllDelayLore.setLoreAction(createLore( - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_open), - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_disable))); + messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_open), + messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_right_to_disable))); sellAllDelayLore.setLoreDescription(createLore( - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_delay) + sellAllConfig.getString("Options.Sell_Delay_Seconds") + "s", - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_sellall_delay_use_1), - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_sellall_delay_use_2))); + messages.getString(MessagesConfig.StringID.spigot_gui_lore_delay) + " " + sellAllConfig.getString("Options.Sell_Delay_Seconds") + "s", + messages.getString(MessagesConfig.StringID.spigot_gui_lore_sellall_delay_use_1), + messages.getString(MessagesConfig.StringID.spigot_gui_lore_sellall_delay_use_2))); sellAllDelayButton = new Button(11, XMaterial.CLOCK, sellAllDelayLore, "&3Delay-Enabled"); } else { - sellAllDelayLore.setLoreAction(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_enable)); + sellAllDelayLore.setLoreAction(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_enable)); sellAllDelayLore.setLoreDescription(createLore( - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_sellall_delay_use_1), - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_sellall_delay_use_2))); + messages.getString(MessagesConfig.StringID.spigot_gui_lore_sellall_delay_use_1), + messages.getString(MessagesConfig.StringID.spigot_gui_lore_sellall_delay_use_2))); sellAllDelayButton = new Button(11, XMaterial.CLOCK, sellAllDelayLore, "&cDelay-Disabled"); } try { if (sellAllConfig.getConfigurationSection("Multiplier") == null) { - multipliersLore.addLineLoreDescription(SpigotPrison.format(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_no_multipliers))); + multipliersLore.addLineLoreDescription(SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_gui_lore_no_multipliers))); } else if (sellAllConfig.getConfigurationSection("Multiplier").getKeys(false).size() == 0) { - multipliersLore.addLineLoreDescription(SpigotPrison.format(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_no_multipliers))); + multipliersLore.addLineLoreDescription(SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_gui_lore_no_multipliers))); } } catch (NullPointerException ex){ - multipliersLore.addLineLoreDescription(SpigotPrison.format(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_no_multipliers))); + multipliersLore.addLineLoreDescription(SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_gui_lore_no_multipliers))); } gui.addButton(new Button(15, XMaterial.EMERALD, setCurrencyLore, SpigotPrison.format("&3SellAll-Currency"))); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllDelayGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllDelayGUI.java index 6275aeb63..5d0938aec 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllDelayGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllDelayGUI.java @@ -3,7 +3,7 @@ import com.cryptomorin.xseries.XMaterial; import org.bukkit.entity.Player; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -30,9 +30,9 @@ public void open() { int dimension = 45; PrisonGUI gui = new PrisonGUI(p, dimension, "&3SellAll -> Delay"); - ButtonLore changeDecreaseValueLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_decrease), null); - ButtonLore confirmButtonLore = new ButtonLore(createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_left_to_confirm), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_cancel)), createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_delay) + " " + val + "s")); - ButtonLore changeIncreaseValueLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_increase), null); + ButtonLore changeDecreaseValueLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_decrease), null); + ButtonLore confirmButtonLore = new ButtonLore(createLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_left_to_confirm), messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_right_to_cancel)), createLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_delay) + " " + val + "s")); + ButtonLore changeIncreaseValueLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_increase), null); XMaterial decreaseMat = XMaterial.REDSTONE_BLOCK; XMaterial increaseMat = XMaterial.EMERALD_BLOCK; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPlayerGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPlayerGUI.java index fa5b2df78..1b8416e95 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPlayerGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPlayerGUI.java @@ -4,7 +4,7 @@ import org.bukkit.entity.Player; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.SpigotUtil; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; @@ -43,7 +43,7 @@ public void open() { } if (emptyInv){ - Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.NoSellAllItems")); + Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_gui_sellall_empty)); return; } @@ -51,7 +51,7 @@ public void open() { Set items = sellAllConfig.getConfigurationSection("Items").getKeys(false); // Global strings. - String loreValue = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_value); + String loreValue = messages.getString(MessagesConfig.StringID.spigot_gui_lore_value); int itemsAdded = 0, itemsRead = 0; for (String key : items) { @@ -60,11 +60,11 @@ public void open() { if (itemsRead >= startingItem) { if (startingItem != 0){ - gui.addButton(new Button(45, XMaterial.BOOK, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_prior_page), null), "&7Prior " + (startingItem - 45))); + gui.addButton(new Button(45, XMaterial.BOOK, new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_prior_page), null), "&7Prior " + (startingItem - 45))); } if (itemsAdded >= 45){ - gui.addButton(new Button(53, XMaterial.BOOK, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_next_page), null), "&7Next " + (startingItem + itemsAdded))); + gui.addButton(new Button(53, XMaterial.BOOK, new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_next_page), null), "&7Next " + (startingItem + itemsAdded))); } if (itemsAdded < 45) { diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPrestigesMultiplierGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPrestigesMultiplierGUI.java index c50f844ca..03926f73b 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPrestigesMultiplierGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPrestigesMultiplierGUI.java @@ -2,14 +2,12 @@ import com.cryptomorin.xseries.XMaterial; import org.bukkit.entity.Player; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; import tech.mcprison.prison.spigot.gui.guiutility.SpigotGUIComponents; -import java.util.List; - /** * @author GABRYCA */ @@ -34,10 +32,10 @@ public void open() { int pageSize = 45; // Global strings. - String lorePrestigeName = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_prestige_name); - String lorePrestigeMultiplier = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_multiplier); - String loreClickToEdit = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_edit); - String loreClickToDelete = newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_delete); + String lorePrestigeName = messages.getString(MessagesConfig.StringID.spigot_gui_lore_prestige_name); + String lorePrestigeMultiplier = messages.getString(MessagesConfig.StringID.spigot_gui_lore_multiplier); + String loreClickToEdit = messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_edit); + String loreClickToDelete = messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_right_to_delete); // Only loop over the blocks that we need to show: int i = counter; @@ -61,10 +59,10 @@ public void open() { } if (i < sellAllConfig.getConfigurationSection("Multiplier").getKeys(false).size()) { - gui.addButton(new Button(53, XMaterial.BOOK, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_next_page), null), "&7Next " + (i + 1))); + gui.addButton(new Button(53, XMaterial.BOOK, new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_next_page), null), "&7Next " + (i + 1))); } if (i >= (pageSize * 2)) { - gui.addButton(new Button(51, XMaterial.BOOK, new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_prior_page), null), "&7Prior " + (i - (pageSize * 2) - 1))); + gui.addButton(new Button(51, XMaterial.BOOK, new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_prior_page), null), "&7Prior " + (i - (pageSize * 2) - 1))); } gui.open(); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPrestigesSetMultiplierGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPrestigesSetMultiplierGUI.java index 1c2f8d649..6774209d1 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPrestigesSetMultiplierGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPrestigesSetMultiplierGUI.java @@ -3,7 +3,7 @@ import com.cryptomorin.xseries.XMaterial; import org.bukkit.entity.Player; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; @@ -31,11 +31,11 @@ public void open() { int dimension = 45; PrisonGUI gui = new PrisonGUI(p, dimension, "&3Edit -> Multiplier"); - ButtonLore changeDecreaseValueLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_decrease), null); + ButtonLore changeDecreaseValueLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_decrease), null); ButtonLore confirmButtonLore = new ButtonLore(createLore( - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_left_to_confirm), - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_cancel)), createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_multiplier) + " " + "x" + val)); - ButtonLore changeIncreaseValueLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_increase), null); + messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_left_to_confirm), + messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_right_to_cancel)), createLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_multiplier) + " " + "x" + val)); + ButtonLore changeIncreaseValueLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_increase), null); XMaterial decreaseMat = XMaterial.REDSTONE_BLOCK; XMaterial increaseMat = XMaterial.EMERALD_BLOCK; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPriceGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPriceGUI.java index b61df22d9..55ece4a1b 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPriceGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/sellall/SellAllPriceGUI.java @@ -3,14 +3,12 @@ import com.cryptomorin.xseries.XMaterial; import org.bukkit.entity.Player; import tech.mcprison.prison.spigot.SpigotPrison; -import tech.mcprison.prison.spigot.configs.NewMessagesConfig; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.gui.guiutility.Button; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; import tech.mcprison.prison.spigot.gui.guiutility.SpigotGUIComponents; -import java.util.List; - /** * @author GABRYCA */ @@ -33,10 +31,10 @@ public void open() { int dimension = 45; PrisonGUI gui = new PrisonGUI(p, dimension, "&3SellAll -> ItemValue"); - ButtonLore changeDecreaseValueLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_decrease), null); + ButtonLore changeDecreaseValueLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_decrease), null); ButtonLore confirmButtonLore = new ButtonLore(createLore( - newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_left_to_confirm), newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_right_to_cancel)), createLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_price) + " " + val)); - ButtonLore changeIncreaseValueLore = new ButtonLore(newMessages.getString(NewMessagesConfig.StringID.spigot_gui_lore_click_to_increase), null); + messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_left_to_confirm), messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_right_to_cancel)), createLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_price) + " " + val)); + ButtonLore changeIncreaseValueLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_increase), null); XMaterial decreaseMat = XMaterial.REDSTONE_BLOCK; XMaterial increaseMat = XMaterial.EMERALD_BLOCK; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java index c007874c2..d0f4d740e 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java @@ -25,6 +25,7 @@ import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.backpacks.BackpacksUtil; import tech.mcprison.prison.spigot.compat.Compatibility; +import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.gui.sellall.SellAllAdminGUI; import tech.mcprison.prison.spigot.gui.sellall.SellAllPlayerGUI; @@ -50,7 +51,7 @@ public class SellAllUtil { private ArrayList sellAllItemTriggers; private ArrayList activePlayerDelay = new ArrayList<>(); private List sellAllDisabledWorlds; - private Configuration messages; + private MessagesConfig messages; private double defaultMultiplier; private int defaultSellAllDelay; private int defaultAutoSellEarningNotificationDelay; @@ -1181,7 +1182,7 @@ public void removeFromDelay(Player p){ * */ public void removeFromAutoSellDelayAndNotify(Player p){ if (autoSellEarningsNotificationWaiting.containsKey(p) && autoSellEarningsNotificationWaiting.get(p) > 0.00){ - Output.get().sendInfo(new SpigotPlayer(p), SpigotPrison.format(messages.getString("Message.SellAllAutoSellEarnedMoney") + autoSellEarningsNotificationWaiting.get(p) + messages.getString("Message.SellAllAutoSellEarnedMoneyCurrency"))); + Output.get().sendInfo(new SpigotPlayer(p), SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_sellall_money_earned) + autoSellEarningsNotificationWaiting.get(p))); } autoSellEarningsNotificationWaiting.remove(p); } @@ -1267,7 +1268,6 @@ public boolean setAutoSellPlayer(Player p, boolean enable){ conf.set("Users." + p.getUniqueId() + ".isEnabled", enable); conf.save(sellAllFile); } catch (IOException e) { - Output.get().sendError(new SpigotPlayer(p), SpigotPrison.format(messages.getString("Message.SellAllConfigSaveFail"))); e.printStackTrace(); return false; } @@ -1391,7 +1391,7 @@ public boolean setDelay(int delay){ * * Return True if success, False if error or nothing changed or Player not meeting requirements. * - * Default usage of this method: sellAllSell(p, false, false, true, false, false, true); + * Default usage of this method: sellAllSell(p, false, false, true, true, false, true); * * @param p - Player. * @param isUsingSign - boolean. @@ -1406,21 +1406,21 @@ public boolean setDelay(int delay){ public boolean sellAllSell(Player p, boolean isUsingSign, boolean completelySilent, boolean notifyPlayerEarned, boolean notifyPlayerDelay, boolean notifyPlayerEarningDelay, boolean playSoundOnSellAll){ if (!isUsingSign && isSellAllSignEnabled && isSellAllBySignOnlyEnabled && !p.hasPermission(permissionBypassSign)){ if (!completelySilent) { - Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.SellAllSignOnly")); + Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_sellall_sell_sign_only)); } return false; } if (isSellAllDelayEnabled && isPlayerWaitingSellAllDelay(p)){ if (notifyPlayerDelay && !completelySilent) { - Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.SellAllWaitDelay")); + Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_sellall_delay_wait)); } return false; } if (sellAllBlocks.isEmpty()){ if (!completelySilent){ - Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.SellAllEmpty")); + Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_sellall_sell_empty)); } return false; } @@ -1450,7 +1450,7 @@ public boolean sellAllSell(Player p, boolean isUsingSign, boolean completelySile addDelayedEarningAutoSellNotification(p, money); } } else if (notifyPlayerEarned){ - Output.get().sendInfo(sPlayer, messages.getString("Message.SellAllYouGotMoney") + money); + Output.get().sendInfo(sPlayer, messages.getString(MessagesConfig.StringID.spigot_message_sellall_money_earned) + money); } } return true; @@ -1459,7 +1459,7 @@ public boolean sellAllSell(Player p, boolean isUsingSign, boolean completelySile if (isSellAllSoundEnabled && playSoundOnSellAll) { p.playSound(p.getLocation(), sellAllSoundFail, 3, 1); } - Output.get().sendInfo(new SpigotPlayer(p), messages.getString("Message.SellAllNothingToSell")); + Output.get().sendInfo(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_sellall_sell_nothing_sellable)); } return false; } @@ -1499,21 +1499,21 @@ public boolean sellAllSell(Player p, boolean isUsingSign, boolean completelySile public ArrayList sellAllSell(Player p, ArrayList itemStacks, boolean isUsingSign, boolean completelySilent, boolean notifyPlayerEarned, boolean notifyPlayerDelay, boolean notifyPlayerEarningDelay, boolean playSoundOnSellAll, boolean sellInputArrayListOnly){ if (!isUsingSign && isSellAllSignEnabled && isSellAllBySignOnlyEnabled && !p.hasPermission(permissionBypassSign)){ if (!completelySilent) { - Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.SellAllSignOnly")); + Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_sellall_sell_sign_only)); } return itemStacks; } if (isSellAllDelayEnabled && isPlayerWaitingSellAllDelay(p)){ if (notifyPlayerDelay && !completelySilent) { - Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.SellAllWaitDelay")); + Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_sellall_delay_wait)); } return itemStacks; } if (sellAllBlocks.isEmpty()){ if (!completelySilent){ - Output.get().sendWarn(new SpigotPlayer(p), messages.getString("Message.SellAllEmpty")); + Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_sellall_sell_empty)); } return itemStacks; } @@ -1557,7 +1557,7 @@ public ArrayList sellAllSell(Player p, ArrayList itemStack addDelayedEarningAutoSellNotification(p, money); } } else if (notifyPlayerEarned){ - Output.get().sendInfo(sPlayer, messages.getString("Message.SellAllYouGotMoney") + money); + Output.get().sendInfo(sPlayer, messages.getString(MessagesConfig.StringID.spigot_message_sellall_money_earned) + money); } } } else { @@ -1565,7 +1565,7 @@ public ArrayList sellAllSell(Player p, ArrayList itemStack if (isSellAllSoundEnabled && playSoundOnSellAll) { p.playSound(p.getLocation(), sellAllSoundFail, 3, 1); } - Output.get().sendInfo(new SpigotPlayer(p), messages.getString("Message.SellAllNothingToSell")); + Output.get().sendInfo(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_sellall_sell_nothing_sellable)); } } return itemStacks; From 3885593a999ab5e8801572b2ed6ae27dd1d71a49 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sat, 11 Sep 2021 17:32:36 -0400 Subject: [PATCH 056/283] Hook up the auto features notification to use the new actionBar interface. This "should" prevent duplicate messages from being sent to the player while the same message is displayed in the actionbar. --- .../autofeatures/AutoManagerFeatures.java | 48 ++++++++++--------- .../prison/spigot/game/SpigotPlayer.java | 8 +++- 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java index aa97437bc..6990766ed 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java @@ -7,13 +7,11 @@ import java.util.Random; import java.util.Set; import java.util.TreeMap; -import java.util.UUID; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.Sound; import org.bukkit.block.Block; -import org.bukkit.configuration.Configuration; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.ArmorStand; import org.bukkit.entity.EntityType; @@ -23,10 +21,9 @@ import com.cryptomorin.xseries.XMaterial; -import net.md_5.bungee.api.ChatMessageType; -import net.md_5.bungee.api.chat.TextComponent; import tech.mcprison.prison.Prison; import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; +import tech.mcprison.prison.autofeatures.PlayerMessaging.MessageType; import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.mines.features.MineBlockEvent.BlockEventType; @@ -41,7 +38,7 @@ import tech.mcprison.prison.spigot.compat.SpigotCompatibility; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.sellall.SellAllUtil; -import tech.mcprison.prison.spigot.spiget.BluesSpigetSemVerComparator; +import tech.mcprison.prison.spigot.utils.tasks.PlayerMessagingTask; import tech.mcprison.prison.util.BlockType; import tech.mcprison.prison.util.Text; @@ -805,10 +802,10 @@ private void dropExtra( HashMap extra, Player player ) } } - private boolean isBoolean( Configuration sellAllConfig, String config ) { - String configValue = sellAllConfig.getString( config ); - return configValue != null && configValue.equalsIgnoreCase( "true" ); - } +// private boolean isBoolean( Configuration sellAllConfig, String config ) { +// String configValue = sellAllConfig.getString( config ); +// return configValue != null && configValue.equalsIgnoreCase( "true" ); +// } private void dropAtBlock( SpigotItemStack itemStack, SpigotBlock block ) { @@ -848,23 +845,30 @@ private void notifyPlayerWithSound( Player player, AutoFeatures messageId ) { player.playSound(player.getLocation(), sound, 10F, 1F); } + (new SpigotPlayer( player )).setActionBar( message ); + // holographic display for showing full inventory does not work well. // if ( isBoolean( AutoFeatures.hologramIfInventoryIsFull ) ) { // displayMessageHologram( block, message , player); // } // else { - actionBarVersion(player, message); +// actionBarVersion(player, message); // } } - private void actionBarVersion(Player player, String message) { - if (new BluesSpigetSemVerComparator().compareMCVersionTo("1.9.0") < 0) { - displayActionBarMessage(player, message); - } - else { - player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(SpigotPrison.format(message))); - } - } +// private void actionBarVersion(Player player, String message) { +// +// PlayerMessagingTask.submitTask( player, MessageType.actionBar, message ); +// +//// SpigotCompatibility.getInstance().sendActionBar( player, message ); +// +//// if (new BluesSpigetSemVerComparator().compareMCVersionTo("1.9.0") < 0) { +//// displayActionBarMessage(player, message); +//// } +//// else { +//// player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(SpigotPrison.format(message))); +//// } +// } /** * This is not usable since it not only prevents the player from mining when it is @@ -888,10 +892,10 @@ private void displayMessageHologram(Block block, String message, Player p){ Bukkit.getScheduler().scheduleSyncDelayedTask(SpigotPrison.getInstance(), as::remove, (7L * 20L)); } - private void displayActionBarMessage(Player player, String message) { - SpigotPlayer prisonPlayer = new SpigotPlayer(player); - Prison.get().getPlatform().showActionBar(prisonPlayer, message, 80); - } +// private void displayActionBarMessage(Player player, String message) { +// SpigotPlayer prisonPlayer = new SpigotPlayer(player); +// Prison.get().getPlatform().showActionBar(prisonPlayer, message, 80); +// } /** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayer.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayer.java index c46d9bbbb..b19c4a3cc 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayer.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayer.java @@ -29,6 +29,7 @@ import org.bukkit.entity.ExperienceOrb; import org.bukkit.event.player.PlayerTeleportEvent; +import tech.mcprison.prison.autofeatures.PlayerMessaging.MessageType; import tech.mcprison.prison.internal.ItemStack; import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.internal.inventory.Inventory; @@ -40,6 +41,7 @@ import tech.mcprison.prison.spigot.compat.SpigotNMSPlayer; import tech.mcprison.prison.spigot.inventory.SpigotPlayerInventory; import tech.mcprison.prison.spigot.scoreboard.SpigotScoreboard; +import tech.mcprison.prison.spigot.utils.tasks.PlayerMessagingTask; import tech.mcprison.prison.util.Gamemode; import tech.mcprison.prison.util.Location; @@ -613,8 +615,10 @@ public void setTitle( String title, String subtitle, int fadeIn, int stay, int f @Override public void setActionBar( String actionBar ) { if ( getWrapper() != null) { - SpigotCompatibility.getInstance() - .sendActionBar( getWrapper(), actionBar ); + PlayerMessagingTask.submitTask( getWrapper(), MessageType.actionBar, actionBar ); + +// SpigotCompatibility.getInstance() +// .sendActionBar( getWrapper(), actionBar ); } } } From 76941165bf9d1c9c741427746dde7f6fc81c996a Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 12 Sep 2021 11:43:47 -0400 Subject: [PATCH 057/283] For the actionBar and title, translate the color codes so they work properly. --- docs/changelog_v3.3.x.md | 9 ++++++++- .../mcprison/prison/spigot/compat/Spigot18Player.java | 8 +++++++- .../mcprison/prison/spigot/compat/Spigot19Player.java | 10 +++++++--- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 28fcd442c..25b866f4b 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,14 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.1 2021-09-08 +# 3.2.11-alpha.1 2021-09-12 + + +* **For the actionBar and title, translate the color codes so they work properly.** + + +* **Hook up the auto features notification to use the new actionBar interface.** +This "should" prevent duplicate messages from being sent to the player while the same message is displayed in the actionbar. * **Fixed an error about backpacks and lore transition:** A single lore was being used for the backpacks utility, if a server diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18Player.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18Player.java index 4862f8e3d..32de7241f 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18Player.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18Player.java @@ -5,6 +5,8 @@ import com.cryptomorin.xseries.messages.ActionBar; import com.cryptomorin.xseries.messages.Titles; +import tech.mcprison.prison.util.Text; + public abstract class Spigot18Player extends CompatibilityCache implements CompatibilityPlayer @@ -43,6 +45,9 @@ public void setMaxHealth( Player player, double maxHealth ) { public void sendTitle( Player player, String title, String subtitle, int fadeIn, int stay, int fadeOut ) { //player.sendTitle( title, subtitle ); + title = title == null ? null : Text.translateAmpColorCodes( title ); + subtitle = subtitle == null ? null : Text.translateAmpColorCodes( subtitle ); + Titles.sendTitle( player, fadeIn, stay, fadeOut, title, subtitle ); } @@ -58,7 +63,8 @@ public void sendTitle( Player player, String title, String subtitle, int fadeIn, @Override public void sendActionBar( Player player, String actionBar ) { - ActionBar.sendActionBar( player, actionBar ); + String message = Text.translateAmpColorCodes( actionBar ); + ActionBar.sendActionBar( player, message ); // Was using the following until it was replaced with XSeries' ActionBar: // player.sendTitle( "", actionBar ); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot19Player.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot19Player.java index 71a0cdb67..370aa8045 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot19Player.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot19Player.java @@ -7,6 +7,8 @@ import com.cryptomorin.xseries.messages.ActionBar; import com.cryptomorin.xseries.messages.Titles; +import tech.mcprison.prison.util.Text; + public abstract class Spigot19Player extends Spigot18Blocks { @@ -38,8 +40,9 @@ public double getMaxHealth( Player player ) { //@SuppressWarnings( "deprecation" ) public void sendTitle( Player player, String title, String subtitle, int fadeIn, int stay, int fadeOut ) { - //player.sendTitle( title, subtitle ); - + title = title == null ? null : Text.translateAmpColorCodes( title ); + subtitle = subtitle == null ? null : Text.translateAmpColorCodes( subtitle ); + Titles.sendTitle( player, fadeIn, stay, fadeOut, title, subtitle ); } @@ -47,7 +50,8 @@ public void sendTitle( Player player, String title, String subtitle, int fadeIn, @Override public void sendActionBar( Player player, String actionBar ) { - ActionBar.sendActionBar( player, actionBar ); + String message = Text.translateAmpColorCodes( actionBar ); + ActionBar.sendActionBar( player, message ); // Was using the following until it was replaced with XSeries' ActionBar: // player.spigot().sendMessage( ChatMessageType.ACTION_BAR, From 3e22fdad7645b969a4491c97b7c5ddaa40b1ac70 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 12 Sep 2021 11:46:46 -0400 Subject: [PATCH 058/283] Add placeholders {actionBar} and {title} to the blockEvent listing of placeholders that can be used. They are shortcuts for the new prison utils commands. --- docs/changelog_v3.3.x.md | 4 ++++ .../java/tech/mcprison/prison/tasks/PrisonCommandTask.java | 2 ++ .../tech/mcprison/prison/mines/commands/MinesCommands.java | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 25b866f4b..de5e964ec 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-09-12 +* **Add placeholders {actionBar} and {title} to the blockEvent listing of placeholders that can be used.** +They are shortcuts for the new prison utils commands. + + * **For the actionBar and title, translate the color codes so they work properly.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonCommandTask.java b/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonCommandTask.java index f0895ec1a..4644767d5 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonCommandTask.java +++ b/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonCommandTask.java @@ -258,6 +258,8 @@ private String translateCommand( Player player, String command ) { if ( player != null ) { formatted = formatted .replace( "{msg}", "prison utils msg {player} " ) + .replace( "{actionBar}", "prison utils titles actionBar {player} " ) + .replace( "{title}", "prison utils titles title {player} " ) .replace( "{player}", player.getName()) .replace( "{player_uid}", player.getUUID().toString()) .replace( "{utilsDecay}", "prison utils decay" ); diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java index e869ea795..112fe0ae8 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java @@ -3227,7 +3227,7 @@ public void blockEventRemove(CommandSender sender, @Command(identifier = "mines blockEvent add", description = "Adds a BlockBreak command to a mine. " + "For each block that is broke there will be a chance to run one of these commands. \n" + - "To send messages use {msg} or {broadcast} followed by the formatted message. " + + "To send messages use {msg}, {broadcast}, {actionBar}, or {title} followed by the formatted message. " + "Can use placeholders {player} and {player_uid}. Use ; between multiple commands. \n" + "Example: &7\\Q'token give {player} 1;{msg} &7You got &31 &7token!;tpa a'\\E&3 \n" + "This command defaults to no permission and 'sync' task mode; " + From e31cdbedd1cee620fa25295143e986e19fb4526a Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 12 Sep 2021 13:45:23 -0400 Subject: [PATCH 059/283] Some initial work to setup the mine bombs configs. --- docs/changelog_v3.3.x.md | 3 + .../tech/mcprison/prison/file/FileIO.java | 22 ++++++- .../tech/mcprison/prison/file/JsonFileIO.java | 5 ++ .../prison/spigot/bombs/MineBombData.java | 50 +++++++++++++- .../prison/spigot/bombs/MineBombs.java | 66 +++++++++++++++++++ .../spigot/bombs/MineBombsConfigData.java | 25 +++++++ .../spigot/utils/PrisonUtilsMineBombs.java | 2 +- 7 files changed, 167 insertions(+), 6 deletions(-) create mode 100644 prison-spigot/src/main/java/tech/mcprison/prison/spigot/bombs/MineBombsConfigData.java diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index de5e964ec..2e62c933a 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-09-12 +* **Some initial work to setup the mine bombs configs.** + + * **Add placeholders {actionBar} and {title} to the blockEvent listing of placeholders that can be used.** They are shortcuts for the new prison utils commands. diff --git a/prison-core/src/main/java/tech/mcprison/prison/file/FileIO.java b/prison-core/src/main/java/tech/mcprison/prison/file/FileIO.java index 75071c04f..67e0c98a6 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/file/FileIO.java +++ b/prison-core/src/main/java/tech/mcprison/prison/file/FileIO.java @@ -9,6 +9,7 @@ import java.util.Date; import java.util.List; +import tech.mcprison.prison.Prison; import tech.mcprison.prison.error.Error; import tech.mcprison.prison.error.ErrorManager; import tech.mcprison.prison.modules.ModuleStatus; @@ -28,6 +29,11 @@ public FileIO() this(null, null); } + /** + * + * @param errorManager Optional; set to null if used outside of a module. + * @param status Optional; set to null if used outside of a module. + */ public FileIO(ErrorManager errorManager, ModuleStatus status) { super(); @@ -39,12 +45,24 @@ public FileIO(ErrorManager errorManager, ModuleStatus status) } + public File getProjectRootDiretory() { + return Prison.get().getDataFolder(); + } + + public File getTempFile( File file ) { + String tempFileName = file.getName() + "." + getTimestampFormat() + ".tmp"; + File tempFile = new File(file.getParentFile(), tempFileName); + + return tempFile; + } + protected void saveFile( File file, String data ) { if ( file != null && data != null ) { - String tempFileName = file.getName() + "." + getTimestampFormat() + ".tmp"; - File tempFile = new File(file.getParentFile(), tempFileName); + File tempFile = getTempFile( file ); +// String tempFileName = file.getName() + "." + getTimestampFormat() + ".tmp"; +// File tempFile = new File(file.getParentFile(), tempFileName); try { diff --git a/prison-core/src/main/java/tech/mcprison/prison/file/JsonFileIO.java b/prison-core/src/main/java/tech/mcprison/prison/file/JsonFileIO.java index 04482a331..bc872b0e8 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/file/JsonFileIO.java +++ b/prison-core/src/main/java/tech/mcprison/prison/file/JsonFileIO.java @@ -14,6 +14,11 @@ public class JsonFileIO { private final Gson gson; + /** + * + * @param errorManager Optional; set to null if used outside of a module. + * @param status Optional; set to null if used outside of a module. + */ public JsonFileIO(ErrorManager errorManager, ModuleStatus status) { super(errorManager, status); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/bombs/MineBombData.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/bombs/MineBombData.java index 93950d8a7..276e48cbf 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/bombs/MineBombData.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/bombs/MineBombData.java @@ -37,12 +37,56 @@ public class MineBombData { * a chance if it is to be included, or excluded. *

*/ - private double chance; + // private double chance; private String explosionShape; - - + public MineBombData() { + super(); + + } + + public String getName() { + return name; + } + public void setName( String name ) { + this.name = name; + } + + public String getItemType() { + return itemType; + } + public void setItemType( String itemType ) { + this.itemType = itemType; + } + + public XMaterial getItem() { + return item; + } + public void setItem( XMaterial item ) { + this.item = item; + } + + public List getLore() { + return lore; + } + public void setLore( List lore ) { + this.lore = lore; + } + + public int getRadius() { + return radius; + } + public void setRadius( int radius ) { + this.radius = radius; + } + + public String getExplosionShape() { + return explosionShape; + } + public void setExplosionShape( String explosionShape ) { + this.explosionShape = explosionShape; + } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/bombs/MineBombs.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/bombs/MineBombs.java index c41d94dd0..50b101b30 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/bombs/MineBombs.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/bombs/MineBombs.java @@ -1,12 +1,22 @@ package tech.mcprison.prison.spigot.bombs; +import java.io.File; import java.util.ArrayList; import java.util.List; +import tech.mcprison.prison.file.JsonFileIO; import tech.mcprison.prison.util.Location; public class MineBombs { + public static final String MINE_BOMBS_FILE_NAME = "mineBombsConifg.json"; + public static final String MINE_BOMBS_PATH_NAME = "module_conf/mines"; + + private static MineBombs instance; + + private MineBombsConfigData configData; + + public enum ExplosionShape { sphere, @@ -14,7 +24,55 @@ public enum ExplosionShape { ; } + + private MineBombs() { + super(); + + loadConfigJson(); + } + public static MineBombs getInstance() { + if ( instance == null ) { + synchronized ( MineBombs.class ) { + if ( instance == null ) { + + instance = new MineBombs(); + } + } + } + return instance; + } + + public void saveConfigJson() { + + JsonFileIO fio = new JsonFileIO( null, null ); + + File configFile = getConfigFile( fio ); + + fio.saveJsonFile( configFile, getConfigData() ); + + } + + public File getConfigFile( JsonFileIO jsonFileIO ) { + + File path = new File( jsonFileIO.getProjectRootDiretory(), MINE_BOMBS_PATH_NAME ); + path.mkdirs(); + File configFile = new File( path, MINE_BOMBS_FILE_NAME ); + + return configFile; + } + + public void loadConfigJson() { + JsonFileIO fio = new JsonFileIO( null, null ); + + File configFile = getConfigFile( fio ); + + MineBombsConfigData configs = + (MineBombsConfigData) fio.readJsonFile( configFile, getConfigData() ); + + setConfigData( configs ); + } + public List calculateSphere( Location loc, int radius, boolean hollow ) { List results = new ArrayList<>(); @@ -48,4 +106,12 @@ public List calculateSphere( Location loc, int radius, boolean hollow } return results; } + + public MineBombsConfigData getConfigData() { + return configData; + } + public void setConfigData( MineBombsConfigData configData ) { + this.configData = configData; + } + } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/bombs/MineBombsConfigData.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/bombs/MineBombsConfigData.java new file mode 100644 index 000000000..22b5cecc7 --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/bombs/MineBombsConfigData.java @@ -0,0 +1,25 @@ +package tech.mcprison.prison.spigot.bombs; + +import java.util.Map; +import java.util.TreeMap; + +import tech.mcprison.prison.file.FileIOData; + +public class MineBombsConfigData + implements FileIOData +{ + private Map bombs; + + public MineBombsConfigData() { + super(); + + this.bombs = new TreeMap<>(); + } + + public Map getBombs() { + return bombs; + } + public void setBombs( Map bombs ) { + this.bombs = bombs; + } +} diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java index 8404aa488..4bb131728 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java @@ -100,7 +100,7 @@ public void utilsMineBombs( CommandSender sender, radius = Integer.parseInt( radiusSize ); - MineBombs mBombs = new MineBombs(); + MineBombs mBombs = MineBombs.getInstance(); SpigotWorld world = (SpigotWorld) location.getWorld(); From 7ca3d5889b14bbaf394c9f691cd00908f418b427 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Tue, 14 Sep 2021 11:35:47 -0400 Subject: [PATCH 060/283] Significant progress on Prison's Mine Bombs: Moved the mine bombs primary classes to the prison core so it's accessible from all packages. Setup 4 default mine bombs if the commands are used and there are none defined. Setup a new /prison utils bomb commands to list all bombs and to give players bombs. These are not complete and fully tested yet. --- docs/changelog_v3.3.x.md | 8 +- .../mcprison/prison}/bombs/MineBombData.java | 45 ++++++- .../mcprison/prison}/bombs/MineBombs.java | 64 +++++++++- .../prison}/bombs/MineBombsConfigData.java | 2 +- .../spigot/utils/PrisonUtilsMineBombs.java | 116 +++++++++++++++++- 5 files changed, 222 insertions(+), 13 deletions(-) rename {prison-spigot/src/main/java/tech/mcprison/prison/spigot => prison-core/src/main/java/tech/mcprison/prison}/bombs/MineBombData.java (65%) rename {prison-spigot/src/main/java/tech/mcprison/prison/spigot => prison-core/src/main/java/tech/mcprison/prison}/bombs/MineBombs.java (53%) rename {prison-spigot/src/main/java/tech/mcprison/prison/spigot => prison-core/src/main/java/tech/mcprison/prison}/bombs/MineBombsConfigData.java (90%) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 2e62c933a..0d86e464c 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,13 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.1 2021-09-12 +# 3.2.11-alpha.1 2021-09-14 + + +* **Significant progress on Prison's Mine Bombs:** +Moved the mine bombs primary classes to the prison core so it's accessible from all packages. +Setup 4 default mine bombs if the commands are used and there are none defined. +Setup a new /prison utils bomb commands to list all bombs and to give players bombs. These are not complete and fully tested yet. * **Some initial work to setup the mine bombs configs.** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/bombs/MineBombData.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java similarity index 65% rename from prison-spigot/src/main/java/tech/mcprison/prison/spigot/bombs/MineBombData.java rename to prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java index 276e48cbf..3edc31be7 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/bombs/MineBombData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java @@ -1,8 +1,9 @@ -package tech.mcprison.prison.spigot.bombs; +package tech.mcprison.prison.bombs; +import java.util.ArrayList; import java.util.List; -import com.cryptomorin.xseries.XMaterial; +import tech.mcprison.prison.internal.block.PrisonBlock; public class MineBombData { @@ -20,7 +21,7 @@ public class MineBombData { * for the bomb. This is converted from the String itemType. *

*/ - private transient XMaterial item; + private transient PrisonBlock item; private List lore; @@ -42,10 +43,37 @@ public class MineBombData { private String explosionShape; + + private String description; + + public MineBombData() { super(); } + + + public MineBombData( String name, String itemType, String explosionShape, + int radius, String... lores ) { + this(); + + this.name = name; + this.itemType = itemType; + + this.explosionShape = explosionShape; + this.radius = radius; + + this.lore = new ArrayList<>(); + + if ( lores != null ) { + for ( String l : lores ) { + this.lore.add( l ); + } + } + + } + + public String getName() { return name; @@ -61,10 +89,10 @@ public void setItemType( String itemType ) { this.itemType = itemType; } - public XMaterial getItem() { + public PrisonBlock getItem() { return item; } - public void setItem( XMaterial item ) { + public void setItem( PrisonBlock item ) { this.item = item; } @@ -88,5 +116,12 @@ public String getExplosionShape() { public void setExplosionShape( String explosionShape ) { this.explosionShape = explosionShape; } + + public String getDescription() { + return description; + } + public void setDescription( String description ) { + this.description = description; + } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/bombs/MineBombs.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java similarity index 53% rename from prison-spigot/src/main/java/tech/mcprison/prison/spigot/bombs/MineBombs.java rename to prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java index 50b101b30..68918bc5a 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/bombs/MineBombs.java +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java @@ -1,15 +1,16 @@ -package tech.mcprison.prison.spigot.bombs; +package tech.mcprison.prison.bombs; import java.io.File; import java.util.ArrayList; import java.util.List; import tech.mcprison.prison.file.JsonFileIO; +import tech.mcprison.prison.output.Output; import tech.mcprison.prison.util.Location; public class MineBombs { - public static final String MINE_BOMBS_FILE_NAME = "mineBombsConifg.json"; + public static final String MINE_BOMBS_FILE_NAME = "mineBombsConfig.json"; public static final String MINE_BOMBS_PATH_NAME = "module_conf/mines"; private static MineBombs instance; @@ -28,6 +29,8 @@ public enum ExplosionShape { private MineBombs() { super(); + this.configData = new MineBombsConfigData(); + loadConfigJson(); } @@ -67,10 +70,21 @@ public void loadConfigJson() { File configFile = getConfigFile( fio ); - MineBombsConfigData configs = - (MineBombsConfigData) fio.readJsonFile( configFile, getConfigData() ); + if ( !configFile.exists() ) { + setupDefaultMineBombData(); + } - setConfigData( configs ); + else { + + MineBombsConfigData configs = + (MineBombsConfigData) fio.readJsonFile( configFile, getConfigData() ); + + if ( configs != null && configs.getBombs().size() > 0 ) { + + getConfigData().getBombs().putAll( configs.getBombs() ); + + } + } } public List calculateSphere( Location loc, int radius, boolean hollow ) { @@ -106,6 +120,46 @@ public List calculateSphere( Location loc, int radius, boolean hollow } return results; } + + public void setupDefaultMineBombData() + { + if ( getConfigData().getBombs().size() == 0 ) { + + MineBombData mbDataSmall = new MineBombData( + "SmallBomb", "brewing_stand", "sphere", 2, "Small Mine Bomb" ); + mbDataSmall.setDescription("A small mine bomb made with some chemicals and a brewing stand."); + + MineBombData mbDataMedium = new MineBombData( + "MediumBomb", "fireworks", "sphere", 5, "Medium Mine Bomb" ); + mbDataMedium.setDescription("A medium mine bomb made from leftover fireworks, " + + "but supercharged with a strange green glowing liquid."); + + MineBombData mbDataLarge = new MineBombData( + "LargeBomb", "tnt", "sphereHollow", 12, "Large Mine Bomb" ); + mbDataLarge.setDescription("A large mine bomb made from TNT with some strange parts " + + "that maybe be " + + "described as alien technology."); + + MineBombData mbDataOof = new MineBombData( + "OofBomb", "tnt_minecard", "sphereHollow", 19, "Oof Mine Bomb" ); + mbDataOof.setDescription("An oof-ably large mine bomb made with a minecart heaping with TNT. " + + "Unlike the large mine bomb, this one obviously is built with alien technology."); + + + getConfigData().getBombs().put( mbDataSmall.getName(), mbDataSmall ); + getConfigData().getBombs().put( mbDataMedium.getName(), mbDataMedium ); + getConfigData().getBombs().put( mbDataLarge.getName(), mbDataLarge ); + getConfigData().getBombs().put( mbDataOof.getName(), mbDataOof ); + + saveConfigJson(); + + Output.get().logInfo( "Mine bombs: setup default values." ); + } + else { + Output.get().logInfo( "Could not generate a mine bombs save file since at least one already exists." ); + } + + } public MineBombsConfigData getConfigData() { return configData; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/bombs/MineBombsConfigData.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombsConfigData.java similarity index 90% rename from prison-spigot/src/main/java/tech/mcprison/prison/spigot/bombs/MineBombsConfigData.java rename to prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombsConfigData.java index 22b5cecc7..07c4fea5b 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/bombs/MineBombsConfigData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombsConfigData.java @@ -1,4 +1,4 @@ -package tech.mcprison.prison.spigot.bombs; +package tech.mcprison.prison.bombs; import java.util.Map; import java.util.TreeMap; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java index 4bb131728..218bf375f 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java @@ -2,16 +2,18 @@ import java.util.ArrayList; import java.util.List; +import java.util.Set; import org.bukkit.Bukkit; +import tech.mcprison.prison.bombs.MineBombData; +import tech.mcprison.prison.bombs.MineBombs; import tech.mcprison.prison.commands.Arg; import tech.mcprison.prison.commands.Command; import tech.mcprison.prison.internal.CommandSender; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.api.ExplosiveBlockBreakEvent; import tech.mcprison.prison.spigot.block.SpigotBlock; -import tech.mcprison.prison.spigot.bombs.MineBombs; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.game.SpigotWorld; import tech.mcprison.prison.util.Location; @@ -128,6 +130,118 @@ public void utilsMineBombs( CommandSender sender, } } + + + @Command(identifier = "prison utils bomb list", + description = "A list of all available bombs.", + onlyPlayers = false, + permissions = "prison.utils.bombs" ) + public void utilsMineBombsList( CommandSender sender + + ) { + + if ( !isEnableMineBombs() ) { + + Output.get().logInfo( "Prison's utils command mine bombs is disabled in modules.yml." ); + } + else { + + MineBombs mBombs = MineBombs.getInstance(); + + Set keys = mBombs.getConfigData().getBombs().keySet(); + for ( String key : keys ) { + + MineBombData bomb = mBombs.getConfigData().getBombs().get( key ); + + String message = String.format( + "%-12s %-7s Radius= %s (%s)\n %s", + bomb.getName(), bomb.getExplosionShape(), Integer.toString(bomb.getRadius()), + bomb.getItemType(), bomb.getDescription() ); + + sender.sendMessage( message ); + } + + } + } + + + @Command(identifier = "prison utils bomb give", + description = "Gives the player a mine bomb. Can also provide a list of " + + "all available bombs.", + onlyPlayers = false, + permissions = "prison.utils.bombs", + altPermissions = "prison.utils.bombs.others") + public void utilsMineBombsGive( CommandSender sender, + @Arg(name = "playerName", description = "Player name") String playerName, + + @Arg(name = "bombName", description = "The bomb name, or 'list' to show all available " + + "bombs. [round]", + def = "list") String bombName, + @Arg(name = "quantity", description = "Quantity of bombs to give. [1 > +]", + def = "1" ) + String quantity + + ) { + + if ( !isEnableMineBombs() ) { + + Output.get().logInfo( "Prison's utils command mine bombs is disabled in modules.yml." ); + } + else { + + + if ( "list".equalsIgnoreCase( bombName ) ) { + + utilsMineBombsList( sender ); + return; + } + + SpigotPlayer player = checkPlayerPerms( sender, playerName, + "prison.utils.bomb", "prison.utils.bomb.others" ); + + if ( player != null ) { + + if ( playerName != null && !playerName.equalsIgnoreCase( player.getName() ) ) { + // Need to shift the player's name over to the message: + + } + + + if ( bombName == null ) { + Output.get().logInfo( "Prison utils giveBomb: You need to specify a bomb name, or " + + "use 'list' to show all available bombs. " ); + return; + } + + int count = 1; + + count = Integer.parseInt( quantity ); + + MineBombs mBombs = MineBombs.getInstance(); + + +// if ( "list".equalsIgnoreCase( bombName ) ) { +// +// Set keys = mBombs.getConfigData().getBombs().keySet(); +// for ( String key : keys ) { +// +// MineBombData bomb = mBombs.getConfigData().getBombs().get( key ); +// +// String message = String.format( +// "%-12s %-7s Radius= %s (%s)\n %s", +// bomb.getName(), bomb.getExplosionShape(), Integer.toString(bomb.getRadius()), +// bomb.getItemType(), bomb.getDescription() ); +// +// sender.sendMessage( message ); +// } +// } + + + } + } + } + + public boolean isEnableMineBombs() { return enableMineBombs; } From 2690945898a347a13597facc2243ecb5ba22cf3b Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Thu, 23 Sep 2021 23:00:01 -0400 Subject: [PATCH 061/283] Able to give players bombs, based upon the item type as defined for the bomb. --- docs/changelog_v3.3.x.md | 5 +- .../tech/mcprison/prison/bombs/MineBombs.java | 15 +-- .../spigot/utils/PrisonUtilsMineBombs.java | 91 ++++++++++++++++++- 3 files changed, 100 insertions(+), 11 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 0d86e464c..c66fbd3de 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,10 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.1 2021-09-14 +# 3.2.11-alpha.1 2021-09-23 + + +* **Able to give players bombs, based upon the item type as defined for the bomb.** * **Significant progress on Prison's Mine Bombs:** diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java index 68918bc5a..8cb245cfd 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java @@ -130,7 +130,7 @@ public void setupDefaultMineBombData() mbDataSmall.setDescription("A small mine bomb made with some chemicals and a brewing stand."); MineBombData mbDataMedium = new MineBombData( - "MediumBomb", "fireworks", "sphere", 5, "Medium Mine Bomb" ); + "MediumBomb", "firework_rocket", "sphere", 5, "Medium Mine Bomb" ); mbDataMedium.setDescription("A medium mine bomb made from leftover fireworks, " + "but supercharged with a strange green glowing liquid."); @@ -141,22 +141,23 @@ public void setupDefaultMineBombData() "described as alien technology."); MineBombData mbDataOof = new MineBombData( - "OofBomb", "tnt_minecard", "sphereHollow", 19, "Oof Mine Bomb" ); + "OofBomb", "tnt_minecart", "sphereHollow", 19, "Oof Mine Bomb" ); mbDataOof.setDescription("An oof-ably large mine bomb made with a minecart heaping with TNT. " + "Unlike the large mine bomb, this one obviously is built with alien technology."); - getConfigData().getBombs().put( mbDataSmall.getName(), mbDataSmall ); - getConfigData().getBombs().put( mbDataMedium.getName(), mbDataMedium ); - getConfigData().getBombs().put( mbDataLarge.getName(), mbDataLarge ); - getConfigData().getBombs().put( mbDataOof.getName(), mbDataOof ); + getConfigData().getBombs().put( mbDataSmall.getName().toLowerCase(), mbDataSmall ); + getConfigData().getBombs().put( mbDataMedium.getName().toLowerCase(), mbDataMedium ); + getConfigData().getBombs().put( mbDataLarge.getName().toLowerCase(), mbDataLarge ); + getConfigData().getBombs().put( mbDataOof.getName().toLowerCase(), mbDataOof ); saveConfigJson(); Output.get().logInfo( "Mine bombs: setup default values." ); } else { - Output.get().logInfo( "Could not generate a mine bombs save file since at least one already exists." ); + Output.get().logInfo( "Could not generate a mine bombs save file since at least one " + + "mine bomb already exists." ); } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java index 218bf375f..ffd0fe244 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java @@ -6,14 +6,18 @@ import org.bukkit.Bukkit; +import com.cryptomorin.xseries.XMaterial; + import tech.mcprison.prison.bombs.MineBombData; import tech.mcprison.prison.bombs.MineBombs; import tech.mcprison.prison.commands.Arg; import tech.mcprison.prison.commands.Command; import tech.mcprison.prison.internal.CommandSender; +import tech.mcprison.prison.output.LogLevel; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.api.ExplosiveBlockBreakEvent; import tech.mcprison.prison.spigot.block.SpigotBlock; +import tech.mcprison.prison.spigot.block.SpigotItemStack; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.game.SpigotWorld; import tech.mcprison.prison.util.Location; @@ -154,11 +158,13 @@ public void utilsMineBombsList( CommandSender sender MineBombData bomb = mBombs.getConfigData().getBombs().get( key ); String message = String.format( - "%-12s %-7s Radius= %s (%s)\n %s", + "%-12s %-7s Radius= %s (%s)\n %s", bomb.getName(), bomb.getExplosionShape(), Integer.toString(bomb.getRadius()), bomb.getItemType(), bomb.getDescription() ); - sender.sendMessage( message ); +// sender.sendMessage( message ); + + Output.get().log( message, LogLevel.PLAIN ); } } @@ -175,7 +181,7 @@ public void utilsMineBombsGive( CommandSender sender, @Arg(name = "playerName", description = "Player name") String playerName, @Arg(name = "bombName", description = "The bomb name, or 'list' to show all available " + - "bombs. [round]", + "bombs. [list]", def = "list") String bombName, @Arg(name = "quantity", description = "Quantity of bombs to give. [1 > +]", def = "1" ) @@ -213,12 +219,91 @@ public void utilsMineBombsGive( CommandSender sender, return; } + int count = 1; count = Integer.parseInt( quantity ); MineBombs mBombs = MineBombs.getInstance(); + MineBombData bomb = mBombs.getConfigData().getBombs().get( bombName ); + + if ( bomb != null ) { + + XMaterial xBomb = XMaterial.matchXMaterial( bomb.getItemType() ).orElse( null ); + + if ( xBomb != null ) { + + SpigotItemStack bombs = new SpigotItemStack( xBomb.parseItem() ); + if ( bombs != null ) { + + bombs.setDisplayName( bomb.getName() ); + bombs.setAmount( count ); + + + List lore = bombs.getLore(); + + lore.add( "&4Prison Mine Bomb:" ); + lore.add( " &7" + bomb.getName() ); + lore.add( " " ); + + lore.add( "Size, Diameter: " + ( 1 + 2 * bomb.getRadius()) ); + lore.add( "Shape: " + bomb.getExplosionShape() ); + + String[] desc = bomb.getDescription().split( " " ); + StringBuilder sb = new StringBuilder(); + + for ( String d : desc ) { + + sb.append( d ).append( " " ); + + if ( sb.length() > 30 ) { + sb.insert( 0, " " ); + + lore.add( sb.toString() ); + sb.setLength( 0 ); + } + } + if ( sb.length() > 0 ) { + sb.insert( 0, " " ); + + lore.add( sb.toString() ); + } +// lore.add( " " + bomb.getDescription() ); + + lore.add( " " ); + + bombs.setLore( lore ); + + + player.getInventory().addItem( bombs ); + } + +// else { +// +// String message = "A mine bomb with the name of %s, is unable to generate an ItemStack. "; +// +// sender.sendMessage( String.format( message, bombName) ); +// } + + } + + else { + + String message = "A mine bomb with the name of %s, has an invalid itemType value. " + + "'%s' does not exist in the XMaterial types. Contact Prison support for help " + + "in finding the correct values to use. Google: 'XSeries XMaterial'"; + + sender.sendMessage( String.format( message, bombName, bomb.getItemType() ) ); + } + + } + + else { + String message = "A mine bomb with the name of %s does not exist."; + + sender.sendMessage( String.format( message, bombName ) ); + } // if ( "list".equalsIgnoreCase( bombName ) ) { // From cfb0ad16e4346ebeeb4f16aebc31a826826882a8 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sat, 25 Sep 2021 01:12:48 -0400 Subject: [PATCH 062/283] Add a new feature to the PrisonSpigotAPI to allow for the creation of a new mine through the API. This could be used to generate player mines in a plot world. --- docs/changelog_v3.3.x.md | 7 +- .../prison/spigot/api/PrisonSpigotAPI.java | 72 ++++++++++++++++++- 2 files changed, 77 insertions(+), 2 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index c66fbd3de..8426f751e 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,12 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.1 2021-09-23 +# 3.2.11-alpha.1 2021-09-25 + + +* **Add a new feature to the PrisonSpigotAPI to allow for the creation of a new mine through the API.** +This could be used to generate player mines in a plot world. + * **Able to give players bombs, based upon the item type as defined for the bomb.** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonSpigotAPI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonSpigotAPI.java index 2d2091b7a..9347363d9 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonSpigotAPI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonSpigotAPI.java @@ -6,6 +6,7 @@ import java.util.TreeMap; import org.bukkit.Material; +import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.event.block.BlockBreakEvent; @@ -18,17 +19,21 @@ import tech.mcprison.prison.mines.managers.MineManager; import tech.mcprison.prison.mines.managers.MineManager.MineSortOrder; import tech.mcprison.prison.modules.Module; +import tech.mcprison.prison.output.Output; import tech.mcprison.prison.ranks.PrisonRanks; import tech.mcprison.prison.ranks.data.Rank; import tech.mcprison.prison.ranks.data.RankPlayer; import tech.mcprison.prison.ranks.managers.PlayerManager; import tech.mcprison.prison.ranks.managers.RankManager; +import tech.mcprison.prison.selection.Selection; import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.backpacks.BackpacksUtil; import tech.mcprison.prison.spigot.block.SpigotBlock; import tech.mcprison.prison.spigot.game.SpigotPlayer; +import tech.mcprison.prison.spigot.game.SpigotWorld; import tech.mcprison.prison.spigot.sellall.SellAllUtil; import tech.mcprison.prison.util.BlockType; +import tech.mcprison.prison.util.Location; import tech.mcprison.prison.util.MaterialType; /** @@ -163,7 +168,7 @@ public String getPrisonBlockName( String blockName ) { } /** - *

Provides a list of all mines that contains the specfied block. + *

Provides a list of all mines that contains the specified block. *

* * @param prisonBlockName - The prison block name @@ -309,6 +314,71 @@ public Mine getPrisonMine( Player player, Block block, boolean isCanceledEvent) return results; } + /** + *

This creates a prison Location. It must include a valid world, and + * then the x, y, z coordinates. + *

+ * + * @param world + * @param x + * @param y + * @param z + * @return + */ + public Location createLocation( World world, int x, int y, int z ) { + Location results = null; + + if ( world != null ) { + + results = new Location( new SpigotWorld(world), x, y, z ); + } + return results; + } + + /** + *

This creates a mine at the given two coordinates. The provided tag + * value is optional. Minimal checks are performed. This checks to ensure the + * mines module is active, and a mine by the same name does not exist. + *

+ * + * @param mineName + * @param tag + * @param location1 + * @param location2 + * @return + */ + public boolean createMine( String mineName, String tag, + Location location1, Location location2 ) { + boolean results = false; + + if ( mineName != null && tag != null && location1 != null && location2 != null ) { + PrisonMines mm = getPrisonMineManager(); + if ( mm != null ) { + + if ( mm.getMine(mineName) != null) { + + String message = String.format( "Cannot create requested mine. " + + "Mine already exists by the name of '%s'.", + mineName); + Output.get().logError( message ); + + } + else { + Selection selection = new Selection( location1, location2 ); + + Mine mine = new Mine(mineName, selection); + + if ( tag != null ) { + mine.setTag( tag ); + } + + mm.getMineManager().add(mine); + } + } + } + + return results; + } private TreeMap getPlayerCache() { return getPrisonMineManager().getPlayerCache(); From f8151d0328b7c4c831cc6292f0a00324aebe5850 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 26 Sep 2021 12:02:32 -0400 Subject: [PATCH 063/283] Added a listener for PlayerInteractEvent. --- docs/changelog_v3.3.x.md | 5 ++++- .../java/tech/mcprison/prison/PrisonCommand.java | 7 ++++++- .../prison/internal/platform/Platform.java | 2 ++ .../java/tech/mcprison/prison/TestPlatform.java | 5 +++++ .../mcprison/prison/spigot/SpigotPlatform.java | 15 +++++++++++++++ 5 files changed, 32 insertions(+), 2 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 8426f751e..46e751281 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,10 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.1 2021-09-25 +# 3.2.11-alpha.1 2021-09-26 + + +* **Added a listener for PlayerInteractEvent.** * **Add a new feature to the PrisonSpigotAPI to allow for the creation of a new mine through the API.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java b/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java index e28d7cf16..9cf417f3f 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java +++ b/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java @@ -1473,7 +1473,7 @@ public void supportListenersDump(CommandSender sender, description = "Provides a detailed list of all registered event listeners for" + "the various event types. BlockBreak listeners will include all " + "listeners that are being monitored within auto features. " + - "[blockBreak, traceBlockBreak, chat]" + "[blockBreak, traceBlockBreak, chat, playerInteract]" ) String listener ) { @@ -1502,6 +1502,11 @@ public void supportListenersDump(CommandSender sender, return; } + if ( "playerInteract".equalsIgnoreCase( listener ) ) { + + results = Prison.get().getPlatform().dumpEventListenersPlayerInteractEvents(); + } + if ( results != null ) { for ( String line : results.split( "\n" ) ) { diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/platform/Platform.java b/prison-core/src/main/java/tech/mcprison/prison/internal/platform/Platform.java index ba68215d0..5b47f64b2 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/platform/Platform.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/platform/Platform.java @@ -370,6 +370,8 @@ public void autoCreateMineLinerAssignment( List rankMineNames, public void traceEventListenersBlockBreakEvents( CommandSender sender ); + public String dumpEventListenersPlayerInteractEvents(); + public void testPlayerUtil( UUID uuid ); diff --git a/prison-core/src/test/java/tech/mcprison/prison/TestPlatform.java b/prison-core/src/test/java/tech/mcprison/prison/TestPlatform.java index a0b2b64fe..789021ced 100644 --- a/prison-core/src/test/java/tech/mcprison/prison/TestPlatform.java +++ b/prison-core/src/test/java/tech/mcprison/prison/TestPlatform.java @@ -361,6 +361,11 @@ public void traceEventListenersBlockBreakEvents( CommandSender sender ) { } + @Override + public String dumpEventListenersPlayerInteractEvents() { + return ""; + } + @Override public void testPlayerUtil( UUID uuid ) { diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java index e33f11467..3238d249d 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java @@ -42,6 +42,7 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.player.AsyncPlayerChatEvent; import org.bukkit.event.player.PlayerChatEvent; +import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.RegisteredListener; @@ -2138,6 +2139,20 @@ public String dumpEventListenersPlayerChatEvents() { return sb.toString(); } + @Override + public String dumpEventListenersPlayerInteractEvents() { + StringBuilder sb = new StringBuilder(); + + ChatDisplay eventDisplay = dumpEventListenersChatDisplay( + "PlayerInteractEvent", + new SpigotHandlerList( PlayerInteractEvent.getHandlerList()) ); + if ( eventDisplay != null ) { + sb.append( eventDisplay.toStringBuilder() ); + } + + return sb.toString(); + } + /** *

Some information on events... *

From a7d8653e9df6909e70b8cd004c6cf8e7c5c4a242 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 26 Sep 2021 12:10:41 -0400 Subject: [PATCH 064/283] Mine Bombs: Initial setup of placing bombs to activate them. Not yet functional. --- .../mcprison/prison/bombs/MineBombData.java | 18 + .../tech/mcprison/prison/bombs/MineBombs.java | 26 +- .../spigot/api/ExplosiveBlockBreakEvent.java | 10 + .../spigot/utils/PrisonBombListener.java | 100 +++++ .../spigot/utils/PrisonUtilsMineBombs.java | 358 +++++++++++++++--- .../spigot/utils/PrisonUtilsModule.java | 6 + 6 files changed, 460 insertions(+), 58 deletions(-) create mode 100644 prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java index 3edc31be7..c3cfc1bef 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java @@ -47,6 +47,9 @@ public class MineBombData { private String description; + private boolean activated = false; + + public MineBombData() { super(); @@ -74,6 +77,14 @@ public MineBombData( String name, String itemType, String explosionShape, } + public MineBombData clone() { + MineBombData cloned = new MineBombData( getName(), getItemType(), getExplosionShape(), + getRadius() ); + for ( String l : lore ) { + cloned.getLore().add( l ); + } + return cloned; + } public String getName() { return name; @@ -123,5 +134,12 @@ public String getDescription() { public void setDescription( String description ) { this.description = description; } + + public boolean isActivated() { + return activated; + } + public void setActivated( boolean activated ) { + this.activated = activated; + } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java index 8cb245cfd..df38267a9 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java @@ -15,7 +15,7 @@ public class MineBombs private static MineBombs instance; - private MineBombsConfigData configData; + private final MineBombsConfigData configData; @@ -46,6 +46,27 @@ public static MineBombs getInstance() { return instance; } + /** + *

This finds a bomb with the given name, and returns a clone. The clone is + * important since individual instances will set the isActivated() variable to + * true if the bomb is active. If it's activated, then that indicates the + * bomb will be used and the bomb was removed from the player's inventory. + *

+ * + * @param bombName + * @return + */ + public MineBombData findBomb( String bombName ) { + MineBombData bombOriginal = null; + + if ( bombName != null ) { + + bombOriginal = getConfigData().getBombs().get( bombName.toLowerCase() ); + } + + return bombOriginal.clone(); + } + public void saveConfigJson() { JsonFileIO fio = new JsonFileIO( null, null ); @@ -165,8 +186,5 @@ public void setupDefaultMineBombData() public MineBombsConfigData getConfigData() { return configData; } - public void setConfigData( MineBombsConfigData configData ) { - this.configData = configData; - } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/ExplosiveBlockBreakEvent.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/ExplosiveBlockBreakEvent.java index b2543ff78..8301952c2 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/ExplosiveBlockBreakEvent.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/ExplosiveBlockBreakEvent.java @@ -9,6 +9,8 @@ import org.bukkit.event.HandlerList; import org.bukkit.event.block.BlockBreakEvent; +import tech.mcprison.prison.bombs.MineBombData; + /** *

This is an example of an explosive event that should be used for * enchantments that will break more than one block at a time. @@ -50,6 +52,7 @@ public class ExplosiveBlockBreakEvent private String triggeredBy; + private MineBombData mineBomb; public ExplosiveBlockBreakEvent( Block theBlock, Player player, List explodedBlocks, String triggeredBy ) { @@ -104,6 +107,13 @@ public void setTriggeredBy( String triggeredBy ) { this.triggeredBy = triggeredBy; } + public MineBombData getMineBomb() { + return mineBomb; + } + public void setMineBomb( MineBombData mineBomb ) { + this.mineBomb = mineBomb; + } + @Override public HandlerList getHandlers(){ return handlers; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java new file mode 100644 index 000000000..e40c5c899 --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java @@ -0,0 +1,100 @@ +package tech.mcprison.prison.spigot.utils; + +import java.text.DecimalFormat; + +import org.bukkit.entity.Item; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; + +import tech.mcprison.prison.bombs.MineBombData; +import tech.mcprison.prison.spigot.block.SpigotBlock; +import tech.mcprison.prison.spigot.block.SpigotItemStack; +import tech.mcprison.prison.spigot.game.SpigotPlayer; + +/** + *

This listener class handles the player's interaction with using a bomb. + * + *

+ * + *

Some of the inspiration for the handling of player's bomb was found in the + * following open source project: + * https://github.com/hpfxd/bombs/blob/master/src/main/java/xyz/tooger/bombs/BombListener.java + * + *

+ */ +public class PrisonBombListener + implements Listener +{ + + @EventHandler( priority = EventPriority.LOW ) + public void onInteract(PlayerInteractEvent event) { + if ( !event.getPlayer().hasPermission("prison.minebombs.use") ) { + return; + } + + if ( event.getAction().equals(Action.RIGHT_CLICK_BLOCK) || event.getAction().equals(Action.RIGHT_CLICK_AIR) ) { + + // If the player is holding a mine bomb, then get the bomb and decrease the + // ItemStack in the player's hand by 1: + MineBombData bomb = PrisonUtilsMineBombs.getBombInHand( event.getPlayer() ); + + if ( bomb != null ) { + + Player player = event.getPlayer(); + + SpigotPlayer sPlayer = new SpigotPlayer( player ); + + // if the bomb is not activated, then that indicates that the players is + // under a cooldown and the bomb cannot be used, nor has it been removed from their + // inventory. + if ( bomb.isActivated() ) { + + + SpigotItemStack bombs = PrisonUtilsMineBombs.getItemStackBomb( bomb ); + + if ( bombs != null ) { + + SpigotBlock sBlock = new SpigotBlock( event.getClickedBlock() ); + + + int throwSpeed = 2; + + final Item dropped = player.getWorld().dropItem(player.getLocation(), bombs.getBukkitStack() ); + dropped.setVelocity(player.getLocation().getDirection().multiply( throwSpeed ).normalize() ); + dropped.setPickupDelay( 50000 ); + + + PrisonUtilsMineBombs.setoffBombDelayed( sPlayer, bomb, dropped, sBlock, throwSpeed ); + + } + } + else { + + String playerUUID = player.getUniqueId().toString(); + int cooldownTicks = PrisonUtilsMineBombs.checkPlayerCooldown( playerUUID ); + float cooldownSeconds = cooldownTicks / 2.0f; + DecimalFormat dFmt = new DecimalFormat( "0.0" ); + + String message = + String.format( "You cannot use another Prison Mine Bomb for %s seconds.", + dFmt.format( cooldownSeconds ) ); + sPlayer.sendMessage( message ); + } + + } + + else { + + // Do nothing since this means the event is not Prison Mine Bomb related. + } + + + + + } + } +} diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java index ffd0fe244..a195b6abc 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java @@ -2,9 +2,14 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.TreeMap; import org.bukkit.Bukkit; +import org.bukkit.entity.Item; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; import com.cryptomorin.xseries.XMaterial; @@ -15,9 +20,11 @@ import tech.mcprison.prison.internal.CommandSender; import tech.mcprison.prison.output.LogLevel; import tech.mcprison.prison.output.Output; +import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.api.ExplosiveBlockBreakEvent; import tech.mcprison.prison.spigot.block.SpigotBlock; import tech.mcprison.prison.spigot.block.SpigotItemStack; +import tech.mcprison.prison.spigot.compat.SpigotCompatibility; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.game.SpigotWorld; import tech.mcprison.prison.util.Location; @@ -25,8 +32,14 @@ public class PrisonUtilsMineBombs extends PrisonUtils { + public static final String MINE_BOMBS_LORE_1 = "&4Prison Mine Bomb:"; + public static final String MINE_BOMBS_LORE_2_PREFIX = " &7"; + public static final int MINE_BOMBS_COOLDOWN_TICKS = 15 * 20; // 15 seconds + private boolean enableMineBombs = false; + public static final Map playerCooldowns = new TreeMap<>(); + public PrisonUtilsMineBombs() { super(); @@ -230,64 +243,14 @@ public void utilsMineBombsGive( CommandSender sender, if ( bomb != null ) { - XMaterial xBomb = XMaterial.matchXMaterial( bomb.getItemType() ).orElse( null ); + SpigotItemStack bombs = getItemStackBomb( bomb ); - if ( xBomb != null ) { - - SpigotItemStack bombs = new SpigotItemStack( xBomb.parseItem() ); - if ( bombs != null ) { - - bombs.setDisplayName( bomb.getName() ); - bombs.setAmount( count ); - - - List lore = bombs.getLore(); - - lore.add( "&4Prison Mine Bomb:" ); - lore.add( " &7" + bomb.getName() ); - lore.add( " " ); - - lore.add( "Size, Diameter: " + ( 1 + 2 * bomb.getRadius()) ); - lore.add( "Shape: " + bomb.getExplosionShape() ); - - String[] desc = bomb.getDescription().split( " " ); - StringBuilder sb = new StringBuilder(); - - for ( String d : desc ) { - - sb.append( d ).append( " " ); - - if ( sb.length() > 30 ) { - sb.insert( 0, " " ); - - lore.add( sb.toString() ); - sb.setLength( 0 ); - } - } - if ( sb.length() > 0 ) { - sb.insert( 0, " " ); - - lore.add( sb.toString() ); - } -// lore.add( " " + bomb.getDescription() ); - - lore.add( " " ); - - bombs.setLore( lore ); - - - player.getInventory().addItem( bombs ); - } + if ( bombs != null ) { -// else { -// -// String message = "A mine bomb with the name of %s, is unable to generate an ItemStack. "; -// -// sender.sendMessage( String.format( message, bombName) ); -// } + bombs.setAmount( count ); + player.getInventory().addItem( bombs ); } - else { String message = "A mine bomb with the name of %s, has an invalid itemType value. " + @@ -297,6 +260,73 @@ public void utilsMineBombsGive( CommandSender sender, sender.sendMessage( String.format( message, bombName, bomb.getItemType() ) ); } +// XMaterial xBomb = XMaterial.matchXMaterial( bomb.getItemType() ).orElse( null ); +// +// if ( xBomb != null ) { +// +// SpigotItemStack bombs = new SpigotItemStack( xBomb.parseItem() ); +// if ( bombs != null ) { +// +// bombs.setDisplayName( bomb.getName() ); +// bombs.setAmount( count ); +// +// +// List lore = bombs.getLore(); +// +// lore.add( MINE_BOMBS_LORE_1 ); +// lore.add( MINE_BOMBS_LORE_2_PREFIX + bomb.getName() ); +// lore.add( " " ); +// +// lore.add( "Size, Diameter: " + ( 1 + 2 * bomb.getRadius()) ); +// lore.add( "Shape: " + bomb.getExplosionShape() ); +// +// String[] desc = bomb.getDescription().split( " " ); +// StringBuilder sb = new StringBuilder(); +// +// for ( String d : desc ) { +// +// sb.append( d ).append( " " ); +// +// if ( sb.length() > 30 ) { +// sb.insert( 0, " " ); +// +// lore.add( sb.toString() ); +// sb.setLength( 0 ); +// } +// } +// if ( sb.length() > 0 ) { +// sb.insert( 0, " " ); +// +// lore.add( sb.toString() ); +// } +//// lore.add( " " + bomb.getDescription() ); +// +// lore.add( " " ); +// +// bombs.setLore( lore ); +// +// +// player.getInventory().addItem( bombs ); +// } +// +//// else { +//// +//// String message = "A mine bomb with the name of %s, is unable to generate an ItemStack. "; +//// +//// sender.sendMessage( String.format( message, bombName) ); +//// } +// +// } + +// else { +// +// String message = "A mine bomb with the name of %s, has an invalid itemType value. " + +// "'%s' does not exist in the XMaterial types. Contact Prison support for help " + +// "in finding the correct values to use. Google: 'XSeries XMaterial'"; +// +// sender.sendMessage( String.format( message, bombName, bomb.getItemType() ) ); +// } + } else { @@ -326,7 +356,227 @@ public void utilsMineBombsGive( CommandSender sender, } } + + public static SpigotItemStack getItemStackBomb( MineBombData bomb ) { + SpigotItemStack bombs = null; + + XMaterial xBomb = XMaterial.matchXMaterial( bomb.getItemType() ).orElse( null ); + + if ( xBomb != null ) { + + bombs = new SpigotItemStack( xBomb.parseItem() ); + if ( bombs != null ) { + + bombs.setDisplayName( bomb.getName() ); + //bombs.setAmount( count ); + + + List lore = bombs.getLore(); + + lore.add( MINE_BOMBS_LORE_1 ); + lore.add( MINE_BOMBS_LORE_2_PREFIX + bomb.getName() ); + lore.add( " " ); + + lore.add( "Size, Diameter: " + ( 1 + 2 * bomb.getRadius()) ); + lore.add( "Shape: " + bomb.getExplosionShape() ); + + String[] desc = bomb.getDescription().split( " " ); + StringBuilder sb = new StringBuilder(); + + for ( String d : desc ) { + + sb.append( d ).append( " " ); + + if ( sb.length() > 30 ) { + sb.insert( 0, " " ); + + lore.add( sb.toString() ); + sb.setLength( 0 ); + } + } + if ( sb.length() > 0 ) { + sb.insert( 0, " " ); + + lore.add( sb.toString() ); + } +// lore.add( " " + bomb.getDescription() ); + + lore.add( " " ); + + bombs.setLore( lore ); + + } + + } + + return bombs; + } + + + /** + *

This takes a player and checks their main hand to see if it contains a bomb. + * If it does, then it return the selected bomb, and it reduces the quantity by + * one. + *

+ * + * @param player + * @return + */ + public static MineBombData getBombInHand( Player player ) { + MineBombData results = null; + + SpigotItemStack itemInHand = SpigotCompatibility.getInstance().getPrisonItemInMainHand( player ); + + if ( itemInHand != null ) { + List lore = itemInHand.getLore(); + + if ( lore.size() > 1 && + lore.get( 0 ).equalsIgnoreCase( MINE_BOMBS_LORE_1 ) && + lore.get( 1 ).startsWith( MINE_BOMBS_LORE_2_PREFIX )) { + + String bombName = lore.get( 1 ).replace( MINE_BOMBS_LORE_2_PREFIX, "" ); + + MineBombs mBombs = MineBombs.getInstance(); + + results = mBombs.findBomb( bombName ); + + String playerUUID = player.getUniqueId().toString(); + + if ( results != null && + checkPlayerCooldown( playerUUID ) == 0 ) { + + // Setting activated to true indicates the bomb is live and it has + // been removed from the player's inventory: + results.setActivated( true ); + itemInHand.setAmount( itemInHand.getAmount() - 1 ); + + // Remove from inventory: + SpigotCompatibility.getInstance().setItemInMainHand( player, itemInHand.getBukkitStack() ); + + // Set cooldown: + PrisonUtilsMineBombs.addPlayerCooldown( playerUUID ); + } + } + } + + return results; + } + + public static boolean addPlayerCooldown( String playerUUID ) { + return addPlayerCooldown( playerUUID, MINE_BOMBS_COOLDOWN_TICKS ); + } + + /** + *

If a cooldown is not setup for the player, this will try to add one and + * will return a value of true to indicate the a cooldown was set. If a cooldown + * already exists, then this will return a value of false. + *

+ * + * @param playerUUID + * @param ticks + * @return + */ + public static boolean addPlayerCooldown( String playerUUID, int ticks ) { + boolean results = false; + + if ( !playerCooldowns.containsKey( playerUUID ) || + playerCooldowns.get( playerUUID ) <= 0 ) { + + playerCooldowns.put( playerUUID, ticks ); + + new BukkitRunnable() { + + @Override + public void run() { + + int ticksRemaining = playerCooldowns.get( playerUUID ) - 10; + + if ( ticksRemaining <= 0 ) { + playerCooldowns.remove( playerUUID ); + this.cancel(); + } + else { + playerCooldowns.put( playerUUID, ticksRemaining ); + } + + } + }.runTaskTimer( SpigotPrison.getInstance(), 10, 10); + + results = true; + } + + return results; + } + + public static int checkPlayerCooldown( String playerUUID ) { + int results = 0; + + if ( playerCooldowns.containsKey( playerUUID ) ) { + results = playerCooldowns.get( playerUUID ); + } + + return results; + } + public static boolean setoffBombDelayed( SpigotPlayer sPlayer, MineBombData bomb, Item droppedBomb, + SpigotBlock sBlock, int delayTicks ) { + boolean results = false; + + new BukkitRunnable() { + + @Override + public void run() { + + // Remove the item that the player threw: + droppedBomb.remove(); + + Location location = sBlock.getLocation(); + SpigotWorld world = (SpigotWorld) location.getWorld(); + + MineBombs mBombs = MineBombs.getInstance(); + + // Calculate all the locations that are included in the explosion: + List blockLocations = mBombs.calculateSphere( location, + bomb.getRadius(), false ); + + + // Convert to spigot blocks: + List blocks = new ArrayList<>(); + for ( Location bLocation : blockLocations ) { + SpigotBlock sBlock = (SpigotBlock) world.getBlockAt( bLocation ); + if ( !sBlock.isEmpty() ) { + + blocks.add( sBlock.getWrapper() ); + } + } + + + SpigotBlock targetBlock = (SpigotBlock) world.getBlockAt( location ); + + + ExplosiveBlockBreakEvent explodeEvent = new ExplosiveBlockBreakEvent( + targetBlock.getWrapper(), sPlayer.getWrapper(), blocks ); + explodeEvent.setTriggeredBy( bomb.getName() ); + explodeEvent.setMineBomb( bomb ); + + Bukkit.getServer().getPluginManager().callEvent( explodeEvent ); + + + + } + }.runTaskLater( SpigotPrison.getInstance(), delayTicks ); + + //.runTaskTimer( SpigotPrison.getInstance(), 10, 10); + + return results; + } + + public static double getPlayerCoolDownRemaining() + { + + return 0; + } + public boolean isEnableMineBombs() { return enableMineBombs; } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsModule.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsModule.java index 1d4c78f7c..7cb23f1da 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsModule.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsModule.java @@ -1,9 +1,11 @@ package tech.mcprison.prison.spigot.utils; +import org.bukkit.Bukkit; import org.bukkit.configuration.file.YamlConfiguration; import tech.mcprison.prison.Prison; import tech.mcprison.prison.modules.Module; +import tech.mcprison.prison.spigot.SpigotPrison; public class PrisonUtilsModule extends Module @@ -130,6 +132,10 @@ public void enable() { Prison.get().getCommandHandler().registerCommands( utils ); + // Only Register the Bomb Listener if bombs are active: + Bukkit.getPluginManager().registerEvents( + new PrisonBombListener(), SpigotPrison.getInstance()); + } } From 85fd9d86a367c2d6aacb559ed422efc0115c8fa5 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 26 Sep 2021 12:13:29 -0400 Subject: [PATCH 065/283] Fortune on a tool was appearing as a negative value: -1000. Not sure how it became negative, but this will better deal with negative values. --- docs/changelog_v3.3.x.md | 4 ++++ .../prison/spigot/autofeatures/AutoManagerFeatures.java | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 46e751281..a61c82078 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-09-26 +* **Fortune on a tool was appearing as a negative value: -1000.** +Not sure how it became negative, but this will better deal with negative values. + + * **Added a listener for PlayerInteractEvent.** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java index 6990766ed..6c0ad34d7 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java @@ -143,7 +143,7 @@ protected short getFortune(SpigotItemStack itemInHand){ } int maxFortuneLevel = getInteger( AutoFeatures.fortuneMultiplierMax ); - if ( maxFortuneLevel != 0 && results > maxFortuneLevel ) { + if ( maxFortuneLevel > 0 && results > maxFortuneLevel ) { results = (short) maxFortuneLevel; } From aeb4983da7ec3f4e9d93efdbdde8453e4393f5c2 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 26 Sep 2021 12:14:20 -0400 Subject: [PATCH 066/283] Upgrade XSeries to v8.4.0 to help prepare for spigot v1.18.x. --- prison-spigot/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prison-spigot/build.gradle b/prison-spigot/build.gradle index 388480ab2..322701478 100644 --- a/prison-spigot/build.gradle +++ b/prison-spigot/build.gradle @@ -105,7 +105,7 @@ dependencies { // implementation 'com.github.cryptomorin:xseries:b95d195482' // https://mvnrepository.com/artifact/com.github.cryptomorin/XSeries - implementation 'com.github.cryptomorin:XSeries:8.3.0' + implementation 'com.github.cryptomorin:XSeries:8.4.0' @@ -187,7 +187,7 @@ shadowJar { include(dependency('me.clip:placeholderapi:2.10.9')) - include(dependency('com.github.cryptomorin:XSeries:8.3.0')) + include(dependency('com.github.cryptomorin:XSeries:8.4.0')) //include(dependency('org.inventivetalent.spiget-update:bukkit:1.4.2-SNAPSHOT')) //include(dependency('me.badbones69:crazyenchantments-plugin:1.8-Dev-Build-v8')) From e3f1e57f5e82c530222d98987d208d93d564501b Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 26 Sep 2021 12:51:17 -0400 Subject: [PATCH 067/283] New auto features settings: Able to prevent event canceling and also control if the drops are cleared. This has not been tested too much, but it may help make prison more compatible with other plugins that are needing to handle the block break events. --- docs/changelog_v3.3.x.md | 4 ++++ .../autofeatures/AutoFeaturesFileConfig.java | 18 +++++++++++------- .../mcprison/prison/spigot/SpigotUtil.java | 6 ++++++ .../autofeatures/AutoManagerFeatures.java | 18 +++++++++++++++--- .../spigot/block/OnBlockBreakEventCore.java | 10 +++++----- .../prison/spigot/block/SpigotBlock.java | 14 +++++++++++++- 6 files changed, 54 insertions(+), 16 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index a61c82078..d918a2d11 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-09-26 +* **New auto features settings: Able to prevent event canceling and also control if the drops are cleared.** +This has not been tested too much, but it may help make prison more compatible with other plugins that are needing to handle the block break events. + + * **Fortune on a tool was appearing as a negative value: -1000.** Not sure how it became negative, but this will better deal with negative values. diff --git a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java index e236f8faa..9ee1a04df 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java +++ b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java @@ -49,7 +49,11 @@ public enum AutoFeatures { blockBreakEvents(options), - blockBreakEventPriority(blockBreakEvents, "LOW"), + cancelAllBlockBreakEvents(blockBreakEvents, true), + cancelAllBlockEventBlockDrops(blockBreakEvents, true), + + + blockBreakEventPriority(blockBreakEvents, "LOW"), isProcessTokensEnchantExplosiveEvents(blockBreakEvents, false), TokenEnchantBlockExplodeEventPriority(blockBreakEvents, "DISABLED"), @@ -232,12 +236,12 @@ public enum AutoFeatures { - debug(options), - isDebugSupressOnBlockBreakEventCancels(debug, false), - isDebugSupressOnTEExplodeEventCancels(debug, false), - isDebugSupressOnCEBlastUseEventCancels(debug, false), - isDebugSupressOnPEExplosiveEventCancels(debug, false), - isDebugSupressOnPrisonMinesBlockBreakEventCancels(debug, false) +// debug(options), +// isDebugSupressOnBlockBreakEventCancels(debug, false), +// isDebugSupressOnTEExplodeEventCancels(debug, false), +// isDebugSupressOnCEBlastUseEventCancels(debug, false), +// isDebugSupressOnPEExplosiveEventCancels(debug, false), +// isDebugSupressOnPrisonMinesBlockBreakEventCancels(debug, false) ; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotUtil.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotUtil.java index c93b150fe..4f1822830 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotUtil.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotUtil.java @@ -1017,6 +1017,12 @@ public static List getDrops(SpigotBlock block, SpigotItemStack return ret; } + +// public static void clearDrops(SpigotBlock block) { +// +// block.getWrapper().getDrops().clear();; +// } + /* * InventoryType */ diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java index 6c0ad34d7..c52c9e03d 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java @@ -23,7 +23,6 @@ import tech.mcprison.prison.Prison; import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; -import tech.mcprison.prison.autofeatures.PlayerMessaging.MessageType; import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.mines.features.MineBlockEvent.BlockEventType; @@ -38,7 +37,6 @@ import tech.mcprison.prison.spigot.compat.SpigotCompatibility; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.sellall.SellAllUtil; -import tech.mcprison.prison.spigot.utils.tasks.PlayerMessagingTask; import tech.mcprison.prison.util.BlockType; import tech.mcprison.prison.util.Text; @@ -426,6 +424,13 @@ protected int autoPickup( Player player, List drops = new ArrayList<>( SpigotUtil.getDrops(block, itemInHand) ); + // This clears the drops for the given block, so if the event is not canceled, it will + // not result in duplicate drops. + if ( isBoolean( AutoFeatures.cancelAllBlockEventBlockDrops ) ) { + block.clearDrops(); + } + + if (drops != null && drops.size() > 0 ) { // Need better drop calculation that is not using the getDrops function. @@ -499,7 +504,14 @@ public int calculateNormalDrop( SpigotItemStack itemInHand, SpigotBlock block ) // plus there are some extra items, such as flint, that will never be dropped. List drops = new ArrayList<>( SpigotUtil.getDrops(block, itemInHand) ); - + + // This clears the drops for the given block, so if the event is not canceled, it will + // not result in duplicate drops. + if ( isBoolean( AutoFeatures.cancelAllBlockEventBlockDrops ) ) { + block.clearDrops(); + } + + if (drops != null && drops.size() > 0 ) { // Need better drop calculation that is not using the getDrops function. diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index 4f0b6d14f..ff79959b7 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -423,7 +423,7 @@ else if ( pmEvent.getMine() != null || pmEvent.getMine() == null && // doAction returns a boolean that indicates if the event should be canceled or not: if ( doAction( sBlock, pmEvent.getMine(), pmEvent.getPlayer(), debugInfo ) ) { - if ( !isBoolean( AutoFeatures.isDebugSupressOnBlockBreakEventCancels ) ) { + if ( !isBoolean( AutoFeatures.cancelAllBlockBreakEvents ) ) { e.setCancelled( true ); } else { @@ -910,7 +910,7 @@ else if ( isTEExplosiveEnabled && if ( doAction( pmEvent.getMine(), pmEvent.getPlayer(), pmEvent.getExplodedBlocks(), BlockEventType.TEXplosion, triggered, debugInfo ) ) { - if ( !isBoolean( AutoFeatures.isDebugSupressOnTEExplodeEventCancels ) ) { + if ( !isBoolean( AutoFeatures.cancelAllBlockBreakEvents ) ) { e.setCancelled( true ); } @@ -1288,7 +1288,7 @@ else if ( isCEBlockExplodeEnabled && if ( doAction( pmEvent.getMine(), e.getPlayer(), pmEvent.getExplodedBlocks(), BlockEventType.CEXplosion, triggered, debugInfo ) ) { - if ( !isBoolean( AutoFeatures.isDebugSupressOnCEBlastUseEventCancels ) ) { + if ( !isBoolean( AutoFeatures.cancelAllBlockBreakEvents ) ) { e.setCancelled( true ); } @@ -1413,7 +1413,7 @@ else if ( isPEExplosiveEnabled && if ( doAction( pmEvent.getMine(), e.getPlayer(), pmEvent.getExplodedBlocks(), BlockEventType.PEExplosive, triggered, debugInfo ) ) { - if ( !isBoolean( AutoFeatures.isDebugSupressOnPEExplosiveEventCancels ) ) { + if ( !isBoolean( AutoFeatures.cancelAllBlockBreakEvents ) ) { e.setCancelled( true ); } @@ -1511,7 +1511,7 @@ else if ( isPPrisonExplosiveBlockBreakEnabled && if ( doAction( pmEvent.getMine(), e.getPlayer(), pmEvent.getExplodedBlocks(), BlockEventType.PrisonExplosion, triggered, debugInfo ) ) { - if ( !isBoolean( AutoFeatures.isDebugSupressOnPrisonMinesBlockBreakEventCancels ) ) { + if ( !isBoolean( AutoFeatures.cancelAllBlockBreakEvents ) ) { e.setCancelled( true ); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java index de8aa83f2..c78e6383d 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java @@ -296,7 +296,8 @@ public void setType(BlockType blockType) { return results; } - @Override public List getDrops() { + @Override + public List getDrops() { List ret = new ArrayList<>(); if ( getWrapper() != null ) { @@ -322,6 +323,17 @@ public List getDrops(ItemStack tool) { return ret; } + /** + *

This clears the drops for the given block, so if the event is not canceled, it will + * not result in duplicate drops. + *

+ */ + public void clearDrops() { + + getWrapper().getDrops().clear(); + } + + // public List getDrops(SpigotItemStack tool) { // List ret = new ArrayList<>(); // From b20cbe65f8b9420a58134dbde8f8d9c068c869f6 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 26 Sep 2021 12:53:04 -0400 Subject: [PATCH 068/283] Removal of some auto feature commented out old code. --- docs/changelog_v3.3.x.md | 3 + .../spigot/block/OnBlockBreakEventCore.java | 402 +----------------- 2 files changed, 4 insertions(+), 401 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index d918a2d11..8160c2906 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-09-26 +* **Removal of some auto feature commented out old code.** + + * **New auto features settings: Able to prevent event canceling and also control if the drops are cleared.** This has not been tested too much, but it may help make prison more compatible with other plugins that are needing to handle the block break events. diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index ff79959b7..a7e63263a 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -328,71 +328,6 @@ protected void genericBlockEvent( BlockBreakEvent e, boolean monitor, boolean bl } } -// boolean isAir = e.getBlock().getType() == null || e.getBlock().getType() == Material.AIR; - - -// Long playerUUIDLSB = Long.valueOf( pmEvent.getPlayer().getUniqueId().getLeastSignificantBits() ); -// -// // Get the cached mine, if it exists: -// Mine mine = getPlayerCache().get( playerUUIDLSB ); -// -// if ( mine == null || !mine.isInMineExact( pmEvent.getSpigotBlock().getLocation() ) ) { -// // Look for the correct mine to use. -// // Set mine to null so if cannot find the right one it will return a null: -// mine = findMineLocation( pmEvent.getSpigotBlock() ); -// -// // Store the mine in the player cache if not null: -// if ( mine != null ) { -// getPlayerCache().put( playerUUIDLSB, mine ); -// } -// } -// pmEvent.setMine( mine ); -// -// debugInfo.append( "mine=" + (mine == null ? "none" : mine.getName()) + " " ); -// -// -// if ( isToolDisabled( e.getPlayer() ) ) { -// -// PrisonUtilsTitles uTitles = new PrisonUtilsTitles(); -// uTitles.utilsTitlesActionBar( pmEvent.getSpigotPlayer(), "", -// "&cYour tool is worn-out and cannot be used." ); -// -// e.setCancelled( true ); -// debugInfo.append( "UNUSABLE_TOOL__WORN_OUT (event canceled) " ); -// } -// else if ( mine != null && BlockUtils.getInstance().isUnbreakable( sBlock ) ) { -// // The block is unbreakable because a utility has it locked: -// -// e.setCancelled( true ); -// debugInfo.append( "UNBREAKABLE_BLOCK_UTILS (event canceled) " ); -// } -// else if ( mine != null && (mine.isMineAccessByRank() || mine.isAccessPermissionEnabled()) && -// !mine.hasMiningAccess( pmEvent.getSpigotPlayer() ) ) { -// // The player does not have permission to access this mine, so do not process -// // -// -// e.setCancelled( true ); -// debugInfo.append( "ACCESS_DENIED (event canceled) " ); -// } -// else if ( blockEventsOnly ) { -// -// String triggered = null; -// -// doActionBlockEventOnly( sBlock, mine, e.getPlayer(), BlockEventType.blockBreak, triggered ); -// -// debugInfo.append( "(actionBlockEventOnly) " ); -// } -// else if ( monitor && mine == null ) { -// // bypass all processing since the block break is outside any mine: -// -// debugInfo.append( "(bypassed monitor no mine) " ); -// } -// else if ( monitor && mine != null ) { -// -// doActionMonitor( sBlock, mine ); -// -// debugInfo.append( "(monitor) " ); -// } // This is where the processing actually happens: else if ( pmEvent.getMine() != null || pmEvent.getMine() == null && @@ -705,157 +640,6 @@ private void genericBlockExplodeEvent( TEBlockExplodeEvent e, boolean monitor, b } } - -// List explodedBlocks = new ArrayList<>(); - -// // Need to wrap in a Prison block so it can be used with the mines: -// SpigotBlock block = new SpigotBlock(e.getBlock()); -// -// // long startNano = System.nanoTime(); -// Long playerUUIDLSB = Long.valueOf( e.getPlayer().getUniqueId().getLeastSignificantBits() ); -// -// // Get the cached mine, if it exists: -// Mine mine = getPlayerCache().get( playerUUIDLSB ); -// -// if ( mine == null || !mine.isInMineExact( block.getLocation() ) ) { -// -// -// // Look for the correct mine to use. -// // Set mine to null so if cannot find the right one it will return a null: -// mine = findMineLocation( block ); -// -// // Store the mine in the player cache if not null: -// if ( mine != null ) { -// getPlayerCache().put( playerUUIDLSB, mine ); -// -// // we found the mine! -// } -// -// } -// -// debugInfo.append( "mine=" + (mine == null ? "none" : mine.getName()) + " " ); - - -// if ( isToolDisabled( e.getPlayer() ) ) { -// -// PrisonUtilsTitles uTitles = new PrisonUtilsTitles(); -// uTitles.utilsTitlesActionBar( new SpigotPlayer( e.getPlayer() ), "", -// "&cYour tool is worn-out and cannot be used." ); -// -// e.setCancelled( true ); -// debugInfo.append( "UNUSABLE_TOOL__WORN_OUT (event canceled) " ); -// } -// else if ( mine != null && BlockUtils.getInstance().isUnbreakable( block ) ) { -// // The block is unbreakable because a utility has it locked: -// -// e.setCancelled( true ); -// debugInfo.append( "UNBREAKABLE_BLOCK_UTILS (event canceled) " ); -// } -// else if ( mine != null && (mine.isMineAccessByRank() || mine.isAccessPermissionEnabled()) && -// !mine.hasMiningAccess( new SpigotPlayer( e.getPlayer() ) ) ) { -// // The player does not have permission to access this mine, so do not process -// // -// -// e.setCancelled( true ); -// debugInfo.append( "ACCESS_DENIED (event canceled) " ); -// } -// else if ( blockEventsOnly ) { -// int unbreakable = 0; -// int outsideOfMine = 0; -// -// if ( mine != null ) { -// -// String triggered = null; -// -// // This was already checked to ensure it's breakable: -// doActionBlockEventOnly( block, mine, e.getPlayer(), BlockEventType.blockBreak, triggered ); -// -// // All other blocks in the explosion: -// for ( Block blk : e.blockList() ) { -// -// // Need to wrap in a Prison block so it can be used with the mines. -// // Since this is a monitor, there is no need to check to see if the -// // block is in a mine since the getTargetPrisonBlock function will -// // perform that check indirectly. -// SpigotBlock sBlock = new SpigotBlock(blk); -// -// if ( BlockUtils.getInstance().isUnbreakable( sBlock ) ) { -// -// unbreakable++; -// } -// else if ( mine.isInMineExact( sBlock.getLocation() ) ) { -// -// doActionBlockEventOnly( sBlock, mine, e.getPlayer(), BlockEventType.blockBreak, triggered ); -// } -// else { -// outsideOfMine++; -// } -// -// } -// -// } -// -// if ( unbreakable > 0 ) { -// -// // e.setCancelled( true ); -// debugInfo.append( "UNBREAKABLE_BLOCK_UTILS (" + unbreakable + -// " blocks, event not canceled) " ); -// } -// if ( outsideOfMine > 0 ) { -// -// debugInfo.append( "BLOCKS_OUTSIDE_OF_MINE (" + outsideOfMine + -// " blocks, event not canceled) " ); -// } -// -// debugInfo.append( "(actionBlockEventOnly) " ); -// } -// else if ( monitor && mine == null ) { -// // bypass all processing since the block break is outside any mine: -// -// debugInfo.append( "(bypassed monitor no mine) " ); -// } -// else if ( monitor && mine != null ) { -// int unbreakable = 0; -// int outsideOfMine = 0; -// -// // Initial block that was hit: -// doActionMonitor( block, mine ); -// -// // All other blocks in the explosion: -// for ( Block blk : e.blockList() ) { -// -// // Need to wrap in a Prison block so it can be used with the mines. -// // Since this is a monitor, there is no need to check to see if the -// // block is in a mine since the getTargetPrisonBlock function will -// // perform that check indirectly. -// SpigotBlock sBlock = new SpigotBlock(blk); -// -// if ( BlockUtils.getInstance().isUnbreakable( new SpigotBlock( blk ) ) ) { -// -// unbreakable++; -// } -// else if ( mine.isInMineExact( sBlock.getLocation() ) ) { -// -// doActionMonitor( sBlock, mine ); -// } -// else { -// outsideOfMine++; -// } -// } -// -// if ( unbreakable > 0 ) { -// -// // e.setCancelled( true ); -// debugInfo.append( "UNBREAKABLE_BLOCK_UTILS (" + unbreakable + -// " blocks, event not canceled) " ); -// } -// if ( outsideOfMine > 0 ) { -// -// debugInfo.append( "BLOCKS_OUTSIDE_OF_MINE (" + outsideOfMine + -// " blocks, event not canceled) " ); -// } -// debugInfo.append( "(monitor) " ); -// } // now process all blocks (non-monitor): @@ -1051,191 +835,7 @@ protected void genericBlastUseEvent( BlastUseEvent e, boolean monitor, boolean b } -// -// List explodedBlocks = new ArrayList<>(); -// -// -// // long startNano = System.nanoTime(); -// Long playerUUIDLSB = Long.valueOf( e.getPlayer().getUniqueId().getLeastSignificantBits() ); -// -// // Get the cached mine, if it exists: -// Mine mine = getPlayerCache().get( playerUUIDLSB ); -// -// if ( mine == null ) { -// -// -// // NOTE: The crazy enchantment's blast use event does not identify the block that -// // was hit, so will have to check them all. -// -// // have to go through all blocks since some blocks may be outside the mine. -// // but terminate search upon first find: -// for ( Block blk : e.getBlockList() ) { -// // Need to wrap in a Prison block so it can be used with the mines: -// SpigotBlock block = new SpigotBlock(blk); -// -// // Look for the correct mine to use. -// // Set mine to null so if cannot find the right one it will return a null: -// mine = findMineLocation( block ); -// -// // Store the mine in the player cache if not null: -// if ( mine != null ) { -// getPlayerCache().put( playerUUIDLSB, mine ); -// -// // we found the mine! -// break; -// } -// } -// } -// else { -// -// // NOTE: Just because the mine is not null, does not mean that the block was tested to be -// // within the mine. The mine from the player cache could be a different mine -// // altogether. The block must be tested. -// -// // have to go through all blocks since some blocks may be outside the mine. -// // but terminate search upon first find: -// for ( Block blk : e.getBlockList() ) { -// // Need to wrap in a Prison block so it can be used with the mines: -// SpigotBlock block = new SpigotBlock(blk); -// -// // Look for the correct mine to use. -// // Set mine to null so if cannot find the right one it will return a null: -// mine = findMineLocation( block ); -// -// // Store the mine in the player cache if not null: -// if ( mine != null ) { -// getPlayerCache().put( playerUUIDLSB, mine ); -// -// // we found the mine! -// break; -// } -// } -// -// } -// -// debugInfo.append( "mine=" + (mine == null ? "none" : mine.getName()) + " " ); -// -// boolean isCEBlockExplodeEnabled = isBoolean( AutoFeatures.isProcessCrazyEnchantsBlockExplodeEvents ); -// -// if ( isToolDisabled( e.getPlayer() ) ) { -// -// PrisonUtilsTitles uTitles = new PrisonUtilsTitles(); -// uTitles.utilsTitlesActionBar( new SpigotPlayer( e.getPlayer() ), "", -// "&cYour tool is worn-out and cannot be used." ); -// -// e.setCancelled( true ); -// debugInfo.append( "UNUSABLE_TOOL__WORN_OUT (event canceled) " ); -// } -//// else if ( mine != null && BlockUtils.getInstance().isUnbreakable( block ) ) { -//// // The block is unbreakable because a utility has it locked: -//// -//// e.setCancelled( true ); -//// debugInfo += "UNBREAKABLE_BLOCK_UTILS (event canceled) "; -//// } -// else if ( mine != null && (mine.isMineAccessByRank() || mine.isAccessPermissionEnabled()) && -// !mine.hasMiningAccess( new SpigotPlayer( e.getPlayer() ) ) ) { -// // The player does not have permission to access this mine, so do not process -// // -// -// e.setCancelled( true ); -// debugInfo.append( "ACCESS_DENIED (event canceled) " ); -// } -// else if ( blockEventsOnly ) { -// int unbreakable = 0; -// int outsideOfMine = 0; -// -// if ( mine != null ) { -// -// String triggered = null; -// -// // All other blocks in the explosion: -// for ( Block blk : e.getBlockList() ) { -// -// -// // Need to wrap in a Prison block so it can be used with the mines. -// // Since this is a monitor, there is no need to check to see if the -// // block is in a mine since the getTargetPrisonBlock function will -// // perform that check indirectly. -// SpigotBlock sBlock = new SpigotBlock(blk); -// -// if ( BlockUtils.getInstance().isUnbreakable( new SpigotBlock( blk ) ) ) { -// -// unbreakable++; -// } -// else if ( mine.isInMineExact( sBlock.getLocation() ) ) { -// -// doActionBlockEventOnly( sBlock, mine, e.getPlayer(), BlockEventType.CEXplosion, triggered ); -// } -// else { -// outsideOfMine++; -// } -// -// } -// } -// -// if ( unbreakable > 0 ) { -// -// // e.setCancelled( true ); -// debugInfo.append( "UNBREAKABLE_BLOCK_UTILS (" + unbreakable + -// " blocks, event not canceled) " ); -// } -// if ( outsideOfMine > 0 ) { -// -// debugInfo.append( "BLOCKS_OUTSIDE_OF_MINE (" + outsideOfMine + -// " blocks, event not canceled) " ); -// } -// -// debugInfo.append( "(actionBlockEventOnly) " ); -// } -// else if ( monitor && mine == null ) { -// // bypass all processing since the block break is outside any mine: -// -// debugInfo.append( "(bypassed monitor no mine) " ); -// } -// else if ( monitor && mine != null ) { -// int unbreakable = 0; -// int outsideOfMine = 0; -// -// // Initial block that was hit: CrazyE does not have the main block: -// // doActionMonitor( block, mine ); -// -// // All other blocks in the explosion: -// for ( Block blk : e.getBlockList() ) { -// -// // Need to wrap in a Prison block so it can be used with the mines. -// // Since this is a monitor, there is no need to check to see if the -// // block is in a mine since the getTargetPrisonBlock function will -// // perform that check indirectly. -// SpigotBlock sBlock = new SpigotBlock(blk); -// -// if ( BlockUtils.getInstance().isUnbreakable( new SpigotBlock( blk ) ) ) { -// -// unbreakable++; -// } -// else if ( mine.isInMineExact( sBlock.getLocation() ) ) { -// -// doActionMonitor( sBlock, mine ); -// } -// else { -// outsideOfMine++; -// } -// -// } -// -// if ( unbreakable > 0 ) { -// -// // e.setCancelled( true ); -// debugInfo.append( "UNBREAKABLE_BLOCK_UTILS (" + unbreakable + -// " blocks, event not canceled) " ); -// } -// if ( outsideOfMine > 0 ) { -// -// debugInfo.append( "BLOCKS_OUTSIDE_OF_MINE (" + outsideOfMine + -// " blocks, event not canceled) " ); -// } -// -// debugInfo.append( "(monitor) " ); -// } + // now process all blocks (non-monitor): else if ( isCEBlockExplodeEnabled && From 32ec731c5fd030c42b7d1e2f9bae97a27c571317 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 26 Sep 2021 13:13:19 -0400 Subject: [PATCH 069/283] Adjustments to the new auto features for cancel block break events and block drops. --- docs/changelog_v3.3.x.md | 3 +++ .../prison/autofeatures/AutoFeaturesFileConfig.java | 6 +++++- .../prison/spigot/block/OnBlockBreakEventCore.java | 10 +++++----- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 8160c2906..5f1ceb8cf 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-09-26 +* **Adjustments to the new auto features for cancel block break events and block drops.** + + * **Removal of some auto feature commented out old code.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java index 9ee1a04df..a711d2cd7 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java +++ b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java @@ -49,8 +49,12 @@ public enum AutoFeatures { blockBreakEvents(options), + // Setting this to true will cancel the block break events (normal prison behavior): cancelAllBlockBreakEvents(blockBreakEvents, true), - cancelAllBlockEventBlockDrops(blockBreakEvents, true), + // Setting this to false will not zero out the block drops (normal prison behavior). + // When set to true, it will zero it out so if the block break event is not cancleed, + // then it will prevent double drops: + cancelAllBlockEventBlockDrops(blockBreakEvents, false), blockBreakEventPriority(blockBreakEvents, "LOW"), diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index a7e63263a..fa4e59cba 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -358,7 +358,7 @@ else if ( pmEvent.getMine() != null || pmEvent.getMine() == null && // doAction returns a boolean that indicates if the event should be canceled or not: if ( doAction( sBlock, pmEvent.getMine(), pmEvent.getPlayer(), debugInfo ) ) { - if ( !isBoolean( AutoFeatures.cancelAllBlockBreakEvents ) ) { + if ( isBoolean( AutoFeatures.cancelAllBlockBreakEvents ) ) { e.setCancelled( true ); } else { @@ -694,7 +694,7 @@ else if ( isTEExplosiveEnabled && if ( doAction( pmEvent.getMine(), pmEvent.getPlayer(), pmEvent.getExplodedBlocks(), BlockEventType.TEXplosion, triggered, debugInfo ) ) { - if ( !isBoolean( AutoFeatures.cancelAllBlockBreakEvents ) ) { + if ( isBoolean( AutoFeatures.cancelAllBlockBreakEvents ) ) { e.setCancelled( true ); } @@ -888,7 +888,7 @@ else if ( isCEBlockExplodeEnabled && if ( doAction( pmEvent.getMine(), e.getPlayer(), pmEvent.getExplodedBlocks(), BlockEventType.CEXplosion, triggered, debugInfo ) ) { - if ( !isBoolean( AutoFeatures.cancelAllBlockBreakEvents ) ) { + if ( isBoolean( AutoFeatures.cancelAllBlockBreakEvents ) ) { e.setCancelled( true ); } @@ -1013,7 +1013,7 @@ else if ( isPEExplosiveEnabled && if ( doAction( pmEvent.getMine(), e.getPlayer(), pmEvent.getExplodedBlocks(), BlockEventType.PEExplosive, triggered, debugInfo ) ) { - if ( !isBoolean( AutoFeatures.cancelAllBlockBreakEvents ) ) { + if ( isBoolean( AutoFeatures.cancelAllBlockBreakEvents ) ) { e.setCancelled( true ); } @@ -1111,7 +1111,7 @@ else if ( isPPrisonExplosiveBlockBreakEnabled && if ( doAction( pmEvent.getMine(), e.getPlayer(), pmEvent.getExplodedBlocks(), BlockEventType.PrisonExplosion, triggered, debugInfo ) ) { - if ( !isBoolean( AutoFeatures.cancelAllBlockBreakEvents ) ) { + if ( isBoolean( AutoFeatures.cancelAllBlockBreakEvents ) ) { e.setCancelled( true ); } From 0c630f51029f17034f732eaa4e604c21961c565a Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 26 Sep 2021 22:27:16 -0400 Subject: [PATCH 070/283] Added an example of possible backpack object to the PlayerCachePlayerData object. --- docs/changelog_v3.3.x.md | 3 +++ .../prison/cache/PlayerCachePlayerData.java | 13 +++++++++++++ 2 files changed, 16 insertions(+) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 5f1ceb8cf..bb2e793f5 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-09-26 +* **Added an example of possible backpack object to the PlayerCachePlayerData object.** + + * **Adjustments to the new auto features for cancel block break events and block drops.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java index 315a1a0fd..8297da749 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java @@ -2,12 +2,15 @@ import java.io.File; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Date; +import java.util.List; import java.util.TreeMap; import tech.mcprison.prison.autofeatures.PlayerMessaging; import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.internal.inventory.Inventory; import tech.mcprison.prison.placeholders.PlaceholdersUtil; /** @@ -87,6 +90,7 @@ public class PlayerCachePlayerData { private transient PlayerMessaging playerMessaging; + private List backpacks; private transient boolean dirty = false; @@ -119,6 +123,8 @@ public PlayerCachePlayerData() { this.playerMessaging = new PlayerMessaging(); + this.backpacks = new ArrayList<>(); + } public PlayerCachePlayerData( Player player, File playerFile ) { @@ -539,6 +545,13 @@ public void setPlayerMessaging( PlayerMessaging playerMessaging ) { this.playerMessaging = playerMessaging; } + public List getBackpacks() { + return backpacks; + } + public void setBackpacks( List backpacks ) { + this.backpacks = backpacks; + } + public boolean isDirty() { return dirty; } From 848acd09e8e8fca6ec2e092b8493d170fb553443 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Tue, 28 Sep 2021 13:32:18 -0400 Subject: [PATCH 071/283] Bug fix: Logic was corrected to handle the double negative correctly. The was an issue with the /mines set area command when the mine's area was larger than 25,000 blocks. They have to enter either "confirm" or "yes". The bug would require them to enter both to create the mine. --- docs/changelog_v3.3.x.md | 6 +++++- .../tech/mcprison/prison/mines/commands/MinesCommands.java | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index bb2e793f5..a29019efa 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,11 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.1 2021-09-26 +# 3.2.11-alpha.1 2021-09-28 + + +* **Bug fix: Logic was corrected to handle the double negative correctly.** +The was an issue with the /mines set area command when the mine's area was larger than 25,000 blocks. They have to enter either "confirm" or "yes". The bug would require them to enter both to create the mine. * **Added an example of possible backpack object to the PlayerCachePlayerData object.** diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java index 112fe0ae8..9bd8e7adb 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java @@ -2252,8 +2252,8 @@ else if ( source == null || "wand".equalsIgnoreCase( source ) ) { Bounds selectedBounds = selection.asBounds(); if ( selectedBounds.getTotalBlockCount() > 25000 && - (options == null || !options.toLowerCase().contains( "confirm" ) || - !options.toLowerCase().contains( "yes" ))) { + (options == null || !options.toLowerCase().contains( "confirm" ) && + !options.toLowerCase().contains( "yes" )) ) { String message = String.format( "&7Warning: This mine has a size of %s. If this is " + "intentional, then please re-submit this command with adding the " + "keyword of either 'confirm' or 'yes' to the end of the command. ", From 26d81903cf5a5f74fe9aab64979bdf898848f893 Mon Sep 17 00:00:00 2001 From: AnonymousGCA Date: Fri, 1 Oct 2021 22:36:09 +0200 Subject: [PATCH 072/283] Changelogs: - Absolutely not ready NewBackPacksUtil, not tested and not even final class name, everything is work-in-progress and there may be a ton of optimizations possible. --- .../spigot/backpacks/BackpacksListeners.java | 4 +- .../spigot/backpacks/NewBackpacksUtil.java | 437 ++++++++++++++++++ 2 files changed, 439 insertions(+), 2 deletions(-) create mode 100644 prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/NewBackpacksUtil.java diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/BackpacksListeners.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/BackpacksListeners.java index 38ead4741..d380712b0 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/BackpacksListeners.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/BackpacksListeners.java @@ -32,7 +32,7 @@ public void onBackpackCloseEvent(InventoryCloseEvent e){ @EventHandler public void onDeadBackpack(PlayerDeathEvent e){ - onDeadBackpackAction(e); + onDeathBackpackAction(e); } @@ -50,7 +50,7 @@ public void onPlayerClickBackpackItem(PlayerInteractEvent e){ backpackItemClickAction(e); } - private void onDeadBackpackAction(PlayerDeathEvent e) { + private void onDeathBackpackAction(PlayerDeathEvent e) { if (getBoolean(BackpacksUtil.get().getBackpacksConfig().getString("Options.BackPack_Lose_Items_On_Death"))) { BackpacksUtil.get().resetBackpack(e.getEntity()); if (getBoolean(BackpacksUtil.get().getBackpacksConfig().getString("Options.Multiple-BackPacks-For-Player-Enabled"))) { diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/NewBackpacksUtil.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/NewBackpacksUtil.java new file mode 100644 index 000000000..4a52f8795 --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/NewBackpacksUtil.java @@ -0,0 +1,437 @@ +package tech.mcprison.prison.spigot.backpacks; + +import com.cryptomorin.xseries.XMaterial; +import com.cryptomorin.xseries.XSound; +import org.bukkit.Bukkit; +import org.bukkit.configuration.Configuration; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import tech.mcprison.prison.cache.PlayerCache; +import tech.mcprison.prison.cache.PlayerCachePlayerData; +import tech.mcprison.prison.output.Output; +import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.configs.MessagesConfig; +import tech.mcprison.prison.spigot.game.SpigotPlayer; +import tech.mcprison.prison.spigot.inventory.SpigotInventory; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +/** + * @author AnonymousGCA (GABRYCA) + */ +public class NewBackpacksUtil { + + private static NewBackpacksUtil instance; + private MessagesConfig messages; + private Configuration backpacksConfig; + private Configuration backpacksData; + private boolean isFoundDeprecatedData; + private boolean isBackpackUsePermissionEnabled; + private boolean isBackpackAutopickupEnabled; + private boolean isBackpackOpenItemEnabled; + private boolean isBackpackOpenItemGivenOnJoin; + private boolean isBackpackEnabledIfLimitZero; + private boolean isBackpackLostOnDeath; + private boolean isBackpackOpenSoundEnabled; + private boolean isBackpackCloseSoundEnabled; + private boolean isMultipleBackpacksEnabled; + private String backpackUsePermission; + private String backpackOpenItemTitle; + private XSound backpackOpenSound = XSound.BLOCK_CHEST_OPEN; + private XSound backpackCloseSound = XSound.BLOCK_CHEST_CLOSE; + private int defaultBackpackSize; + private int defaultBackpackLimitForPlayer; + private XMaterial backpackOpenItem = XMaterial.CHEST; + + + /** + * Get an instance of Backpacks to get full access to the API. + *

+ * If Backpacks are disabled, this will return null. + * + * @return BackpacksUtil + */ + public NewBackpacksUtil get() { + + if (!getBoolean(SpigotPrison.getInstance().getConfig().getString("backpacks"))) { + return null; + } + + if (instance == null) { + instance = new NewBackpacksUtil(); + instance.initCachedData(); + } + + return instance; + } + + /** + * Return boolean value from String. + * + * @param string - Boolean string. + * @return boolean. + */ + public static boolean getBoolean(String string) { + return string != null && string.equalsIgnoreCase("true"); + } + + /** + * Init options that will be cached. + */ + private void initCachedData() { + messages = SpigotPrison.getInstance().getMessagesConfig(); + backpacksConfig = SpigotPrison.getInstance().getBackpacksConfig(); + if (new File(SpigotPrison.getInstance().getDataFolder() + "/backpacks/backpacksData.yml").exists()) { + backpacksData = YamlConfiguration.loadConfiguration(new File(SpigotPrison.getInstance().getDataFolder() + "/backpacks/backpacksData.yml")); + isFoundDeprecatedData = true; + } else { + isFoundDeprecatedData = false; + } + isBackpackUsePermissionEnabled = getBoolean(backpacksConfig.getString("Options.BackPack_Use_Permission_Enabled")); + isBackpackAutopickupEnabled = getBoolean(backpacksConfig.getString("Options.BackPack_AutoPickup_Usable")); + isBackpackOpenItemEnabled = getBoolean(backpacksConfig.getString("Options.Back_Pack_GUI_Opener_Item")); + isBackpackOpenItemGivenOnJoin = getBoolean(backpacksConfig.getString("Options.BackPack_Item_OnJoin")); + isBackpackEnabledIfLimitZero = getBoolean(backpacksConfig.getString("Options.BackPack_Access_And_Item_If_Limit_Is_0")); + isBackpackLostOnDeath = getBoolean(backpacksConfig.getString("Options.BackPack_Lose_Items_On_Death")); + isBackpackOpenSoundEnabled = getBoolean(backpacksConfig.getString("Options.BackPack_Open_Sound_Enabled")); + isBackpackCloseSoundEnabled = getBoolean(backpacksConfig.getString("Options.BackPack_Close_Sound_Enabled")); + isMultipleBackpacksEnabled = getBoolean(backpacksConfig.getString("Options.Multiple-BackPacks-For-Player-Enabled")); + if (XSound.matchXSound(backpacksConfig.getString("Options.BackPack_Open_Sound")).isPresent()) { + backpackOpenSound = XSound.matchXSound(backpacksConfig.getString("Options.BackPack_Open_Sound")).get(); + } + if (XSound.matchXSound(backpacksConfig.getString("Options.BackPack_Close_Sound")).isPresent()) { + backpackCloseSound = XSound.matchXSound(backpacksConfig.getString("Options.BackPack_Close_Sound")).get(); + } + if (XMaterial.matchXMaterial(backpacksConfig.getString("Options.BackPack_Item")).isPresent()) { + backpackOpenItem = XMaterial.matchXMaterial(backpacksConfig.getString("Options.BackPack_Item")).get(); + } + backpackUsePermission = backpacksConfig.getString("Options.BackPack_Use_Permission"); + backpackOpenItemTitle = backpacksConfig.getString("Options.BackPack_Item_Title"); + defaultBackpackSize = Integer.parseInt(backpacksConfig.getString("Options.BackPack_Default_Size")); + defaultBackpackLimitForPlayer = Integer.parseInt(backpacksConfig.getString("Options.Multiple-BackPacks-For-Player")); + } + + /** + * Save a Player's Backpack. + * + * @param p - Player. + * @param inv - Backpack. + */ + public void setBackpack(Player p, Inventory inv, int id) { + + //TODO + // Add conditions here to check if Player can own backpacks. + // This may also be a method with a boolean return value. + + PlayerCachePlayerData pData = PlayerCache.getInstance().getOnlinePlayer(new SpigotPlayer(p)); + + if (pData == null) { + Output.get().sendInfo(new SpigotPlayer(p), "Sorry, unable to find cached data on you, this may be a bug! Please report it."); + return; + } + + List inventories = prisonInventoryToNormalConverter(pData.getBackpacks()); + + if (inventories.get(id) != null){ + // No need to check more conditions here, Player already owns a backpack here. + inventories.set(id, inv); + + pData.setBackpacks(normalInventoryToPrisonConverter(inventories)); + } else { + + //TODO + // Add conditions to check if player can own a new backpack, maybe he reached the limit. + // This may be also a method with a boolean return value. + + inventories.add(inv); + + pData.setBackpacks(normalInventoryToPrisonConverter(inventories)); + } + } + + /** + * Get a Player's Backpack, there may be multiple ones. + * + * @param p - Player. + * @param id - int. + * @return Inventory - Backpack. + */ + public Inventory getBackpack(Player p, int id) { + + PlayerCachePlayerData pData = PlayerCache.getInstance().getOnlinePlayer(new SpigotPlayer(p)); + + if (pData == null) { + return null; + } + + oldBackpacksConverter(p); + + if (pData.getBackpacks() == null || pData.getBackpacks().get(id) == null) { + return null; + } + SpigotInventory sInv = (SpigotInventory) pData.getBackpacks().get(id); + + return sInv.getWrapper(); + } + + /** + * Get Backpacks of a Player in a List of Inventories. + * + * @param p - Player. + * + * @return Inventory - List. + */ + public List getBackpacks(Player p) { + + PlayerCachePlayerData pData = PlayerCache.getInstance().getOnlinePlayer(new SpigotPlayer(p)); + + if (pData == null) { + return null; + } + + oldBackpacksConverter(p); + + if (pData.getBackpacks() == null) { + return null; + } + + return prisonInventoryToNormalConverter(pData.getBackpacks()); + } + + /** + * Converts a Prison's Inventory List to the spigot standard one. + * + * @param pInv - PrisonInventory List. + * + * @return List - Inventory. + * */ + private List prisonInventoryToNormalConverter(List pInv) { + List inventories = new ArrayList<>(); + for (tech.mcprison.prison.internal.inventory.Inventory pInvRead : pInv) { + SpigotInventory sInv = (SpigotInventory) pInvRead; + inventories.add(sInv.getWrapper()); + } + + return inventories; + } + + /** + * Converts a Spigot's normal Inventory List to the Prison one. + * + * @param inventories - Inventories. + * + * @return List - Prison Inventories. + * */ + private List normalInventoryToPrisonConverter(List inventories) { + List pInv = new ArrayList<>(); + for (Inventory readInv : inventories){ + pInv.add(SpigotInventory.fromWrapper(readInv)); + } + return pInv; + } + + /** + * Converts old Backpacks storage to the new one, deleting the deprecated one for this player. + * + * @param p - Player. + */ + private void oldBackpacksConverter(Player p) { + if (isFoundDeprecatedData) { + if (backpacksData.getString("Inventories." + p.getUniqueId() + ".PlayerName") != null) { + + PlayerCachePlayerData pData = PlayerCache.getInstance().getOnlinePlayer(new SpigotPlayer(p)); + + List prisonBackpacks = pData.getBackpacks(); + List readBackpacks = new ArrayList<>(); + + Output.get().sendWarn(new SpigotPlayer(p), "The Backpack data got updated, conversion started..."); + File backpacksFile = new File(SpigotPrison.getInstance().getDataFolder() + "/backpacks/backpacksData.yml"); + FileConfiguration backpacksFileData = YamlConfiguration.loadConfiguration(backpacksFile); + + // Check if multiple backpacks is enabled and get the backpacks. + if (isMultipleBackpacksEnabled) { + for (String backpackIds : getBackpacksIDsList(p)) { + readBackpacks.add(getOldBackpackOwn(p, backpackIds)); + } + } else { + readBackpacks.add(getOldBackpackOwn(p)); + } + + // Set to null this data and save it in the old config. + backpacksFileData.set("Inventories." + p.getUniqueId(), null); + try { + backpacksFileData.save(backpacksFile); + } catch (IOException e) { + e.printStackTrace(); + } + + int numberConverted = 0; + for (Inventory inv : readBackpacks) { + numberConverted++; + prisonBackpacks.add(SpigotInventory.fromWrapper(inv)); + } + + pData.setBackpacks(prisonBackpacks); + pData.isDirty(); + Output.get().sendInfo(new SpigotPlayer(p), numberConverted + " Backpacks converted with success, will open soon..."); + } + } + } + + /** + * This method exists only for the conversion of the old deprecated one. + */ + @Deprecated + private Inventory getOldBackpackOwn(Player p) { + + int size = getOldSize(p); + Inventory inv = Bukkit.createInventory(p, size, SpigotPrison.format("&3" + p.getName() + " -> Backpack")); + + // Get the Items config section. + Set slots; + try { + slots = backpacksData.getConfigurationSection("Inventories." + p.getUniqueId() + ".Items").getKeys(false); + } catch (NullPointerException ex) { + return inv; + } + if (slots.size() != 0) { + for (String slot : slots) { + ItemStack finalItem = backpacksData.getItemStack("Inventories." + p.getUniqueId() + ".Items." + slot + ".ITEMSTACK"); + if (finalItem != null) { + int slotNumber = Integer.parseInt(slot); + if (size > slotNumber) { + inv.setItem(slotNumber, finalItem); + } + } + } + } + + return inv; + } + + /** + * This method exists only for the conversion of the old deprecated one. + */ + @Deprecated + private Inventory getOldBackpackOwn(Player p, String id) { + + int size = getOldSize(p, id); + Inventory inv = Bukkit.createInventory(p, size, SpigotPrison.format("&3" + p.getName() + " -> Backpack-" + id)); + + // Get the Items config section + Set slots; + try { + slots = backpacksData.getConfigurationSection("Inventories." + p.getUniqueId() + ".Items-" + id).getKeys(false); + } catch (NullPointerException ex) { + return inv; + } + if (slots.size() != 0) { + for (String slot : slots) { + ItemStack finalItem = backpacksData.getItemStack("Inventories." + p.getUniqueId() + ".Items-" + id + "." + slot + ".ITEMSTACK"); + if (finalItem != null) { + int slotNumber = Integer.parseInt(slot); + if (size > slotNumber) { + inv.setItem(slotNumber, finalItem); + } + } + } + } + + return inv; + } + + /** + * Don't use this method. + */ + @Deprecated + private int getOldSize(Player p) { + + int backPackSize = defaultBackpackSize; + + try { + backPackSize = Integer.parseInt(backpacksData.getString("Inventories." + p.getUniqueId() + ".Items.Size")); + } catch (NumberFormatException ignored) { + } + + if (backPackSize % 9 != 0) { + backPackSize = (int) Math.ceil((float) backPackSize / 9) * 9; + } + + if (backPackSize == 0) backPackSize = 9; + + return getBackpackPermSize(p, backPackSize); + } + + /** + * Don't use this method. + */ + @Deprecated + private int getOldSize(Player p, String id) { + int backPackSize = defaultBackpackSize; + + try { + backPackSize = Integer.parseInt(backpacksData.getString("Inventories." + p.getUniqueId() + ".Items-" + id + ".Size")); + } catch (NumberFormatException ignored) { + } + + if (backPackSize % 9 != 0) { + backPackSize = (int) Math.ceil((float) backPackSize / 9) * 9; + } + + if (backPackSize == 0) backPackSize = 9; + + return getBackpackPermSize(p, backPackSize); + } + + /** + * Get backpack size of a Player Backpack with the permission for a custom one. + */ + private int getBackpackPermSize(Player p, int backPackSize) { + SpigotPlayer sPlayer = new SpigotPlayer(p); + List perms = sPlayer.getPermissions("prison.backpack.size."); + int value = 0; + for (String permNumber : perms) { + int newValue = Integer.parseInt(permNumber.substring(21)); + if (newValue > value) { + value = (int) Math.ceil((float) newValue / 9) * 9; + } + } + + if (value != 0) { + return value; + } + return backPackSize; + } + + /** + * This method exists only for the conversion of the old deprecated one. + */ + @Deprecated + private List getBackpacksIDsList(Player p) { + List backpacksIDs = new ArrayList<>(); + + // Items can be -> Items- or just Items in the config, the default and old backpacks will have Items only, newer will be like + // Items-1 or anyway an ID, I'm just getting the ID with this which's what I need. + try { + for (String key : backpacksData.getConfigurationSection("Inventories." + p.getUniqueId()).getKeys(false)) { + if (!key.equalsIgnoreCase("Items") && !key.equalsIgnoreCase("Limit") && !key.equalsIgnoreCase("PlayerName") && !key.equalsIgnoreCase("UniqueID")) { + backpacksIDs.add(key.substring(6)); + } else { + if (!backpacksIDs.contains(null) && !key.equalsIgnoreCase("PlayerName") && !key.equalsIgnoreCase("UniqueID") && !key.equalsIgnoreCase("Limit")) { + backpacksIDs.add(null); + } + } + } + } catch (NullPointerException ignored) { + } + + return backpacksIDs; + } +} From 31763dc1a35e96ba801cdb460aed167233fd6dbe Mon Sep 17 00:00:00 2001 From: AnonymousGCA Date: Fri, 1 Oct 2021 23:04:08 +0200 Subject: [PATCH 073/283] Changelogs: - Absolutely not ready NewBackPacksUtil, not tested and not even final class name, everything is work-in-progress and there may be a ton of optimizations possible. --- .../spigot/backpacks/NewBackpacksUtil.java | 166 ++++++++++++++---- 1 file changed, 134 insertions(+), 32 deletions(-) diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/NewBackpacksUtil.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/NewBackpacksUtil.java index 4a52f8795..e9b72c6ef 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/NewBackpacksUtil.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/NewBackpacksUtil.java @@ -120,21 +120,26 @@ private void initCachedData() { /** * Save a Player's Backpack. + * This method will return true if ran with success, false if Player is missing permission (if enabled) + * or some conditions aren't met, or even errors. + * Essentially, return true if success, false if fail. * * @param p - Player. * @param inv - Backpack. + * + * @return boolean. */ - public void setBackpack(Player p, Inventory inv, int id) { + public boolean setBackpack(Player p, Inventory inv, int id) { - //TODO - // Add conditions here to check if Player can own backpacks. - // This may also be a method with a boolean return value. + if (!canOwnBackpacks(p)){ + return false; + } PlayerCachePlayerData pData = PlayerCache.getInstance().getOnlinePlayer(new SpigotPlayer(p)); if (pData == null) { - Output.get().sendInfo(new SpigotPlayer(p), "Sorry, unable to find cached data on you, this may be a bug! Please report it."); - return; + Output.get().sendInfo(new SpigotPlayer(p), "Sorry, unable to find cached data about you, this may be a bug! Please report it."); + return false; } List inventories = prisonInventoryToNormalConverter(pData.getBackpacks()); @@ -146,21 +151,99 @@ public void setBackpack(Player p, Inventory inv, int id) { pData.setBackpacks(normalInventoryToPrisonConverter(inventories)); } else { - //TODO - // Add conditions to check if player can own a new backpack, maybe he reached the limit. - // This may be also a method with a boolean return value. + return addBackpack(p, inv); + } + return true; + } - inventories.add(inv); + /** + * Add a Backpack to a Player. + * + * Return true if success, false if fail. + * + * @param p - Player. + * @param inv - Inventory. + * + * @return boolean. + * */ + public boolean addBackpack(Player p, Inventory inv){ - pData.setBackpacks(normalInventoryToPrisonConverter(inventories)); + if (!canOwnBackpacks(p)){ + return false; } + + if (inv.getSize() <= getBackpackPermSize(p)){ + Output.get().sendWarn(new SpigotPlayer(p), "Sorry but you can't own a Backpack of this size."); + return false; + } + + PlayerCachePlayerData pData = PlayerCache.getInstance().getOnlinePlayer(new SpigotPlayer(p)); + + if (pData == null) { + Output.get().sendInfo(new SpigotPlayer(p), "Sorry, unable to find cached data on you, this may be a bug! Please report it."); + return false; + } + + List inventories = prisonInventoryToNormalConverter(pData.getBackpacks()); + + if (reachedBackpacksLimit(p)){ + Output.get().sendWarn(new SpigotPlayer(p), "Sorry, you can't own more Backpacks!"); + return false; + } + + inventories.add(inv); + pData.setBackpacks(normalInventoryToPrisonConverter(inventories)); + return true; + } + + /** + * Check if player reached limit of own backpacks. + * + * @return boolean - True if reached, false if not. + * */ + public boolean reachedBackpacksLimit(Player p){ + return isMultipleBackpacksEnabled && (getBackpacksLimit(p) <= getNumberOwnedBackpacks(p)); + } + + /** + * Get number of Backpacks own by Player. + * + * @param p - Player. + * */ + public int getNumberOwnedBackpacks(Player p){ + PlayerCachePlayerData pData = PlayerCache.getInstance().getOnlinePlayer(new SpigotPlayer(p)); + + if (pData == null){ + return 0; + } + + return pData.getBackpacks().size(); + } + + // TODO + // Not sure if this data is cached yet. + private int getBackpacksLimit(Player p) { + return defaultBackpackLimitForPlayer; + } + + /** + * Check if Player can own Backpacks. + * Return true if can, False otherwise. + * + * @param p - Player. + * + * @return boolean. + * */ + public boolean canOwnBackpacks(Player p){ + return !isBackpackUsePermissionEnabled || p.hasPermission(backpackUsePermission); } /** * Get a Player's Backpack, there may be multiple ones. * - * @param p - Player. + * @param p - Player. * @param id - int. + * * @return Inventory - Backpack. */ public Inventory getBackpack(Player p, int id) { @@ -285,6 +368,45 @@ private void oldBackpacksConverter(Player p) { } } + /** + * Get backpack size of a Player Backpack with the permission for a custom one. + */ + private int getBackpackPermSize(Player p, int backPackSize) { + SpigotPlayer sPlayer = new SpigotPlayer(p); + List perms = sPlayer.getPermissions("prison.backpack.size."); + int value = 0; + for (String permNumber : perms) { + int newValue = Integer.parseInt(permNumber.substring(21)); + if (newValue > value) { + value = (int) Math.ceil((float) newValue / 9) * 9; + } + } + + if (value != 0) { + return value; + } + return backPackSize; + } + + /** + * Get backpack size from permissions of a Player and/or defaults. + * + * @param p - Player. + * + * @return int - size. + * */ + public int getBackpackPermSize(Player p){ + int backPackSize = defaultBackpackSize; + + if (backPackSize % 9 != 0) { + backPackSize = (int) Math.ceil((float) backPackSize / 9) * 9; + } + + if (backPackSize == 0) backPackSize = 9; + + return getBackpackPermSize(p, backPackSize); + } + /** * This method exists only for the conversion of the old deprecated one. */ @@ -390,26 +512,6 @@ private int getOldSize(Player p, String id) { return getBackpackPermSize(p, backPackSize); } - /** - * Get backpack size of a Player Backpack with the permission for a custom one. - */ - private int getBackpackPermSize(Player p, int backPackSize) { - SpigotPlayer sPlayer = new SpigotPlayer(p); - List perms = sPlayer.getPermissions("prison.backpack.size."); - int value = 0; - for (String permNumber : perms) { - int newValue = Integer.parseInt(permNumber.substring(21)); - if (newValue > value) { - value = (int) Math.ceil((float) newValue / 9) * 9; - } - } - - if (value != 0) { - return value; - } - return backPackSize; - } - /** * This method exists only for the conversion of the old deprecated one. */ From 9451ffb18e5929dfbdd549f6c291b82d94a4cfcb Mon Sep 17 00:00:00 2001 From: AnonymousGCA Date: Sun, 3 Oct 2021 15:40:34 +0200 Subject: [PATCH 074/283] Changelogs: - Absolutely not ready NewBackPacksUtil, not tested and not even final class name, everything is work-in-progress and there may be a ton of optimizations possible. --- .../spigot/backpacks/NewBackpacksUtil.java | 179 ++++++++++++++---- 1 file changed, 146 insertions(+), 33 deletions(-) diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/NewBackpacksUtil.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/NewBackpacksUtil.java index e9b72c6ef..e1332baf3 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/NewBackpacksUtil.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/NewBackpacksUtil.java @@ -3,18 +3,21 @@ import com.cryptomorin.xseries.XMaterial; import com.cryptomorin.xseries.XSound; import org.bukkit.Bukkit; +import org.bukkit.Sound; import org.bukkit.configuration.Configuration; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; import tech.mcprison.prison.cache.PlayerCache; import tech.mcprison.prison.cache.PlayerCachePlayerData; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; +import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.inventory.SpigotInventory; import java.io.File; @@ -34,7 +37,7 @@ public class NewBackpacksUtil { private Configuration backpacksData; private boolean isFoundDeprecatedData; private boolean isBackpackUsePermissionEnabled; - private boolean isBackpackAutopickupEnabled; + private boolean isBackpackAutoPickupEnabled; private boolean isBackpackOpenItemEnabled; private boolean isBackpackOpenItemGivenOnJoin; private boolean isBackpackEnabledIfLimitZero; @@ -72,6 +75,124 @@ public NewBackpacksUtil get() { return instance; } + /** + * Check if Backpack AutoPickup is enabled. + * + * @return boolean. + */ + public boolean isBackpackAutoPickupEnabled() { + return this.isBackpackAutoPickupEnabled; + } + + /** + * Check if the Backpack Open Item is enabled. + * + * @return boolean. + */ + public boolean isBackpackOpenItemEnabled() { + return this.isBackpackOpenItemEnabled; + } + + /** + * Check if the Backpack Open Item is given on join. + * + * @return boolean. + */ + public boolean isBackpackOpenItemGivenOnJoin() { + return this.isBackpackOpenItemGivenOnJoin; + } + + /** + * Check if Backpack can be used and Backpack item too + * if the Player's limit is set to 0. + * + * @return boolean. + */ + public boolean isBackpackEnabledIfLimitZero() { + return this.isBackpackEnabledIfLimitZero; + } + + /** + * Check if Backpack is deleted/reset on death. + * + * @return boolean. + */ + public boolean isBackpackLostOnDeath() { + return this.isBackpackLostOnDeath; + } + + /** + * Check if Backpack open sound is enabled. + * + * @return boolean. + * */ + public boolean isBackpackOpenSoundEnabled(){ + return this.isBackpackOpenSoundEnabled; + } + + /** + * Check if Backpack close sound is enabled. + * + * @return boolean. + * */ + public boolean isBackpackCloseSoundEnabled(){ + return this.isBackpackCloseSoundEnabled; + } + + /** + * Get Backpack Open Item Title. + * + * @return String. + * */ + public String getBackpackOpenItemTitle(){ + return this.backpackOpenItemTitle; + } + + /** + * Get Backpack Open Permission. + * + * @return String. + * */ + public String getBackpackUsePermission(){ + return this.backpackUsePermission; + } + + /** + * Get Backpack Open Sound. + * + * @return Sound. + * */ + public Sound getBackpackOpenSound(){ + return this.backpackOpenSound.parseSound(); + } + + /** + * Get Backpack Close Sound. + * + * @return Sound. + * */ + public Sound getBackpackCloseSound(){ + return this.backpackCloseSound.parseSound(); + } + + /** + * Get Backpack Open Item. + * + * @return ItemStack. + * */ + public ItemStack getBackpackOpenItem(){ + + ItemStack backPackOpenItemStack = new ItemStack(backpackOpenItem.parseMaterial(), 1); + ItemMeta meta = backPackOpenItemStack.getItemMeta(); + meta.setDisplayName(SpigotPrison.format(SpigotPrison.format(backpackOpenItemTitle))); + ButtonLore lore = new ButtonLore(); + lore.setLoreAction("Click to open Backpack!"); + meta.setLore(lore.getLore()); + backPackOpenItemStack.setItemMeta(meta); + + return backPackOpenItemStack; + } + /** * Return boolean value from String. * @@ -95,7 +216,7 @@ private void initCachedData() { isFoundDeprecatedData = false; } isBackpackUsePermissionEnabled = getBoolean(backpacksConfig.getString("Options.BackPack_Use_Permission_Enabled")); - isBackpackAutopickupEnabled = getBoolean(backpacksConfig.getString("Options.BackPack_AutoPickup_Usable")); + isBackpackAutoPickupEnabled = getBoolean(backpacksConfig.getString("Options.BackPack_AutoPickup_Usable")); isBackpackOpenItemEnabled = getBoolean(backpacksConfig.getString("Options.Back_Pack_GUI_Opener_Item")); isBackpackOpenItemGivenOnJoin = getBoolean(backpacksConfig.getString("Options.BackPack_Item_OnJoin")); isBackpackEnabledIfLimitZero = getBoolean(backpacksConfig.getString("Options.BackPack_Access_And_Item_If_Limit_Is_0")); @@ -124,14 +245,13 @@ private void initCachedData() { * or some conditions aren't met, or even errors. * Essentially, return true if success, false if fail. * - * @param p - Player. + * @param p - Player. * @param inv - Backpack. - * * @return boolean. */ public boolean setBackpack(Player p, Inventory inv, int id) { - if (!canOwnBackpacks(p)){ + if (!canOwnBackpacks(p)) { return false; } @@ -144,7 +264,7 @@ public boolean setBackpack(Player p, Inventory inv, int id) { List inventories = prisonInventoryToNormalConverter(pData.getBackpacks()); - if (inventories.get(id) != null){ + if (inventories.get(id) != null) { // No need to check more conditions here, Player already owns a backpack here. inventories.set(id, inv); @@ -158,21 +278,20 @@ public boolean setBackpack(Player p, Inventory inv, int id) { /** * Add a Backpack to a Player. - * + *

* Return true if success, false if fail. * - * @param p - Player. + * @param p - Player. * @param inv - Inventory. - * * @return boolean. - * */ - public boolean addBackpack(Player p, Inventory inv){ + */ + public boolean addBackpack(Player p, Inventory inv) { - if (!canOwnBackpacks(p)){ + if (!canOwnBackpacks(p)) { return false; } - if (inv.getSize() <= getBackpackPermSize(p)){ + if (inv.getSize() <= getBackpackPermSize(p)) { Output.get().sendWarn(new SpigotPlayer(p), "Sorry but you can't own a Backpack of this size."); return false; } @@ -186,7 +305,7 @@ public boolean addBackpack(Player p, Inventory inv){ List inventories = prisonInventoryToNormalConverter(pData.getBackpacks()); - if (reachedBackpacksLimit(p)){ + if (reachedBackpacksLimit(p)) { Output.get().sendWarn(new SpigotPlayer(p), "Sorry, you can't own more Backpacks!"); return false; } @@ -200,8 +319,8 @@ public boolean addBackpack(Player p, Inventory inv){ * Check if player reached limit of own backpacks. * * @return boolean - True if reached, false if not. - * */ - public boolean reachedBackpacksLimit(Player p){ + */ + public boolean reachedBackpacksLimit(Player p) { return isMultipleBackpacksEnabled && (getBackpacksLimit(p) <= getNumberOwnedBackpacks(p)); } @@ -209,11 +328,11 @@ public boolean reachedBackpacksLimit(Player p){ * Get number of Backpacks own by Player. * * @param p - Player. - * */ - public int getNumberOwnedBackpacks(Player p){ + */ + public int getNumberOwnedBackpacks(Player p) { PlayerCachePlayerData pData = PlayerCache.getInstance().getOnlinePlayer(new SpigotPlayer(p)); - if (pData == null){ + if (pData == null) { return 0; } @@ -231,19 +350,17 @@ private int getBackpacksLimit(Player p) { * Return true if can, False otherwise. * * @param p - Player. - * * @return boolean. - * */ - public boolean canOwnBackpacks(Player p){ + */ + public boolean canOwnBackpacks(Player p) { return !isBackpackUsePermissionEnabled || p.hasPermission(backpackUsePermission); } /** * Get a Player's Backpack, there may be multiple ones. * - * @param p - Player. + * @param p - Player. * @param id - int. - * * @return Inventory - Backpack. */ public Inventory getBackpack(Player p, int id) { @@ -268,7 +385,6 @@ public Inventory getBackpack(Player p, int id) { * Get Backpacks of a Player in a List of Inventories. * * @param p - Player. - * * @return Inventory - List. */ public List getBackpacks(Player p) { @@ -292,9 +408,8 @@ public List getBackpacks(Player p) { * Converts a Prison's Inventory List to the spigot standard one. * * @param pInv - PrisonInventory List. - * * @return List - Inventory. - * */ + */ private List prisonInventoryToNormalConverter(List pInv) { List inventories = new ArrayList<>(); for (tech.mcprison.prison.internal.inventory.Inventory pInvRead : pInv) { @@ -309,12 +424,11 @@ private List prisonInventoryToNormalConverter(List normalInventoryToPrisonConverter(List inventories) { List pInv = new ArrayList<>(); - for (Inventory readInv : inventories){ + for (Inventory readInv : inventories) { pInv.add(SpigotInventory.fromWrapper(readInv)); } return pInv; @@ -392,10 +506,9 @@ private int getBackpackPermSize(Player p, int backPackSize) { * Get backpack size from permissions of a Player and/or defaults. * * @param p - Player. - * * @return int - size. - * */ - public int getBackpackPermSize(Player p){ + */ + public int getBackpackPermSize(Player p) { int backPackSize = defaultBackpackSize; if (backPackSize % 9 != 0) { From 9b801c5c0f29be16bf44395f457c121d6dc592f9 Mon Sep 17 00:00:00 2001 From: AnonymousGCA Date: Sun, 3 Oct 2021 23:19:38 +0200 Subject: [PATCH 075/283] Changelogs: - Absolutely not ready NewBackPacksUtil, not tested and not even final class name, everything is work-in-progress and there may be a ton of optimizations possible. --- .../spigot/backpacks/NewBackpacksUtil.java | 31 ++++++++++- .../gui/backpacks/BackpacksPlayerGUI.java | 54 +++++++++++++++++++ 2 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksPlayerGUI.java diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/NewBackpacksUtil.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/NewBackpacksUtil.java index e1332baf3..cd9617ba9 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/NewBackpacksUtil.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/NewBackpacksUtil.java @@ -17,6 +17,7 @@ import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; +import tech.mcprison.prison.spigot.gui.backpacks.BackpacksPlayerGUI; import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.inventory.SpigotInventory; @@ -56,12 +57,12 @@ public class NewBackpacksUtil { /** * Get an instance of Backpacks to get full access to the API. - *

+ * * If Backpacks are disabled, this will return null. * * @return BackpacksUtil */ - public NewBackpacksUtil get() { + public static NewBackpacksUtil get() { if (!getBoolean(SpigotPrison.getInstance().getConfig().getString("backpacks"))) { return null; @@ -269,6 +270,7 @@ public boolean setBackpack(Player p, Inventory inv, int id) { inventories.set(id, inv); pData.setBackpacks(normalInventoryToPrisonConverter(inventories)); + pData.isDirty(); } else { return addBackpack(p, inv); @@ -312,6 +314,7 @@ public boolean addBackpack(Player p, Inventory inv) { inventories.add(inv); pData.setBackpacks(normalInventoryToPrisonConverter(inventories)); + pData.isDirty(); return true; } @@ -404,6 +407,30 @@ public List getBackpacks(Player p) { return prisonInventoryToNormalConverter(pData.getBackpacks()); } + /** + * Open Player's Backpack. + * + * Return true if open with success, false if fail or error. + * + * @param p - Player. + * @param id - Int. + * + * return boolean. + * */ + public boolean openBackpack(Player p, int id){ + + // Check if Player owns a Backpack with this ID. + if (getBackpack(p, id) == null){ + + Output.get().sendWarn(new SpigotPlayer(p), "Backpack not found!"); + return false; + } + + BackpacksPlayerGUI gui = new BackpacksPlayerGUI(p, id); + gui.open(); + return true; + } + /** * Converts a Prison's Inventory List to the spigot standard one. * diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksPlayerGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksPlayerGUI.java new file mode 100644 index 000000000..843100d1f --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/backpacks/BackpacksPlayerGUI.java @@ -0,0 +1,54 @@ +package tech.mcprison.prison.spigot.gui.backpacks; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import tech.mcprison.prison.output.Output; +import tech.mcprison.prison.spigot.backpacks.NewBackpacksUtil; +import tech.mcprison.prison.spigot.game.SpigotPlayer; +import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; +import tech.mcprison.prison.spigot.gui.guiutility.SpigotGUIComponents; + +public class BackpacksPlayerGUI extends SpigotGUIComponents { + + private final Player p; + private final int id; + + /** + * Load Backpack of a Player if exists. + * + * @param p - Player. + * @param id - Backpack id. + * */ + public BackpacksPlayerGUI(Player p, int id){ + this.p = p; + this.id = id; + } + + public void open(){ + + NewBackpacksUtil backpacksUtil = NewBackpacksUtil.get(); + + if (backpacksUtil == null){ + return; + } + + SpigotPlayer sPlayer = new SpigotPlayer(p); + + Inventory inv = backpacksUtil.getBackpack(p, id); + + if (inv != null){ + PrisonGUI gui = new PrisonGUI(p, inv.getSize(), "&3" + p.getName() + " -> Backpack-" + id); + + Output.get().sendInfo(sPlayer, "Backpack" + id + " open with success!"); + + if (backpacksUtil.isBackpackOpenSoundEnabled()){ + p.playSound(p.getLocation(), backpacksUtil.getBackpackOpenSound(),3,1); + } + + gui.open(); + } + + Output.get().sendWarn(sPlayer, "Backpack ID -> " + id + " not found"); + } + +} From fbb0c6904311f3a1007dbc7246f9365a55e40353 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 3 Oct 2021 23:59:00 -0400 Subject: [PATCH 076/283] Changed the message about worn out tool to use the SpigotPlayer's setActionBar() function to prevent overloading console messages. --- docs/changelog_v3.3.x.md | 5 ++++- .../prison/spigot/block/OnBlockBreakEventCore.java | 10 ++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index a29019efa..fd7ec372a 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,10 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.1 2021-09-28 +# 3.2.11-alpha.1 2021-10-03 + + +* **Changed the message about worn out tool to use the SpigotPlayer's setActionBar() function to prevent overloading console messages.** * **Bug fix: Logic was corrected to handle the double negative correctly.** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index fa4e59cba..7d0fe44b3 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -41,7 +41,6 @@ import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.integrations.IntegrationCrazyEnchantmentsPickaxes; import tech.mcprison.prison.spigot.utils.BlockUtils; -import tech.mcprison.prison.spigot.utils.PrisonUtilsTitles; import tech.mcprison.prison.util.Text; public class OnBlockBreakEventCore @@ -498,9 +497,12 @@ else if ( mine.isInMineExact( sBlock.getLocation() ) ) { if ( isToolDisabled( pmEvent.getPlayer() ) ) { - PrisonUtilsTitles uTitles = new PrisonUtilsTitles(); - uTitles.utilsTitlesActionBar( pmEvent.getSpigotPlayer(), "", - "&cYour tool is worn-out and cannot be used." ); + // This will prevent sending too many messages since it is using PlayerMessagingTask: + pmEvent.getSpigotPlayer().setActionBar( "&cYour tool is worn-out and cannot be used." ); + +// PrisonUtilsTitles uTitles = new PrisonUtilsTitles(); +// uTitles.utilsTitlesActionBarForce( pmEvent.getSpigotPlayer(), null, +// "&cYour tool is worn-out and cannot be used." ); pmEvent.setCancelOriginalEvent( true ); debugInfo.append( "UNUSABLE_TOOL__WORN_OUT (event canceled) " ); From e83224819f351562e3628bb3a8959577fb88bbf3 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Thu, 7 Oct 2021 18:22:54 -0400 Subject: [PATCH 077/283] Fixed a compatibility issue with older versions of spigot. Should have possibly use the compatibility classes, but if a method does not exist, then this will fall back on a string matching pattern. --- docs/changelog_v3.3.x.md | 5 ++- .../prison/spigot/game/SpigotPlayerUtil.java | 33 ++++++++++++++++--- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index fd7ec372a..439e929c4 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,10 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.1 2021-10-03 +# 3.2.11-alpha.1 2021-10-07 + + +* **Fixed a compatibility issue with older versions of spigot.** Should have possibly use the compatibility classes, but if a method does not exist, then this will fall back on a string matching pattern. * **Changed the message about worn out tool to use the SpigotPlayer's setActionBar() function to prevent overloading console messages.** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayerUtil.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayerUtil.java index 8bdd8cf68..4ac67b8c3 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayerUtil.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayerUtil.java @@ -1,7 +1,9 @@ package tech.mcprison.prison.spigot.game; +import java.lang.reflect.Method; import java.util.UUID; +import org.bukkit.NamespacedKey; import org.bukkit.enchantments.Enchantment; import tech.mcprison.prison.Prison; @@ -333,12 +335,35 @@ private int getEnchantment( String enchant ) { Enchantment enchantment = null; - for ( Enchantment e : Enchantment.values() ) { - if ( e.getKey().getKey().equalsIgnoreCase( enchant ) ) { - enchantment = e; - break; + try + { + @SuppressWarnings( "unused" ) + Method methodGetKey = Enchantment.LUCK.getClass().getMethod( "getKey" ); + + for ( Enchantment e : Enchantment.values() ) { + if (e.getKey().getKey().equalsIgnoreCase( enchant ) ) { + enchantment = e; + break; + } } } + catch ( NoSuchMethodException | SecurityException e1 ) { + // Ignore the fact that the method does not exist, which just means this is + // spigot 1.8 or so. + + for ( Enchantment e : Enchantment.values() ) { + if ( e.toString().toLowerCase().contains( enchant.toLowerCase() ) ) { + enchantment = e; + } + } + } + +// for ( Enchantment e : Enchantment.values() ) { +// if (e.getKey().getKey().equalsIgnoreCase( enchant ) ) { +// enchantment = e; +// break; +// } +// } if ( enchantment != null ) { From 6c848b14d986745ec91fbad97077baf240aa0ae5 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Thu, 7 Oct 2021 18:25:24 -0400 Subject: [PATCH 078/283] For a couple of rankup messages, using the rank tag now instead of the rank name. --- docs/changelog_v3.3.x.md | 3 +++ .../mcprison/prison/ranks/commands/RankUpCommandMessages.java | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 439e929c4..fdf592f1f 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-10-07 +* **For a couple of rankup messages, using the rank tag now instead of the rank name.** + + * **Fixed a compatibility issue with older versions of spigot.** Should have possibly use the compatibility classes, but if a method does not exist, then this will fall back on a string matching pattern. diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RankUpCommandMessages.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RankUpCommandMessages.java index b756c595c..895a1f578 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RankUpCommandMessages.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RankUpCommandMessages.java @@ -180,7 +180,7 @@ protected void ranksRankupSuccessMsg( CommandSender sender, String playerName, .withReplacements( (playerName == null ? messagNoPlayerName : playerName), - (tRank == null ? "" : tRank.getName()), + (tRank == null ? "" : tRank.getTag() ), (results.getMessage() != null ? results.getMessage() : "") ); @@ -202,7 +202,7 @@ protected void ranksRankupSuccessMsg( CommandSender sender, String playerName, .withReplacements( (playerName == null ? messagNoPlayerNameBroadcast : playerName), - (tRank == null ? "" : tRank.getName()), + (tRank == null ? "" : tRank.getTag() ), (results.getMessage() != null ? results.getMessage() : "") ) .broadcast(); From b913d6395a534137838acdf4f64f9a63e9151325 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Thu, 7 Oct 2021 18:35:52 -0400 Subject: [PATCH 079/283] Add the abilty to glow the prison bombs when they are dropped/set. --- docs/changelog_v3.3.x.md | 3 +++ .../java/tech/mcprison/prison/bombs/MineBombData.java | 9 +++++++++ .../mcprison/prison/spigot/utils/PrisonBombListener.java | 8 +++++++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index fdf592f1f..ebaba599b 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.1 2021-10-07 +* **Add the ability to glow the prison bombs when they are dropped/set.** + + * **For a couple of rankup messages, using the rank tag now instead of the rank name.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java index c3cfc1bef..034c0cb1f 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java @@ -47,6 +47,8 @@ public class MineBombData { private String description; + private boolean glowing = false; + private boolean activated = false; @@ -135,6 +137,13 @@ public void setDescription( String description ) { this.description = description; } + public boolean isGlowing() { + return glowing; + } + public void setGlowing( boolean glowing ) { + this.glowing = glowing; + } + public boolean isActivated() { return activated; } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java index e40c5c899..d8e5fcd98 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java @@ -31,7 +31,7 @@ public class PrisonBombListener { @EventHandler( priority = EventPriority.LOW ) - public void onInteract(PlayerInteractEvent event) { + public void onInteract( PlayerInteractEvent event ) { if ( !event.getPlayer().hasPermission("prison.minebombs.use") ) { return; } @@ -67,6 +67,12 @@ public void onInteract(PlayerInteractEvent event) { dropped.setVelocity(player.getLocation().getDirection().multiply( throwSpeed ).normalize() ); dropped.setPickupDelay( 50000 ); + dropped.setGlowing( bomb.isGlowing() ); + dropped.setCustomName( bomb.getName() ); + + dropped.setMetadata( "prisonMineBomb", new FixedMetadataValue( SpigotPrison.getInstance(), true ) ); + //dropped.setMetadata( "prisonMineName", new FixedMetadataValue( SpigotPrison.getInstance(), "mineName" ) ); + PrisonUtilsMineBombs.setoffBombDelayed( sPlayer, bomb, dropped, sBlock, throwSpeed ); From f1178a7cb5d9153875ad8dedeaab73d7d2e7159d Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 8 Oct 2021 06:28:56 -0400 Subject: [PATCH 080/283] Add the abilty to glow the prison bombs when they are dropped/set. --- .../tech/mcprison/prison/spigot/utils/PrisonBombListener.java | 1 + 1 file changed, 1 insertion(+) diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java index d8e5fcd98..3fbdafbf2 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java @@ -9,6 +9,7 @@ import org.bukkit.event.Listener; import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.metadata.FixedMetadataValue; import tech.mcprison.prison.bombs.MineBombData; import tech.mcprison.prison.spigot.block.SpigotBlock; From a0b5db6302ae62f337edc18fe0f9571281996120 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 8 Oct 2021 06:32:10 -0400 Subject: [PATCH 081/283] Add the abilty to glow the prison bombs when they are dropped/set. --- .../tech/mcprison/prison/spigot/utils/PrisonBombListener.java | 1 + 1 file changed, 1 insertion(+) diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java index 3fbdafbf2..923a9799e 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java @@ -12,6 +12,7 @@ import org.bukkit.metadata.FixedMetadataValue; import tech.mcprison.prison.bombs.MineBombData; +import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.block.SpigotBlock; import tech.mcprison.prison.spigot.block.SpigotItemStack; import tech.mcprison.prison.spigot.game.SpigotPlayer; From 41fce1f049d1259d0288f6e4b6cd65bcd814e284 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Tue, 12 Oct 2021 22:21:52 -0400 Subject: [PATCH 082/283] A few updates to mine bombs. They have been disabled so they cannot be used. --- docs/changelog_v3.3.x.md | 5 +- .../prison/spigot/game/SpigotPlayerUtil.java | 1 - .../spigot/utils/PrisonBombListener.java | 141 ++++++++++++++++-- 3 files changed, 129 insertions(+), 18 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index ebaba599b..8dfea901b 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,10 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.1 2021-10-07 +# 3.2.11-alpha.1 2021-10-12 + + +* **A few updates to mine bombs. They have been disabled so they cannot be used.** * **Add the ability to glow the prison bombs when they are dropped/set.** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayerUtil.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayerUtil.java index 4ac67b8c3..df736630f 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayerUtil.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayerUtil.java @@ -3,7 +3,6 @@ import java.lang.reflect.Method; import java.util.UUID; -import org.bukkit.NamespacedKey; import org.bukkit.enchantments.Enchantment; import tech.mcprison.prison.Prison; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java index 923a9799e..e98316b7a 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java @@ -2,16 +2,25 @@ import java.text.DecimalFormat; +import org.bukkit.attribute.Attribute; +import org.bukkit.attribute.AttributeModifier; import org.bukkit.entity.Item; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.player.PlayerDropItemEvent; import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.metadata.FixedMetadataValue; +import com.google.common.collect.Multimap; + import tech.mcprison.prison.bombs.MineBombData; +import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.block.SpigotBlock; import tech.mcprison.prison.spigot.block.SpigotItemStack; @@ -31,12 +40,15 @@ public class PrisonBombListener implements Listener { + - @EventHandler( priority = EventPriority.LOW ) +// @EventHandler( priority = EventPriority.LOW ) public void onInteract( PlayerInteractEvent event ) { - if ( !event.getPlayer().hasPermission("prison.minebombs.use") ) { - return; - } +// if ( !event.getPlayer().hasPermission("prison.minebombs.use") ) { +// return; +// } + + Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent 01 " ); if ( event.getAction().equals(Action.RIGHT_CLICK_BLOCK) || event.getAction().equals(Action.RIGHT_CLICK_AIR) ) { @@ -44,8 +56,12 @@ public void onInteract( PlayerInteractEvent event ) { // ItemStack in the player's hand by 1: MineBombData bomb = PrisonUtilsMineBombs.getBombInHand( event.getPlayer() ); + Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent 02 is bomb null " + (bomb == null) ); + if ( bomb != null ) { + Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent 03 " ); + Player player = event.getPlayer(); SpigotPlayer sPlayer = new SpigotPlayer( player ); @@ -55,28 +71,32 @@ public void onInteract( PlayerInteractEvent event ) { // inventory. if ( bomb.isActivated() ) { +// Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent 04 " ); SpigotItemStack bombs = PrisonUtilsMineBombs.getItemStackBomb( bomb ); if ( bombs != null ) { + + Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent 05 " ); SpigotBlock sBlock = new SpigotBlock( event.getClickedBlock() ); + Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent dropping block " ); int throwSpeed = 2; - final Item dropped = player.getWorld().dropItem(player.getLocation(), bombs.getBukkitStack() ); - dropped.setVelocity(player.getLocation().getDirection().multiply( throwSpeed ).normalize() ); - dropped.setPickupDelay( 50000 ); - - dropped.setGlowing( bomb.isGlowing() ); - dropped.setCustomName( bomb.getName() ); - - dropped.setMetadata( "prisonMineBomb", new FixedMetadataValue( SpigotPrison.getInstance(), true ) ); - //dropped.setMetadata( "prisonMineName", new FixedMetadataValue( SpigotPrison.getInstance(), "mineName" ) ); - - - PrisonUtilsMineBombs.setoffBombDelayed( sPlayer, bomb, dropped, sBlock, throwSpeed ); +// final Item dropped = player.getWorld().dropItem(player.getLocation(), bombs.getBukkitStack() ); +// dropped.setVelocity(player.getLocation().getDirection().multiply( throwSpeed ).normalize() ); +// dropped.setPickupDelay( 50000 ); +// +// dropped.setGlowing( bomb.isGlowing() ); +// dropped.setCustomName( bomb.getName() ); +// +// dropped.setMetadata( "prisonMineBomb", new FixedMetadataValue( SpigotPrison.getInstance(), true ) ); +// //dropped.setMetadata( "prisonMineName", new FixedMetadataValue( SpigotPrison.getInstance(), "mineName" ) ); +// +// +// PrisonUtilsMineBombs.setoffBombDelayed( sPlayer, bomb, dropped, sBlock, throwSpeed ); } } @@ -105,4 +125,93 @@ public void onInteract( PlayerInteractEvent event ) { } } + + +// @EventHandler( priority = EventPriority.HIGHEST, ignoreCancelled = false ) + public void onBlockPlace( PlayerDropItemEvent event ) { + + Output.get().logInfo( "### PrisonBombListener: PlayerDropItemEvent " ); + + if ( event.isCancelled() && event.getItemDrop().hasMetadata( "prisonMineBomb" ) ) { + +// event.getItemDrop().getMetadata( "prisonMineBomb" ); + +// event.getItemDrop(). + + event.setCancelled( false ); + } + + } + +// @EventHandler( priority = EventPriority.HIGHEST, ignoreCancelled = false ) +// public void onBlockPlace2( PlayerInteractEvent event ) { +// +// Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent - oof" ); +// } + +// @EventHandler( priority = EventPriority.HIGHEST, ignoreCancelled = false ) + public void onBlockPlace3( BlockPlaceEvent event ) { + + Output.get().logInfo( "### PrisonBombListener: BlockPlaceEvent HIGHEST isCanceled= " + event.isCancelled() ); + +// event.getBlockPlaced(); + + + event.setBuild( true ); + event.setCancelled( false ); + + ItemStack item = event.getItemInHand(); + + + if ( item.hasItemMeta() && item.getItemMeta().hasDisplayName() ) { + ItemMeta meta = item.getItemMeta(); + + Output.get().logInfo( "### PrisonBombListener: BlockPlaceEvent " + meta.getDisplayName() ); + +// meta.getCustomTagContainer().hasCustomTag( null, null ) + +// meta. +// +// Multimap attributes = meta.getAttributeModifiers(); +// +// +// for ( String attri : attributes. ) { +// +// } + + } + + + } + +// @EventHandler( priority = EventPriority.HIGHEST, ignoreCancelled = false ) + public void onBlockPlace3( PlayerInteractEvent event ) { + + Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent " ); + + + } + +// @EventHandler( priority = EventPriority.HIGHEST, ignoreCancelled = false ) +// public void onBlockPlace3( BlockDropItemEvent event ) { +// +// Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent " ); +// +// +// } + +// @EventHandler( priority = EventPriority.HIGHEST ) +// public void onBlockPlace2( Player event ) { +// +// +// if ( event.isCancelled() && event.getItemDrop().hasMetadata( "prisonMineBomb" ) ) { +// +//// event.getItemDrop().getMetadata( "prisonMineBomb" ); +// +//// event.getItemDrop(). +// +// event.setCancelled( false ); +// } +// +// } } From cb46c660736db7f3c1fd2c231d69c534dee6b084 Mon Sep 17 00:00:00 2001 From: AnonymousGCA Date: Wed, 13 Oct 2021 18:50:53 +0200 Subject: [PATCH 083/283] Changelogs: - Fixes to /sellall auto toggle command not being handled correctly in the internal SellAll util. --- .../spigot/commands/PrisonSpigotSellAllCommands.java | 2 +- .../tech/mcprison/prison/spigot/sellall/SellAllUtil.java | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotSellAllCommands.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotSellAllCommands.java index d635719b4..c8be38d4f 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotSellAllCommands.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotSellAllCommands.java @@ -368,7 +368,7 @@ public void sellAllSellWithDelayCommand(CommandSender sender){ } - @Command(identifier = "sellall auto toggle", description = "Let the user enable or disable sellall auto", onlyPlayers = true) + @Command(identifier = "sellall auto toggle", description = "Let the user enable or disable sellall auto", altPermissions = "prison.sellall.toggle", onlyPlayers = true) private void sellAllAutoEnableUser(CommandSender sender){ if (!isEnabled()) return; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java index d0f4d740e..9a90cb4b3 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java @@ -419,6 +419,11 @@ private HashMap getHashMapOfPlayerInventories(Player p) { * @return boolean. * */ public boolean isPlayerAutoSellEnabled(Player p){ + + if (isAutoSellPerUserToggleablePermEnabled && !p.hasPermission(permissionAutoSellPerUserToggleable)){ + return false; + } + if (sellAllConfig.getString("Users." + p.getUniqueId() + ".isEnabled") == null){ return true; } @@ -1271,6 +1276,8 @@ public boolean setAutoSellPlayer(Player p, boolean enable){ e.printStackTrace(); return false; } + + updateConfig(); return true; } From 8a1675f2c5b7015876da6676f3f4542a2e1dfe1d Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 15 Oct 2021 01:04:10 -0400 Subject: [PATCH 084/283] Release the v3.2.11-alpha.2 of prison. --- docs/changelog_v3.3.x.md | 6 +++++- gradle.properties | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 8dfea901b..94cfa7732 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,11 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.1 2021-10-12 +# 3.2.11-alpha.2 2021-10-14 + + + +**3.2.11-alpha.2 2021-10-14** * **A few updates to mine bombs. They have been disabled so they cannot be used.** diff --git a/gradle.properties b/gradle.properties index 6937acf6b..bbda2e2a3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ ## # This is actually the "correct" place to define the version for the project. ## # Used within build.gradle with ${project.version}. ## # Can be overridden on the command line: gradle -Pversion=3.2.1-alpha.3 -version=3.2.11-alpha.1 +version=3.2.11-alpha.2 #version=3.2.8.2 #version=3.3.0-alpha.6 From b6e42fecb80382fc1a90e9f7af44428e8f4e192e Mon Sep 17 00:00:00 2001 From: AnonymousGCA Date: Sat, 16 Oct 2021 00:13:27 +0200 Subject: [PATCH 085/283] Changelogs: - Prestiges GUI fix. --- .../prison/spigot/gui/rank/SpigotPlayerPrestigesGUI.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerPrestigesGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerPrestigesGUI.java index de6ad766c..a7e2ac9d7 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerPrestigesGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerPrestigesGUI.java @@ -169,10 +169,11 @@ public void open() { } } - Button itemrank = new Button(null, playerHasThisRank ? materialHas : materialHasNot, amount++, ranksLore, rank.getTag()); if (playerRank != null && playerRank.equals( rank )){ playerHasThisRank = false; } + + Button itemrank = new Button(null, playerHasThisRank ? materialHas : materialHasNot, amount++, ranksLore, rank.getTag()); if (!(playerHasThisRank)){ if (hackyCounterEnchant <= 0) { hackyCounterEnchant++; From dcd08f20d0173d1e024dc2a7c872fa816f3d1ef3 Mon Sep 17 00:00:00 2001 From: AnonymousGCA Date: Sat, 16 Oct 2021 00:19:59 +0200 Subject: [PATCH 086/283] Changelogs: - Prestiges GUI fix. --- .../gui/rank/SpigotPlayerPrestigesGUI.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerPrestigesGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerPrestigesGUI.java index a7e2ac9d7..c2b7e9cb0 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerPrestigesGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerPrestigesGUI.java @@ -132,14 +132,22 @@ public void open() { } Rank rank = ladder.getLowestRank().get(); - PlayerRank prestigePlayerRank = getRankPlayer().getRank("prestiges"); - Rank playerRank = prestigePlayerRank == null ? null : prestigePlayerRank.getRank(); + XMaterial materialHas; + XMaterial materialHasNot; // Not sure how you want to represent this: - XMaterial materialHas = XMaterial.valueOf(guiConfig.getString("Options.Ranks.Item_gotten_rank")); - XMaterial materialHasNot = XMaterial.valueOf(guiConfig.getString("Options.Ranks.Item_not_gotten_rank")); + try { + materialHas = XMaterial.valueOf(guiConfig.getString("Options.Ranks.Item_gotten_rank")); + } catch (IllegalArgumentException ignored){ + materialHas = XMaterial.TRIPWIRE_HOOK; + } + try { + materialHasNot = XMaterial.valueOf(guiConfig.getString("Options.Ranks.Item_not_gotten_rank")); + } catch (IllegalArgumentException ignored){ + materialHasNot = XMaterial.REDSTONE_BLOCK; + } // Variables. boolean playerHasThisRank = true; From 92a7741de9edf9754ad96642a73a0050aa39b49f Mon Sep 17 00:00:00 2001 From: AnonymousGCA Date: Sat, 16 Oct 2021 00:22:22 +0200 Subject: [PATCH 087/283] Changelogs: - Prestiges GUI fix. --- .../prison/spigot/gui/rank/SpigotPlayerPrestigesGUI.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerPrestigesGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerPrestigesGUI.java index c2b7e9cb0..7efb64069 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerPrestigesGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerPrestigesGUI.java @@ -193,6 +193,9 @@ public void open() { gui.addButton(itemrank); rank = rank.getRankNext(); + if (amount > 45){ + break; + } } ButtonLore rankupLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_rankup), messages.getString(MessagesConfig.StringID.spigot_gui_lore_rankup_if_enough_money)); From 88d16be53dab20e6c59181b6aa66291ed59d3f7a Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Mon, 18 Oct 2021 21:01:06 -0400 Subject: [PATCH 088/283] Add millisecond reporting for the time it takes to handle a block break event. --- docs/changelog_v3.3.x.md | 6 ++++- .../spigot/block/OnBlockBreakEventCore.java | 25 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 94cfa7732..d53cb7faf 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,11 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.2 2021-10-14 +# 3.2.11-alpha.2 2021-10-18 + + + +* **Add millisecond reporting for the time it takes to handle a block break event.** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index 7d0fe44b3..7837e53cf 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -291,6 +291,8 @@ protected void genericBlockEvent( BlockBreakEvent e, boolean monitor, boolean bl return; } + long start = System.currentTimeMillis(); + // Register all external events such as mcMMO and EZBlocks: OnBlockBreakExternalEvents.getInstance().registerAllExternalEvents(); @@ -383,6 +385,9 @@ else if ( pmEvent.getMine() != null || pmEvent.getMine() == null && } + long stop = System.currentTimeMillis(); + debugInfo.append( " [" ).append( stop - start ).append( " ms]" ); + Output.get().logDebug( DebugTarget.blockBreak, debugInfo.toString() ); } @@ -602,6 +607,8 @@ else if ( pmEvent.isMonitor() && mine != null ) { private void genericBlockExplodeEvent( TEBlockExplodeEvent e, boolean monitor, boolean blockEventsOnly, boolean autoManager ) { + long start = System.currentTimeMillis(); + // Register all external events such as mcMMO and EZBlocks: OnBlockBreakExternalEvents.getInstance().registerAllExternalEvents(); @@ -736,6 +743,9 @@ else if ( isTEExplosiveEnabled && } + long stop = System.currentTimeMillis(); + debugInfo.append( " [" ).append( stop - start ).append( " ms]" ); + Output.get().logDebug( DebugTarget.blockBreak, debugInfo.toString() ); } @@ -788,6 +798,8 @@ private String checkCEExplosionTriggered( TEBlockExplodeEvent e ) protected void genericBlastUseEvent( BlastUseEvent e, boolean monitor, boolean blockEventsOnly, boolean autoManager ) { + long start = System.currentTimeMillis(); + // Register all external events such as mcMMO and EZBlocks: OnBlockBreakExternalEvents.getInstance().registerAllExternalEvents(); @@ -929,6 +941,9 @@ else if ( isCEBlockExplodeEnabled && } + long stop = System.currentTimeMillis(); + debugInfo.append( " [" ).append( stop - start ).append( " ms]" ); + Output.get().logDebug( DebugTarget.blockBreak, debugInfo.toString() ); } @@ -950,6 +965,8 @@ else if ( isCEBlockExplodeEnabled && protected void genericExplosiveEvent( PEExplosionEvent e, boolean monitor, boolean blockEventsOnly, boolean autoManager ) { + long start = System.currentTimeMillis(); + // Register all external events such as mcMMO and EZBlocks: OnBlockBreakExternalEvents.getInstance().registerAllExternalEvents(); @@ -1043,6 +1060,9 @@ else if ( isPEExplosiveEnabled && } + long stop = System.currentTimeMillis(); + debugInfo.append( " [" ).append( stop - start ).append( " ms]" ); + Output.get().logDebug( DebugTarget.blockBreak, debugInfo.toString() ); } @@ -1050,6 +1070,8 @@ else if ( isPEExplosiveEnabled && protected void genericExplosiveEvent( ExplosiveBlockBreakEvent e, boolean monitor, boolean blockEventsOnly, boolean autoManager ) { + long start = System.currentTimeMillis(); + // Register all external events such as mcMMO and EZBlocks: OnBlockBreakExternalEvents.getInstance().registerAllExternalEvents(); @@ -1141,6 +1163,9 @@ else if ( isPPrisonExplosiveBlockBreakEnabled && } + long stop = System.currentTimeMillis(); + debugInfo.append( " [" ).append( stop - start ).append( " ms]" ); + Output.get().logDebug( DebugTarget.blockBreak, debugInfo.toString() ); } From 9da566b6d252495a8385969846f10e885aabeca6 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Mon, 18 Oct 2021 21:59:08 -0400 Subject: [PATCH 089/283] Simplified the configuration of the handling of the block break events. Instead of having a separate setting that is a boolean value that indicates it's either enabled or disabled, these are now using the priority value of DISABLED. --- docs/changelog_v3.3.x.md | 3 +++ .../tech/mcprison/prison/PrisonCommand.java | 17 ++++--------- .../autofeatures/AutoFeaturesFileConfig.java | 7 +----- .../prison/spigot/SpigotPlatform.java | 24 +++++++++++++++---- .../events/AutoManagerCrazyEnchants.java | 9 ++++--- .../events/AutoManagerPrisonEnchants.java | 13 ++++++---- ...nagerPrisonsExplosiveBlockBreakEvents.java | 11 +++++---- .../events/AutoManagerTokenEnchant.java | 11 +++++---- .../events/AutoManagerZenchantments.java | 9 ++++--- .../spigot/block/OnBlockBreakEventCore.java | 22 +++++++++++------ 10 files changed, 76 insertions(+), 50 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index d53cb7faf..2d5cd3dba 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.2 2021-10-18 +* **Simplified the configuration of the handling of the block break events.** +Instead of having a separate setting that is a boolean value that indicates it's either enabled or disabled, these are now using the priority value of DISABLED. + * **Add millisecond reporting for the time it takes to handle a block break event.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java b/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java index 9cf417f3f..2946fd814 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java +++ b/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java @@ -885,26 +885,21 @@ public void autoFeaturesInformation(CommandSender sender) { display.addText( "&b " ); - display.addText( "&b options.blockBreakEvents.isProcessTokensEnchantExplosiveEvents: %s", - afw.isBoolean( AutoFeatures.isProcessTokensEnchantExplosiveEvents ) ); display.addText( "&b options.blockBreakEvents.TokenEnchantBlockExplodeEventPriority: %s", - afw.getMessage( AutoFeatures.isProcessTokensEnchantExplosiveEvents ) ); + afw.getMessage( AutoFeatures.TokenEnchantBlockExplodeEventPriority ) ); - display.addText( "&b options.blockBreakEvents.isProcessCrazyEnchantsBlockExplodeEvents: %s", - afw.isBoolean( AutoFeatures.isProcessCrazyEnchantsBlockExplodeEvents ) ); display.addText( "&b options.blockBreakEvents.CrazyEnchantsBlastUseEventPriority: %s", afw.getMessage( AutoFeatures.CrazyEnchantsBlastUseEventPriority ) ); - display.addText( "&b options.blockBreakEvents.isProcessZenchantsBlockExplodeEvents: %s", - afw.isBoolean( AutoFeatures.isProcessZenchantsBlockExplodeEvents ) ); display.addText( "&b options.blockBreakEvents.ZenchantmentsBlockShredEventPriority: %s", afw.getMessage( AutoFeatures.ZenchantmentsBlockShredEventPriority ) ); - display.addText( "&b options.blockBreakEvents.isProcessPrisonEnchantsExplosiveEvents: %s", - afw.isBoolean( AutoFeatures.isProcessPrisonEnchantsExplosiveEvents ) ); display.addText( "&b options.blockBreakEvents.PrisonEnchantsExplosiveEventPriority: %s", afw.getMessage( AutoFeatures.PrisonEnchantsExplosiveEventPriority ) ); + display.addText( "&b options.blockBreakEvents.ProcessPrisons_ExplosiveBlockBreakEventsPriority: %s", + afw.getMessage( AutoFeatures.ProcessPrisons_ExplosiveBlockBreakEventsPriority ) ); + display.addText( "&b " ); display.addText( "&b Normal Drops (if auto pickup is off):" ); @@ -944,10 +939,6 @@ public void autoFeaturesInformation(CommandSender sender) { afw.getMessage( AutoFeatures.fortuneMultiplierMax )); display.addText( "&b " ); - display.addText( "&b options.isProcessTokensEnchantExplosiveEvents %s", - afw.isBoolean( AutoFeatures.isProcessTokensEnchantExplosiveEvents )); - display.addText( "&b options.isProcessCrazyEnchantsBlockExplodeEvents %s", - afw.isBoolean( AutoFeatures.isProcessCrazyEnchantsBlockExplodeEvents )); display.addText( "&b options.isProcessMcMMOBlockBreakEvents %s", afw.isBoolean( AutoFeatures.isProcessMcMMOBlockBreakEvents )); display.addText( "&b " ); diff --git a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java index a711d2cd7..4fc6ea770 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java +++ b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java @@ -52,26 +52,21 @@ public enum AutoFeatures { // Setting this to true will cancel the block break events (normal prison behavior): cancelAllBlockBreakEvents(blockBreakEvents, true), // Setting this to false will not zero out the block drops (normal prison behavior). - // When set to true, it will zero it out so if the block break event is not cancleed, + // When set to true, it will zero it out so if the block break event is not canceled, // then it will prevent double drops: cancelAllBlockEventBlockDrops(blockBreakEvents, false), blockBreakEventPriority(blockBreakEvents, "LOW"), - isProcessTokensEnchantExplosiveEvents(blockBreakEvents, false), TokenEnchantBlockExplodeEventPriority(blockBreakEvents, "DISABLED"), - isProcessCrazyEnchantsBlockExplodeEvents(blockBreakEvents, false), CrazyEnchantsBlastUseEventPriority(blockBreakEvents, "DISABLED"), - isProcessZenchantsBlockExplodeEvents(blockBreakEvents, false), ZenchantmentsBlockShredEventPriority(blockBreakEvents, "DISABLED"), - isProcessPrisonEnchantsExplosiveEvents(blockBreakEvents, false), PrisonEnchantsExplosiveEventPriority(blockBreakEvents, "DISABLED"), - isProcessPrisons_ExplosiveBlockBreakEvents(blockBreakEvents, false), ProcessPrisons_ExplosiveBlockBreakEventsPriority(blockBreakEvents, "DISABLED"), diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java index 3238d249d..f4003f495 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java @@ -1870,13 +1870,27 @@ public List getActiveFeatures() { if ( isAutoManagerEnabled ) { + + + boolean bbeCabbe = afw.isBoolean( AutoFeatures.cancelAllBlockBreakEvents ); + results.add( String.format(". Cancel all Block Break Events:&b %s", + Boolean.toString( bbeCabbe ) ) ); + + + boolean bbeCabebd = afw.isBoolean( AutoFeatures.cancelAllBlockEventBlockDrops ); + results.add( String.format(". Cancel All Block Break Events Block Drops:&b %s", + Boolean.toString( bbeCabebd ) ) ); + + + + String bbePriority = afw.getMessage( AutoFeatures.blockBreakEventPriority ); BlockBreakPriority blockBreakPriority = BlockBreakPriority.fromString( bbePriority ); results.add( String.format(". '&7org.bukkit.BlockBreakEvent&3' Priority:&b %s", blockBreakPriority.name() ) ); String pebbePriority = afw.getMessage( AutoFeatures.ProcessPrisons_ExplosiveBlockBreakEventsPriority ); - boolean isPebbeEnabled = afw.isBoolean( AutoFeatures.isProcessPrisons_ExplosiveBlockBreakEvents ); + boolean isPebbeEnabled = pebbePriority != null && !"DISABLED".equalsIgnoreCase( pebbePriority ); BlockBreakPriority pebbeEventPriority = BlockBreakPriority.fromString( pebbePriority ); results.add( String.format("%s. Prison's own '&7ExplosiveBlockBreakEvent&3' Priority:&b %s %s", (isPebbeEnabled ? "" : "+" ), @@ -1885,7 +1899,7 @@ public List getActiveFeatures() { ) ); String peeePriority = afw.getMessage( AutoFeatures.PrisonEnchantsExplosiveEventPriority ); - boolean isPeeeEnabled = afw.isBoolean( AutoFeatures.isProcessPrisonEnchantsExplosiveEvents ); + boolean isPeeeEnabled = peeePriority != null && !"DISABLED".equalsIgnoreCase( peeePriority ); BlockBreakPriority peeeEventPriority = BlockBreakPriority.fromString( peeePriority ); results.add( String.format("%s. Pulsi_'s PrisonEnchants '&7PEExplosiveEvent&3' Priority:&b %s %s", (isPeeeEnabled ? "" : "+" ), @@ -1894,7 +1908,7 @@ public List getActiveFeatures() { ) ); String tebePriority = afw.getMessage( AutoFeatures.TokenEnchantBlockExplodeEventPriority ); - boolean isTebeEnabled = afw.isBoolean( AutoFeatures.isProcessTokensEnchantExplosiveEvents ); + boolean isTebeEnabled = tebePriority != null && !"DISABLED".equalsIgnoreCase( tebePriority ); BlockBreakPriority tebEventPriority = BlockBreakPriority.fromString( tebePriority ); results.add( String.format("%s. TokenEnchant '&7BlockExplodeEvent&3' Priority:&b %s %s", (isTebeEnabled ? "" : "+" ), @@ -1903,7 +1917,7 @@ public List getActiveFeatures() { ) ); String cebuePriority = afw.getMessage( AutoFeatures.CrazyEnchantsBlastUseEventPriority ); - boolean isCebueEnabled = afw.isBoolean( AutoFeatures.isProcessCrazyEnchantsBlockExplodeEvents ); + boolean isCebueEnabled = cebuePriority != null && !"DISABLED".equalsIgnoreCase( cebuePriority ); BlockBreakPriority cebuEventPriority = BlockBreakPriority.fromString( cebuePriority ); results.add( String.format("%s. CrazyEnchant '&7BlastUseEvent&3' Priority:&b %s %s", (isCebueEnabled ? "" : "+" ), @@ -1912,7 +1926,7 @@ public List getActiveFeatures() { ) ); String zbsePriority = afw.getMessage( AutoFeatures.ZenchantmentsBlockShredEventPriority ); - boolean isZbseEnabled = afw.isBoolean( AutoFeatures.isProcessZenchantsBlockExplodeEvents ); + boolean isZbseEnabled = zbsePriority != null && !"DISABLED".equalsIgnoreCase( zbsePriority ); BlockBreakPriority zbsEventPriority = BlockBreakPriority.fromString( zbsePriority ); results.add( String.format("%s. Zenchantments '&7BlockShredEvent&3' Priority:&b %s %s", (isZbseEnabled ? "" : "+" ), diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerCrazyEnchants.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerCrazyEnchants.java index 2b988874d..fdf09e653 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerCrazyEnchants.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerCrazyEnchants.java @@ -66,7 +66,9 @@ public void onCrazyEnchantsBlockExplode(BlastUseEvent e) { @Override public void initialize() { - boolean isEventEnabled = isBoolean( AutoFeatures.isProcessCrazyEnchantsBlockExplodeEvents ); + + String eP = getMessage( AutoFeatures.CrazyEnchantsBlastUseEventPriority ); + boolean isEventEnabled = eP != null && !"DISABLED".equalsIgnoreCase( eP ); if ( !isEventEnabled ) { return; @@ -81,7 +83,6 @@ public void initialize() { Output.get().logInfo( "AutoManager: Trying to register CrazyEnchants" ); - String eP = getMessage( AutoFeatures.CrazyEnchantsBlastUseEventPriority ); BlockBreakPriority eventPriority = BlockBreakPriority.fromString( eP ); if ( eventPriority != BlockBreakPriority.DISABLED ) { @@ -188,8 +189,10 @@ public void dumpEventListeners() { @Override public void dumpEventListeners( StringBuilder sb ) { - boolean isEventEnabled = isBoolean( AutoFeatures.isProcessCrazyEnchantsBlockExplodeEvents ); + String eP = getMessage( AutoFeatures.CrazyEnchantsBlastUseEventPriority ); + boolean isEventEnabled = eP != null && !"DISABLED".equalsIgnoreCase( eP ); + if ( !isEventEnabled ) { return; } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonEnchants.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonEnchants.java index 4f0a2f493..cee4721d2 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonEnchants.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonEnchants.java @@ -69,8 +69,10 @@ public void onPrisonEnchantsExplosiveEvent(PEExplosionEvent e) { @Override public void initialize() { - boolean isEventEnabled = isBoolean( AutoFeatures.isProcessPrisonEnchantsExplosiveEvents ); - + + String eP = getMessage( AutoFeatures.PrisonEnchantsExplosiveEventPriority ); + boolean isEventEnabled = eP != null && !"DISABLED".equalsIgnoreCase( eP ); + if ( !isEventEnabled ) { return; } @@ -85,7 +87,6 @@ public void initialize() { Output.get().logInfo( "AutoManager: Trying to register Pulsi_'s PrisonEnchants" ); - String eP = getMessage( AutoFeatures.PrisonEnchantsExplosiveEventPriority ); BlockBreakPriority eventPriority = BlockBreakPriority.fromString( eP ); if ( eventPriority != BlockBreakPriority.DISABLED ) { @@ -187,8 +188,10 @@ public void dumpEventListeners() { @Override public void dumpEventListeners( StringBuilder sb ) { - boolean isEventEnabled = isBoolean( AutoFeatures.isProcessPrisonEnchantsExplosiveEvents ); - + + String eP = getMessage( AutoFeatures.PrisonEnchantsExplosiveEventPriority ); + boolean isEventEnabled = eP != null && !"DISABLED".equalsIgnoreCase( eP ); + if ( !isEventEnabled ) { return; } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonsExplosiveBlockBreakEvents.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonsExplosiveBlockBreakEvents.java index e630a7778..a612ee66d 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonsExplosiveBlockBreakEvents.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonsExplosiveBlockBreakEvents.java @@ -70,8 +70,10 @@ public void onPrisonExplosiveBlockBreakEventMonitor(ExplosiveBlockBreakEvent e) @Override public void initialize() { - boolean isEventEnabled = isBoolean( AutoFeatures.isProcessPrisons_ExplosiveBlockBreakEvents ); + String eP = getMessage( AutoFeatures.ProcessPrisons_ExplosiveBlockBreakEventsPriority ); + boolean isEventEnabled = eP != null && !"DISABLED".equalsIgnoreCase( eP ); + if ( !isEventEnabled ) { return; } @@ -81,7 +83,6 @@ public void initialize() { Output.get().logInfo( "AutoManager: Trying to register ExplosiveBlockBreakEvent Listener" ); - String eP = getMessage( AutoFeatures.ProcessPrisons_ExplosiveBlockBreakEventsPriority ); BlockBreakPriority eventPriority = BlockBreakPriority.fromString( eP ); if ( eventPriority != BlockBreakPriority.DISABLED ) { @@ -179,8 +180,10 @@ public void dumpEventListeners() { @Override public void dumpEventListeners( StringBuilder sb ) { - boolean isEventEnabled = isBoolean( AutoFeatures.isProcessPrisonEnchantsExplosiveEvents ); - + + String eP = getMessage( AutoFeatures.ProcessPrisons_ExplosiveBlockBreakEventsPriority ); + boolean isEventEnabled = eP != null && !"DISABLED".equalsIgnoreCase( eP ); + if ( !isEventEnabled ) { return; } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerTokenEnchant.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerTokenEnchant.java index 4f07af864..566ed6785 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerTokenEnchant.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerTokenEnchant.java @@ -67,8 +67,10 @@ public void onTEBlockExplode(TEBlockExplodeEvent e) { @Override public void initialize() { - boolean isEventEnabled = isBoolean( AutoFeatures.isProcessTokensEnchantExplosiveEvents ); - + + String eP = getMessage( AutoFeatures.TokenEnchantBlockExplodeEventPriority ); + boolean isEventEnabled = eP != null && !"DISABLED".equalsIgnoreCase( eP ); + if ( !isEventEnabled ) { return; } @@ -83,7 +85,6 @@ public void initialize() { Output.get().logInfo( "AutoManager: Trying to register TokenEnchant" ); - String eP = getMessage( AutoFeatures.TokenEnchantBlockExplodeEventPriority ); BlockBreakPriority eventPriority = BlockBreakPriority.fromString( eP ); if ( eventPriority != BlockBreakPriority.DISABLED ) { @@ -182,8 +183,10 @@ public void dumpEventListeners() { @Override public void dumpEventListeners( StringBuilder sb ) { - boolean isEventEnabled = isBoolean( AutoFeatures.isProcessTokensEnchantExplosiveEvents ); + String eP = getMessage( AutoFeatures.TokenEnchantBlockExplodeEventPriority ); + boolean isEventEnabled = eP != null && !"DISABLED".equalsIgnoreCase( eP ); + if ( !isEventEnabled ) { return; } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerZenchantments.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerZenchantments.java index 99ac0bb91..9301fb23d 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerZenchantments.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerZenchantments.java @@ -67,8 +67,10 @@ public void onBlockShredBreakMonitor(BlockShredEvent e) { @Override public void initialize() { - boolean isEventEnabled = isBoolean( AutoFeatures.isProcessZenchantsBlockExplodeEvents ); + String eP = getMessage( AutoFeatures.ZenchantmentsBlockShredEventPriority ); + boolean isEventEnabled = eP != null && !"DISABLED".equalsIgnoreCase( eP ); + if ( !isEventEnabled ) { return; } @@ -83,7 +85,6 @@ public void initialize() { Output.get().logInfo( "AutoManager: Trying to register Zenchantments" ); - String eP = getMessage( AutoFeatures.ZenchantmentsBlockShredEventPriority ); BlockBreakPriority eventPriority = BlockBreakPriority.fromString( eP ); if ( eventPriority != BlockBreakPriority.DISABLED ) { @@ -195,7 +196,9 @@ public void dumpEventListeners() { @Override public void dumpEventListeners( StringBuilder sb ) { - boolean isEventEnabled = isBoolean( AutoFeatures.isProcessZenchantsBlockExplodeEvents ); + + String eP = getMessage( AutoFeatures.ZenchantmentsBlockShredEventPriority ); + boolean isEventEnabled = eP != null && !"DISABLED".equalsIgnoreCase( eP ); if ( !isEventEnabled ) { return; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index 7837e53cf..46a3138ad 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -624,7 +624,10 @@ private void genericBlockExplodeEvent( TEBlockExplodeEvent e, boolean monitor, b // NOTE that check for auto manager has happened prior to accessing this function. if ( !monitor && !e.isCancelled() || monitor ) { - boolean isTEExplosiveEnabled = isBoolean( AutoFeatures.isProcessTokensEnchantExplosiveEvents ); + + String eP = getMessage( AutoFeatures.TokenEnchantBlockExplodeEventPriority ); + boolean isTEExplosiveEnabled = eP != null && !"DISABLED".equalsIgnoreCase( eP ); + // Need to wrap in a Prison block so it can be used with the mines: SpigotBlock sBlock = new SpigotBlock(e.getBlock()); @@ -816,8 +819,11 @@ protected void genericBlastUseEvent( BlastUseEvent e, boolean monitor, boolean b if ( (!monitor && !e.isCancelled() || monitor) && e.getBlockList().size() > 0 ) { - boolean isCEBlockExplodeEnabled = isBoolean( AutoFeatures.isProcessCrazyEnchantsBlockExplodeEvents ); - + + String eP = getMessage( AutoFeatures.CrazyEnchantsBlastUseEventPriority ); + boolean isCEBlockExplodeEnabled = eP != null && !"DISABLED".equalsIgnoreCase( eP ); + + Block bukkitBlock = e.getBlockList().get( 0 ); // Need to wrap in a Prison block so it can be used with the mines: @@ -983,8 +989,9 @@ protected void genericExplosiveEvent( PEExplosionEvent e, boolean monitor, boole if ( !monitor && !e.isCancelled() || monitor ) { - boolean isPEExplosiveEnabled = isBoolean( AutoFeatures.isProcessPrisonEnchantsExplosiveEvents ); - + String eP = getMessage( AutoFeatures.PrisonEnchantsExplosiveEventPriority ); + boolean isPEExplosiveEnabled = eP != null && !"DISABLED".equalsIgnoreCase( eP ); + // Need to wrap in a Prison block so it can be used with the mines: SpigotBlock sBlock = new SpigotBlock(e.getBlockBroken()); @@ -1088,8 +1095,9 @@ protected void genericExplosiveEvent( ExplosiveBlockBreakEvent e, boolean monito if ( !monitor && !e.isCancelled() || monitor ) { - boolean isPPrisonExplosiveBlockBreakEnabled = isBoolean( AutoFeatures.isProcessPrisons_ExplosiveBlockBreakEvents ); - + String eP = getMessage( AutoFeatures.ProcessPrisons_ExplosiveBlockBreakEventsPriority ); + boolean isPPrisonExplosiveBlockBreakEnabled = eP != null && !"DISABLED".equalsIgnoreCase( eP ); + // Need to wrap in a Prison block so it can be used with the mines: SpigotBlock sBlock = new SpigotBlock(e.getBlock()); From 4ffe8dea836f966d7026acf99198c83bc2b35ef3 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Mon, 18 Oct 2021 22:05:13 -0400 Subject: [PATCH 090/283] Enable the ability to choose between setting the block to air inline, or through submitting a synch task to allow the blockBreak event handler to finish quicker, which may reduce lag. --- docs/changelog_v3.3.x.md | 3 ++ .../tech/mcprison/prison/PrisonCommand.java | 11 ++++++ .../autofeatures/AutoFeaturesFileConfig.java | 3 ++ .../prison/spigot/SpigotPlatform.java | 5 +++ .../autofeatures/AutoManagerFeatures.java | 34 ++++++++++++++----- 5 files changed, 48 insertions(+), 8 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 2d5cd3dba..8c3863c13 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.2 2021-10-18 +* **Enable the ability to choose between setting the block to air inline, or through submitting a synch task to allow the blockBreak event handler to finish quicker, which may reduce lag.** + + * **Simplified the configuration of the handling of the block break events.** Instead of having a separate setting that is a boolean value that indicates it's either enabled or disabled, these are now using the priority value of DISABLED. diff --git a/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java b/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java index 2946fd814..8ebb5bab0 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java +++ b/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java @@ -885,6 +885,16 @@ public void autoFeaturesInformation(CommandSender sender) { display.addText( "&b " ); + display.addText( "&b options.blockBreakEvents.applyBlockBreaksThroughSyncTask: %s", + afw.getMessage( AutoFeatures.applyBlockBreaksThroughSyncTask ) ); + + display.addText( "&b options.blockBreakEvents.cancelAllBlockBreakEvents: %s", + afw.getMessage( AutoFeatures.cancelAllBlockBreakEvents ) ); + + display.addText( "&b options.blockBreakEvents.cancelAllBlockEventBlockDrops: %s", + afw.getMessage( AutoFeatures.cancelAllBlockEventBlockDrops ) ); + + display.addText( "&b options.blockBreakEvents.TokenEnchantBlockExplodeEventPriority: %s", afw.getMessage( AutoFeatures.TokenEnchantBlockExplodeEventPriority ) ); @@ -901,6 +911,7 @@ public void autoFeaturesInformation(CommandSender sender) { afw.getMessage( AutoFeatures.ProcessPrisons_ExplosiveBlockBreakEventsPriority ) ); + display.addText( "&b " ); display.addText( "&b Normal Drops (if auto pickup is off):" ); display.addText( "&b options.normalDrop.isProcessNormalDropsEvents: %s", diff --git a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java index 4fc6ea770..78257ff5b 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java +++ b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java @@ -55,6 +55,9 @@ public enum AutoFeatures { // When set to true, it will zero it out so if the block break event is not canceled, // then it will prevent double drops: cancelAllBlockEventBlockDrops(blockBreakEvents, false), + + + applyBlockBreaksThroughSyncTask(blockBreakEvents, true), blockBreakEventPriority(blockBreakEvents, "LOW"), diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java index f4003f495..b5169cb00 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java @@ -1872,6 +1872,11 @@ public List getActiveFeatures() { + boolean bbeAbbtst = afw.isBoolean( AutoFeatures.applyBlockBreaksThroughSyncTask ); + results.add( String.format(". Apply Block Breaks through Sync Tasks:&b %s", + Boolean.toString( bbeAbbtst ) ) ); + + boolean bbeCabbe = afw.isBoolean( AutoFeatures.cancelAllBlockBreakEvents ); results.add( String.format(". Cancel all Block Break Events:&b %s", Boolean.toString( bbeCabbe ) ) ); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java index c52c9e03d..8514ab5ab 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java @@ -560,8 +560,18 @@ public int calculateNormalDrop( SpigotItemStack itemInHand, SpigotBlock block ) // Break the block and change it to air: - AutoManagerBreakBlockTask.submitTask( block ); -// block.setPrisonBlock( PrisonBlock.AIR ); + if ( !block.isEmpty() ) { + + if ( isBoolean( AutoFeatures.applyBlockBreaksThroughSyncTask ) ) { + + AutoManagerBreakBlockTask.submitTask( block ); + } + else { + + block.setPrisonBlock( PrisonBlock.AIR ); + } + + } } return count; @@ -689,13 +699,21 @@ protected void autoPickupCleanup( SpigotBlock block, int count ) // Auto pickup has been successful. Now clean up. if ( count > 0 ) { - // submit a task to change the block to air: - AutoManagerBreakBlockTask.submitTask( block ); -//// // Set the broken block to AIR and cancel the event -// if ( !block.isEmpty() ) { -// block.setPrisonBlock( PrisonBlock.AIR ); -// } +// // Set the broken block to AIR and cancel the event + if ( !block.isEmpty() ) { + + if ( isBoolean( AutoFeatures.applyBlockBreaksThroughSyncTask ) ) { + + // submit a task to change the block to air: + AutoManagerBreakBlockTask.submitTask( block ); + } + + else { + + block.setPrisonBlock( PrisonBlock.AIR ); + } + } } } From ae7779618d733588d014fcdec65c8de09a625bba Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Wed, 20 Oct 2021 22:32:42 -0400 Subject: [PATCH 091/283] Increased to version 3.2.11-alpha.3 a few days ago but forgot to commit. --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index bbda2e2a3..d31a44bd3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ ## # This is actually the "correct" place to define the version for the project. ## # Used within build.gradle with ${project.version}. ## # Can be overridden on the command line: gradle -Pversion=3.2.1-alpha.3 -version=3.2.11-alpha.2 +version=3.2.11-alpha.3 #version=3.2.8.2 #version=3.3.0-alpha.6 From 2c4885304b7513ae68ee6414913bd7a965c43fee Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Wed, 20 Oct 2021 22:34:38 -0400 Subject: [PATCH 092/283] Bug Fix: When using block constraints, there was a common situation where an AIR block was being used in the top layers because all other blocks were being rejected due to chance. Order of blocks had an impact on this error, when it shouldn't. Now, if a block cannot be selected, the first block with no constraint issue will be used instead. Also found a bug in the applying of the chance to each block. Under some situations, the percent chance was not being reduced for a bypassed block, when it should have. This now will better select the blocks, and better preserve their intended percentage odds of being spawned. --- docs/changelog_v3.3.x.md | 9 ++- .../mcprison/prison/mines/data/MineReset.java | 56 ++++++++++++++----- 2 files changed, 50 insertions(+), 15 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 8c3863c13..de9b3a79d 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,14 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.2 2021-10-18 +# 3.2.11-alpha.3 2021-10-20 + + + +* **Bug Fix: When using block constraints,** there was a common situation where an AIR block was being used in the top layers because all other blocks were being rejected due to chance. Order of blocks had an impact on this error, when it shouldn't. Now, if a block cannot be selected, the first block with no constraint issue will be used instead. Also found a bug in the applying of the chance to each block. Under some situations, the percent chance was not being reduced for a bypassed block, when it should have. This now will better select the blocks, and better preserve their intended percentage odds of being spawned. + + +**Prison v3.2.11-alpha.3 2021-10-18** * **Enable the ability to choose between setting the block to air inline, or through submitting a synch task to allow the blockBreak event handler to finish quicker, which may reduce lag.** diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java index 5fb34690e..7bef72666 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java @@ -1484,6 +1484,13 @@ private PrisonBlock randomlySelectPrisonBlock( Random random, int currentLevel ) PrisonBlock prisonBlock = Prison.get().getPlatform().getPrisonBlock( "AIR" ); + + // this fallbackBlock field will provide a valid block that can be used when all other + // blocks have failed to be matched due to constraints not aligning with the random chance. + // As a result of failing to find a block, would result in an AIR block being used instead. + PrisonBlock fallbackBlock = null; + + // If a chosen block was skipped, try to find another block, but try no more than 10 times // to prevent a possible endless loop. Side effects of failing to find a block in 10 attempts // would be an air block. @@ -1495,23 +1502,30 @@ private PrisonBlock randomlySelectPrisonBlock( Random random, int currentLevel ) for (PrisonBlock block : getPrisonBlocks()) { boolean isBlockEnabled = block.isBlockConstraintsEnbled( currentLevel, targetBlockPosition ); - if ( chance <= block.getChance() ) { + if ( fallbackBlock == null && isBlockEnabled && !block.isAir() ) { + fallbackBlock = block; + } + + if ( chance <= block.getChance() && isBlockEnabled ) { // If this block is chosen and it was not skipped, then use this block and exit. // Otherwise the chance will be recalculated and tried again to find a valid block, // since the odds have been thrown off... - if ( isBlockEnabled ) { - prisonBlock = block; - - // stop trying to locate a block so success will terminate the search: - success = true; - } + prisonBlock = block; + + // stop trying to locate a block so success will terminate the search: + success = true; break; } else { chance -= block.getChance(); } } + + if ( !success && fallbackBlock != null ) { + prisonBlock = fallbackBlock; + success = true; + } } return prisonBlock; } @@ -1522,6 +1536,14 @@ private BlockOld randomlySelectBlock( Random random, int currentLevel ) { BlockOld results = BlockOld.AIR; + + // this fallbackBlock field will provide a valid block that can be used when all other + // blocks have failed to be matched due to constraints not aligning with the random chance. + // As a result of failing to find a block, would result in an AIR block being used instead. + BlockOld fallbackBlock = null; + + + // If a chosen block was skipped, try to find another block, but try no more than 10 times // to prevent a possible endless loop. Side effects of failing to find a block in 10 attempts // would be an air block. @@ -1533,17 +1555,19 @@ private BlockOld randomlySelectBlock( Random random, int currentLevel ) { for (BlockOld block : getBlocks()) { boolean isBlockEnabled = block.isBlockConstraintsEnbled( currentLevel, targetBlockPosition ); - if ( chance <= block.getChance() ) { + if ( fallbackBlock == null && isBlockEnabled && !block.isAir() ) { + fallbackBlock = block; + } + + if ( chance <= block.getChance() && isBlockEnabled ) { // If this block is chosen and it was not skipped, then use this block and exit. // Otherwise the chance will be recalculated and tried again to find a valid block, // since the odds have been thrown off... - if ( isBlockEnabled ) { - results = block; - - // stop trying to locate a block so success will terminate the search: - success = true; - } + results = block; + + // stop trying to locate a block so success will terminate the search: + success = true; break; } else { @@ -1552,6 +1576,10 @@ private BlockOld randomlySelectBlock( Random random, int currentLevel ) { } } + if ( !success && fallbackBlock != null ) { + results = fallbackBlock; + success = true; + } // for (BlockOld block : getBlocks()) { // if (block.checkConstraints( currentLevel, targetBlockPosition ) && From c76ff03b2a65266934f48e95bd88b8050e5e9e19 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Wed, 20 Oct 2021 22:39:25 -0400 Subject: [PATCH 093/283] Switched prison block debugging timing to use nanoTime instead of milliseconds since milliseconds is too large of a unit. --- docs/changelog_v3.3.x.md | 2 ++ .../spigot/block/OnBlockBreakEventCore.java | 30 +++++++++---------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index de9b3a79d..41ff75bbb 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,8 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.3 2021-10-20 +* **Switched prison block debugging timing to use nanoTime instead of milliseconds since milliseconds is too large of a unit.** + * **Bug Fix: When using block constraints,** there was a common situation where an AIR block was being used in the top layers because all other blocks were being rejected due to chance. Order of blocks had an impact on this error, when it shouldn't. Now, if a block cannot be selected, the first block with no constraint issue will be used instead. Also found a bug in the applying of the chance to each block. Under some situations, the percent chance was not being reduced for a bypassed block, when it should have. This now will better select the blocks, and better preserve their intended percentage odds of being spawned. diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index 46a3138ad..08d984aae 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -291,7 +291,7 @@ protected void genericBlockEvent( BlockBreakEvent e, boolean monitor, boolean bl return; } - long start = System.currentTimeMillis(); + long start = System.nanoTime(); // Register all external events such as mcMMO and EZBlocks: OnBlockBreakExternalEvents.getInstance().registerAllExternalEvents(); @@ -385,8 +385,8 @@ else if ( pmEvent.getMine() != null || pmEvent.getMine() == null && } - long stop = System.currentTimeMillis(); - debugInfo.append( " [" ).append( stop - start ).append( " ms]" ); + long stop = System.nanoTime(); + debugInfo.append( " [" ).append( (stop - start) / 1000000d ).append( " ms]" ); Output.get().logDebug( DebugTarget.blockBreak, debugInfo.toString() ); } @@ -607,7 +607,7 @@ else if ( pmEvent.isMonitor() && mine != null ) { private void genericBlockExplodeEvent( TEBlockExplodeEvent e, boolean monitor, boolean blockEventsOnly, boolean autoManager ) { - long start = System.currentTimeMillis(); + long start = System.nanoTime(); // Register all external events such as mcMMO and EZBlocks: OnBlockBreakExternalEvents.getInstance().registerAllExternalEvents(); @@ -746,8 +746,8 @@ else if ( isTEExplosiveEnabled && } - long stop = System.currentTimeMillis(); - debugInfo.append( " [" ).append( stop - start ).append( " ms]" ); + long stop = System.nanoTime(); + debugInfo.append( " [" ).append( (stop - start) / 1000000d ).append( " ms]" ); Output.get().logDebug( DebugTarget.blockBreak, debugInfo.toString() ); } @@ -801,7 +801,7 @@ private String checkCEExplosionTriggered( TEBlockExplodeEvent e ) protected void genericBlastUseEvent( BlastUseEvent e, boolean monitor, boolean blockEventsOnly, boolean autoManager ) { - long start = System.currentTimeMillis(); + long start = System.nanoTime(); // Register all external events such as mcMMO and EZBlocks: OnBlockBreakExternalEvents.getInstance().registerAllExternalEvents(); @@ -947,8 +947,8 @@ else if ( isCEBlockExplodeEnabled && } - long stop = System.currentTimeMillis(); - debugInfo.append( " [" ).append( stop - start ).append( " ms]" ); + long stop = System.nanoTime(); + debugInfo.append( " [" ).append( (stop - start) / 1000000d ).append( " ms]" ); Output.get().logDebug( DebugTarget.blockBreak, debugInfo.toString() ); @@ -971,7 +971,7 @@ else if ( isCEBlockExplodeEnabled && protected void genericExplosiveEvent( PEExplosionEvent e, boolean monitor, boolean blockEventsOnly, boolean autoManager ) { - long start = System.currentTimeMillis(); + long start = System.nanoTime(); // Register all external events such as mcMMO and EZBlocks: OnBlockBreakExternalEvents.getInstance().registerAllExternalEvents(); @@ -1067,8 +1067,8 @@ else if ( isPEExplosiveEnabled && } - long stop = System.currentTimeMillis(); - debugInfo.append( " [" ).append( stop - start ).append( " ms]" ); + long stop = System.nanoTime(); + debugInfo.append( " [" ).append( (stop - start) / 1000000d ).append( " ms]" ); Output.get().logDebug( DebugTarget.blockBreak, debugInfo.toString() ); @@ -1077,7 +1077,7 @@ else if ( isPEExplosiveEnabled && protected void genericExplosiveEvent( ExplosiveBlockBreakEvent e, boolean monitor, boolean blockEventsOnly, boolean autoManager ) { - long start = System.currentTimeMillis(); + long start = System.nanoTime(); // Register all external events such as mcMMO and EZBlocks: OnBlockBreakExternalEvents.getInstance().registerAllExternalEvents(); @@ -1171,8 +1171,8 @@ else if ( isPPrisonExplosiveBlockBreakEnabled && } - long stop = System.currentTimeMillis(); - debugInfo.append( " [" ).append( stop - start ).append( " ms]" ); + long stop = System.nanoTime(); + debugInfo.append( " [" ).append( (stop - start) / 1000000d ).append( " ms]" ); Output.get().logDebug( DebugTarget.blockBreak, debugInfo.toString() ); From 40cee1460fb44539755c7418c9347162aaac230f Mon Sep 17 00:00:00 2001 From: AnonymousGCA Date: Thu, 21 Oct 2021 09:27:38 +0200 Subject: [PATCH 094/283] Changelogs: - SellAll Sell potions error fix. --- docs/changelog_v3.3.x.md | 6 ++++ .../prison/spigot/sellall/SellAllUtil.java | 30 +++++++++++-------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 41ff75bbb..f056bf1db 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,12 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.3 2021-10-20 +* **Fix for Potion IllegalArgumentException:** Fixed an error with potions in Player inventories when +using sellall sell, potions aren't supported by now and won't be sold, but at least it won't break +sellall anymore. + + + * **Switched prison block debugging timing to use nanoTime instead of milliseconds since milliseconds is too large of a unit.** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java index 9a90cb4b3..3a31913ee 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java @@ -221,12 +221,14 @@ public HashMap getXMaterialsHashMapFromArrayList(ArrayList xMaterialIntegerHashMap = new HashMap<>(); for (ItemStack itemStack : itemStacks){ if (itemStack != null){ - XMaterial xMaterial = getXMaterialOrLapis(itemStack); - if (xMaterialIntegerHashMap.containsKey(xMaterial) && xMaterialIntegerHashMap.get(xMaterial) != 0){ - xMaterialIntegerHashMap.put(xMaterial, xMaterialIntegerHashMap.get(xMaterial) + itemStack.getAmount()); - } else { - xMaterialIntegerHashMap.put(xMaterial, itemStack.getAmount()); - } + try { + XMaterial xMaterial = getXMaterialOrLapis(itemStack); + if (xMaterialIntegerHashMap.containsKey(xMaterial) && xMaterialIntegerHashMap.get(xMaterial) != 0) { + xMaterialIntegerHashMap.put(xMaterial, xMaterialIntegerHashMap.get(xMaterial) + itemStack.getAmount()); + } else { + xMaterialIntegerHashMap.put(xMaterial, itemStack.getAmount()); + } + } catch (IllegalArgumentException ignored){} } } @@ -1125,14 +1127,16 @@ public Inventory removeSellableItems(Player p, Inventory inv){ for (ItemStack itemStack : inv.getContents()){ if (itemStack != null){ - XMaterial xMaterial = getXMaterialOrLapis(itemStack); - if (sellAllBlocks.containsKey(xMaterial)){ - if (isPerBlockPermissionEnabled && !p.hasPermission(permissionPrefixBlocks + xMaterial.name())){ - // Nothing will change. - } else { - inv.remove(itemStack); + try { + XMaterial xMaterial = getXMaterialOrLapis(itemStack); + if (sellAllBlocks.containsKey(xMaterial)) { + if (isPerBlockPermissionEnabled && !p.hasPermission(permissionPrefixBlocks + xMaterial.name())) { + // Nothing will change. + } else { + inv.remove(itemStack); + } } - } + } catch (IllegalArgumentException ignored){} } } From b32fd02630cb58c233243f9e0657a9546715428d Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Thu, 21 Oct 2021 14:01:37 -0400 Subject: [PATCH 095/283] Cloning a bomb was not complete. Some details were omitted. --- docs/changelog_v3.3.x.md | 5 ++++- .../main/java/tech/mcprison/prison/bombs/MineBombData.java | 6 ++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index f056bf1db..41ce909bb 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,10 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.3 2021-10-20 +# 3.2.11-alpha.3 2021-10-21 + + +* **Cloning a bomb was not complete. Some details were omitted.** * **Fix for Potion IllegalArgumentException:** Fixed an error with potions in Player inventories when diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java index 034c0cb1f..71d4557a9 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java @@ -82,9 +82,15 @@ public MineBombData( String name, String itemType, String explosionShape, public MineBombData clone() { MineBombData cloned = new MineBombData( getName(), getItemType(), getExplosionShape(), getRadius() ); + + cloned.setDescription( getDescription() ); + cloned.setGlowing( isGlowing() ); + cloned.setActivated( isActivated() ); + for ( String l : lore ) { cloned.getLore().add( l ); } + return cloned; } From 0f235b6b695fc87818c829e2d8e355ae3800d091 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sat, 23 Oct 2021 20:27:55 -0400 Subject: [PATCH 096/283] Async Mine Reset performance Improvements. Adjustments were made to improve the performance of the asynch mine resets by providing the ability to fine tune the page sizes, and also provide the ability to reset more than one block in the synchronous thread at a time. This is called a slice. Measuring the actual block reset time with nanos for better resolution. MineTargetBlockKey class was relocated to allow for the use of sub listings on the synchronized block updates. --- docs/changelog_v3.3.x.md | 6 +- .../internal/PrisonStatsElapsedTimeNanos.java | 28 +++++ .../tech/mcprison/prison/internal/World.java | 8 +- .../prison/internal/block/MineResetType.java | 9 ++ .../internal/block}/MineTargetBlockKey.java | 2 +- .../block}/MineTargetPrisonBlock.java | 32 +++++- .../java/tech/mcprison/prison/TestWorld.java | 11 ++ .../mcprison/prison/mines/data/MineData.java | 2 +- .../mcprison/prison/mines/data/MineReset.java | 50 +++------ .../prison/mines/data/MineScheduler.java | 6 +- .../prison/mines/features/MineBlockEvent.java | 1 + .../mines/features/MineTracerBuilder.java | 2 +- .../mines/tasks/MinePagedResetAsyncTask.java | 103 ++++++++++-------- .../api/PrisonMinesBlockBreakEvent.java | 2 +- .../api/PrisonMinesBlockEventEvent.java | 2 +- .../spigot/block/OnBlockBreakEventCore.java | 2 +- .../prison/spigot/block/SpigotBlock.java | 3 +- .../prison/spigot/game/SpigotWorld.java | 52 +++++++++ .../utils/tasks/PrisonUtilsRainbowDecay.java | 2 +- .../utils/tasks/PrisonUtilsTaskTypes.java | 2 +- prison-spigot/src/main/resources/config.yml | 3 + 21 files changed, 227 insertions(+), 101 deletions(-) create mode 100644 prison-core/src/main/java/tech/mcprison/prison/internal/PrisonStatsElapsedTimeNanos.java create mode 100644 prison-core/src/main/java/tech/mcprison/prison/internal/block/MineResetType.java rename {prison-mines/src/main/java/tech/mcprison/prison/mines/features => prison-core/src/main/java/tech/mcprison/prison/internal/block}/MineTargetBlockKey.java (97%) rename {prison-mines/src/main/java/tech/mcprison/prison/mines/features => prison-core/src/main/java/tech/mcprison/prison/internal/block}/MineTargetPrisonBlock.java (77%) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 41ce909bb..92a62dec2 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,11 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.3 2021-10-21 +# 3.2.11-alpha.3 2021-10-23 + + +* **Async Mine Reset performance Improvements.** Adjustments were made to improve the performance of the asynch mine resets by providing the ability to fine tune the page sizes, and also provide the ability to reset more than one block in the synchronous thread at a time. This is called a slice. Measuring the actual block reset time with nanos for better resolution. +MineTargetBlockKey class was relocated to allow for the use of sub listings on the synchronized block updates. * **Cloning a bomb was not complete. Some details were omitted.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/PrisonStatsElapsedTimeNanos.java b/prison-core/src/main/java/tech/mcprison/prison/internal/PrisonStatsElapsedTimeNanos.java new file mode 100644 index 000000000..9892358ad --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/PrisonStatsElapsedTimeNanos.java @@ -0,0 +1,28 @@ +package tech.mcprison.prison.internal; + +public class PrisonStatsElapsedTimeNanos +{ + + private long elapsedTimeNanos; + + public PrisonStatsElapsedTimeNanos() { + super(); + + } + + public synchronized void addNanos( Long nanos ) { + + this.elapsedTimeNanos += nanos; + } + + public long getElapsedTimeNanos() + { + return elapsedTimeNanos; + } + + public void setElapsedTimeNanos( long elapsedTimeNanos ) + { + this.elapsedTimeNanos = elapsedTimeNanos; + } + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/World.java b/prison-core/src/main/java/tech/mcprison/prison/internal/World.java index d09226841..8541c896d 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/World.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/World.java @@ -21,6 +21,8 @@ import java.util.List; import tech.mcprison.prison.internal.block.Block; +import tech.mcprison.prison.internal.block.MineResetType; +import tech.mcprison.prison.internal.block.MineTargetPrisonBlock; import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.util.Location; @@ -63,6 +65,10 @@ public interface World { * @param prisonBlock * @param location */ - void setBlockAsync( PrisonBlock prisonBlock, Location location ); + public void setBlockAsync( PrisonBlock prisonBlock, Location location ); + + public void setBlocksSynchronously( List tBlocks, + MineResetType resetType, + PrisonStatsElapsedTimeNanos nanos ); } diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineResetType.java b/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineResetType.java new file mode 100644 index 000000000..f300b2470 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineResetType.java @@ -0,0 +1,9 @@ +package tech.mcprison.prison.internal.block; + +public enum MineResetType +{ + normal, + paged, + clear, + tracer; +} diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTargetBlockKey.java b/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetBlockKey.java similarity index 97% rename from prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTargetBlockKey.java rename to prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetBlockKey.java index 28577dfff..0b51b0e2c 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTargetBlockKey.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetBlockKey.java @@ -1,4 +1,4 @@ -package tech.mcprison.prison.mines.features; +package tech.mcprison.prison.internal.block; import tech.mcprison.prison.internal.World; import tech.mcprison.prison.util.Location; diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTargetPrisonBlock.java b/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetPrisonBlock.java similarity index 77% rename from prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTargetPrisonBlock.java rename to prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetPrisonBlock.java index 2afea0b8d..bc4082ec9 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTargetPrisonBlock.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetPrisonBlock.java @@ -1,7 +1,6 @@ -package tech.mcprison.prison.mines.features; +package tech.mcprison.prison.internal.block; import tech.mcprison.prison.internal.World; -import tech.mcprison.prison.internal.block.PrisonBlockStatusData; import tech.mcprison.prison.util.Location; public class MineTargetPrisonBlock @@ -39,6 +38,35 @@ public String toString() { " block= " + getPrisonBlock().toString(); } + public PrisonBlock getPrisonBlock( MineResetType resetType ) { + + final PrisonBlock pBlock; + + if ( resetType == MineResetType.tracer && isEdge() ) + { + pBlock = PrisonBlock.PINK_STAINED_GLASS; + } + else if ( resetType == MineResetType.clear || + resetType == MineResetType.tracer ) + { + pBlock = PrisonBlock.AIR; + } + else if ( getPrisonBlock() != null && + getPrisonBlock() instanceof PrisonBlock ) + { + + // MineResetType.normal and MineResetType.paged + pBlock = (PrisonBlock) getPrisonBlock(); + } + else + { + pBlock = null; + } + + return pBlock; + + } + public PrisonBlockStatusData getPrisonBlock() { return prisonBlock; } diff --git a/prison-core/src/test/java/tech/mcprison/prison/TestWorld.java b/prison-core/src/test/java/tech/mcprison/prison/TestWorld.java index b5e3a3651..72d67a289 100644 --- a/prison-core/src/test/java/tech/mcprison/prison/TestWorld.java +++ b/prison-core/src/test/java/tech/mcprison/prison/TestWorld.java @@ -21,8 +21,11 @@ import java.util.List; import tech.mcprison.prison.internal.Player; +import tech.mcprison.prison.internal.PrisonStatsElapsedTimeNanos; import tech.mcprison.prison.internal.World; import tech.mcprison.prison.internal.block.Block; +import tech.mcprison.prison.internal.block.MineResetType; +import tech.mcprison.prison.internal.block.MineTargetPrisonBlock; import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.util.Location; @@ -56,4 +59,12 @@ public void setBlock( PrisonBlock block, int x, int y, int z ) { @Override public void setBlockAsync( PrisonBlock prisonBlock, Location location ) { } + + @Override + public void setBlocksSynchronously( List tBlocks, + MineResetType resetType, + PrisonStatsElapsedTimeNanos nanos ) { + + } + } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java index 6d11ff8f4..f1bb42da9 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java @@ -13,13 +13,13 @@ import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.internal.World; import tech.mcprison.prison.internal.block.Block; +import tech.mcprison.prison.internal.block.MineTargetPrisonBlock; import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.internal.block.PrisonBlock.PrisonBlockType; import tech.mcprison.prison.internal.block.PrisonBlockStatusData; import tech.mcprison.prison.mines.data.Mine.MineType; import tech.mcprison.prison.mines.features.MineBlockEvent; import tech.mcprison.prison.mines.features.MineLinerData; -import tech.mcprison.prison.mines.features.MineTargetPrisonBlock; import tech.mcprison.prison.modules.ModuleElement; import tech.mcprison.prison.modules.ModuleElementType; import tech.mcprison.prison.output.Output; diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java index 7bef72666..a8e9b03c6 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java @@ -11,6 +11,9 @@ import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.internal.World; import tech.mcprison.prison.internal.block.Block; +import tech.mcprison.prison.internal.block.MineResetType; +import tech.mcprison.prison.internal.block.MineTargetBlockKey; +import tech.mcprison.prison.internal.block.MineTargetPrisonBlock; import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.internal.block.PrisonBlockStatusData; import tech.mcprison.prison.mines.PrisonMines; @@ -20,11 +23,8 @@ import tech.mcprison.prison.mines.features.MineLinerBuilder; import tech.mcprison.prison.mines.features.MineLinerBuilder.LinerPatterns; import tech.mcprison.prison.mines.features.MineMover; -import tech.mcprison.prison.mines.features.MineTargetBlockKey; -import tech.mcprison.prison.mines.features.MineTargetPrisonBlock; import tech.mcprison.prison.mines.features.MineTracerBuilder; import tech.mcprison.prison.mines.tasks.MinePagedResetAsyncTask; -import tech.mcprison.prison.mines.tasks.MinePagedResetAsyncTask.MineResetType; import tech.mcprison.prison.mines.tasks.MineTeleportTask; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.tasks.PrisonCommandTask; @@ -113,6 +113,7 @@ public abstract class MineReset private long statsResetTimeMS = 0; private long statsBlockGenTimeMS = 0; private long statsBlockUpdateTimeMS = 0; + private long statsBlockUpdateTimeNanos = 0; // Note: The time it takes to teleport players and broadcast is so trivial // that they are being disabled to reduce the clutter and memory load. @@ -331,17 +332,11 @@ public String statsMessage() { sb.append( "&3 BlockGenTime: &7" ); sb.append( dFmt.format(getStatsBlockGenTimeMS() / 1000.0d )).append( " s " ); -// sb.append( "&3 TP1: &7" ); -// sb.append( dFmt.format(getStatsTeleport1TimeMS() / 1000.0d )); sb.append( "&3 BlockUpdateTime: &7" ); sb.append( dFmt.format(getStatsBlockUpdateTimeMS() / 1000.0d )).append( " s " ); + sb.append( dFmt.format(getStatsBlockUpdateTimeNanos() / 1000000.0d )).append( " ms(nanos) " ); -// sb.append( "&3 TP2: &7" ); -// sb.append( dFmt.format(getStatsTeleport2TimeMS() / 1000.0d )); - -// sb.append( "&3 Msg: &7" ); -// sb.append( dFmt.format(getStatsMessageBroadcastTimeMS() / 1000.0d )); sb.append( "&3 ResetPages: &7" ); sb.append( iFmt.format(getStatsResetPages() )); @@ -400,6 +395,7 @@ private void resetStats() { setStatsResetTimeMS( 0 ); setStatsBlockGenTimeMS( 0 ); setStatsBlockUpdateTimeMS( 0 ); + setStatsBlockUpdateTimeNanos( 0 ); // setStatsTeleport1TimeMS( 0 ); // setStatsTeleport2TimeMS( 0 ); // setStatsMessageBroadcastTimeMS( 0 ); @@ -702,7 +698,7 @@ private void trackConstraints( int currentLevel, List con *

* */ - protected void xresetAsynchonously() { + protected void resetAsynchonously() { boolean canceled = false; // Output.get().logInfo( "MineRest.resetAsynchonously() " + getName() ); @@ -1946,32 +1942,12 @@ public void setStatsBlockUpdateTimeMS( long statsBlockUpdateTimeMS ) this.statsBlockUpdateTimeMS = statsBlockUpdateTimeMS; } -// public long getStatsTeleport1TimeMS() -// { -// return statsTeleport1TimeMS; -// } -// public void setStatsTeleport1TimeMS( long statsTeleport1TimeMS ) -// { -// this.statsTeleport1TimeMS = statsTeleport1TimeMS; -// } -// -// public long getStatsTeleport2TimeMS() -// { -// return statsTeleport2TimeMS; -// } -// public void setStatsTeleport2TimeMS( long statsTeleport2TimeMS ) -// { -// this.statsTeleport2TimeMS = statsTeleport2TimeMS; -// } -// -// public long getStatsMessageBroadcastTimeMS() -// { -// return statsMessageBroadcastTimeMS; -// } -// public void setStatsMessageBroadcastTimeMS( long statsMessageBroadcastTimeMS ) -// { -// this.statsMessageBroadcastTimeMS = statsMessageBroadcastTimeMS; -// } + public long getStatsBlockUpdateTimeNanos() { + return statsBlockUpdateTimeNanos; + } + public void setStatsBlockUpdateTimeNanos( long statsBlockUpdateTimeNanos ) { + this.statsBlockUpdateTimeNanos = statsBlockUpdateTimeNanos; + } public int getStatsResetPages() { return statsResetPages; diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineScheduler.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineScheduler.java index d6b0f9665..a56cfdc82 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineScheduler.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineScheduler.java @@ -11,19 +11,19 @@ import tech.mcprison.prison.Prison; import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.internal.World; +import tech.mcprison.prison.internal.block.MineResetType; +import tech.mcprison.prison.internal.block.MineTargetPrisonBlock; import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.internal.block.PrisonBlockStatusData; import tech.mcprison.prison.mines.PrisonMines; import tech.mcprison.prison.mines.features.MineBlockEvent; import tech.mcprison.prison.mines.features.MineBlockEvent.BlockEventType; import tech.mcprison.prison.mines.tasks.MinePagedResetAsyncTask; -import tech.mcprison.prison.mines.tasks.MinePagedResetAsyncTask.MineResetType; -import tech.mcprison.prison.mines.features.MineTargetPrisonBlock; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.tasks.PrisonCommandTask; +import tech.mcprison.prison.tasks.PrisonCommandTask.CustomPlaceholders; import tech.mcprison.prison.tasks.PrisonRunnable; import tech.mcprison.prison.tasks.PrisonTaskSubmitter; -import tech.mcprison.prison.tasks.PrisonCommandTask.CustomPlaceholders; public abstract class MineScheduler extends MineTasks diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineBlockEvent.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineBlockEvent.java index 5a2fa2648..b2664751b 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineBlockEvent.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineBlockEvent.java @@ -8,6 +8,7 @@ import java.util.TreeSet; import tech.mcprison.prison.Prison; +import tech.mcprison.prison.internal.block.MineTargetPrisonBlock; import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.internal.block.PrisonBlockTypes; import tech.mcprison.prison.output.Output; diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTracerBuilder.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTracerBuilder.java index d5ec44c0e..d8814b9f8 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTracerBuilder.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/features/MineTracerBuilder.java @@ -1,8 +1,8 @@ package tech.mcprison.prison.mines.features; +import tech.mcprison.prison.internal.block.MineResetType; import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.mines.tasks.MinePagedResetAsyncTask; -import tech.mcprison.prison.mines.tasks.MinePagedResetAsyncTask.MineResetType; import tech.mcprison.prison.output.Output; public class MineTracerBuilder diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java index 16a8c1a5c..d8882b719 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java @@ -2,14 +2,15 @@ import java.util.List; -import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.Prison; +import tech.mcprison.prison.internal.PrisonStatsElapsedTimeNanos; +import tech.mcprison.prison.internal.block.MineResetType; +import tech.mcprison.prison.internal.block.MineTargetPrisonBlock; import tech.mcprison.prison.mines.PrisonMines; import tech.mcprison.prison.mines.data.Mine; -import tech.mcprison.prison.mines.features.MineTargetPrisonBlock; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.tasks.PrisonRunnable; import tech.mcprison.prison.tasks.PrisonTaskSubmitter; -import tech.mcprison.prison.util.Location; public class MinePagedResetAsyncTask implements PrisonRunnable @@ -19,12 +20,9 @@ public class MinePagedResetAsyncTask private int position = 0; - - private int pageSize = 2000; private int page = 0; private int totalPages = 0; -// private int subPage = 0; private int pagesPerReport = 20; private int pagePosition = 0; @@ -32,14 +30,12 @@ public class MinePagedResetAsyncTask private long timeStart = 0; private long timePage = 0; + private PrisonStatsElapsedTimeNanos nanos; - public enum MineResetType { - normal, - paged, - clear, - tracer; - } + // Config Settings: + private int configAsyncResetPageSize = -1; + private int configSyncSubPageSlice = -1; public MinePagedResetAsyncTask( Mine mine, MineResetType resetType ) { @@ -48,10 +44,14 @@ public MinePagedResetAsyncTask( Mine mine, MineResetType resetType ) { this.mine = mine; this.resetType = resetType; + this.timeStart = System.currentTimeMillis(); this.timePage = timeStart; - this.totalPages = (mine.getMineTargetPrisonBlocks().size() / pageSize) + 1; + this.nanos = new PrisonStatsElapsedTimeNanos(); + + this.totalPages = (mine.getMineTargetPrisonBlocks().size() / + getConfigAsyncResetPageSize()) + 1; } @@ -95,7 +95,9 @@ private void logStats() mine.setResetPage( page ); -// long time = System.currentTimeMillis() - start; + mine.setStatsBlockUpdateTimeNanos( nanos.getElapsedTimeNanos() ); + + // long time = System.currentTimeMillis() - start; mine.setStatsBlockUpdateTimeMS( timeElapsedPage + mine.getStatsBlockUpdateTimeMS() ); mine.setStatsResetTimeMS( timeElapsedPage + mine.getStatsResetTimeMS() ); @@ -113,7 +115,9 @@ private void logStats() resetType.name() + " : page " + page + " of " + totalPages + " : " + " blocks = " + blocksPlaced + " elapsed = " + timeElapsedPage + - " ms TotalElapsed = " + timeElapsedTotal + " ms"// + + " ms TotalElapsed = " + timeElapsedTotal + " ms " + + "block update elapsed = " + + ( getNanos().getElapsedTimeNanos() / 1000000d ) + " ms(nanos)" // " TPS " + // Prison.get().getPrisonTPS().getAverageTPSFormatted() ); @@ -134,23 +138,25 @@ public void run() { List targetBlocks = mine.getMineTargetPrisonBlocks(); - int pageEndPosition = position + pageSize; + int pageEndPosition = position + getConfigAsyncResetPageSize(); + - for ( int i = position; i < pageEndPosition && i < targetBlocks.size(); i++ ) { - MineTargetPrisonBlock tBlock = targetBlocks.get( i ); + while ( position < pageEndPosition ) { - final PrisonBlock pBlock = getPrisonBlock( tBlock ); - - if ( pBlock != null ) { - - Location location = tBlock.getLocation(); - - location.setBlockAsync( pBlock ); + int endIndex = position + getConfigSyncSubPageSlice(); + if ( endIndex > targetBlocks.size() ) { + endIndex = targetBlocks.size(); + pageEndPosition = endIndex; } - position++; + List tBlocks = targetBlocks.subList( position, endIndex ); + + mine.getWorld().get().setBlocksSynchronously( tBlocks, resetType, getNanos() ); + + position += tBlocks.size(); } + // Keep resubmitting this task until it is completed: if ( position < targetBlocks.size() ) { submitTaskSync(); @@ -189,31 +195,32 @@ private void runShutdown() { mine.asynchronouslyResetFinalize(); } - private PrisonBlock getPrisonBlock( MineTargetPrisonBlock tBlock ) { - final PrisonBlock pBlock; + + public PrisonStatsElapsedTimeNanos getNanos() { + return nanos; + } + public void setNanos( PrisonStatsElapsedTimeNanos nanos ) { + this.nanos = nanos; + } - if ( resetType == MineResetType.tracer && tBlock.isEdge() ) - { - pBlock = PrisonBlock.PINK_STAINED_GLASS; - } - else if ( resetType == MineResetType.clear || - resetType == MineResetType.tracer ) - { - pBlock = PrisonBlock.AIR; - } - else if ( tBlock.getPrisonBlock() != null && - tBlock.getPrisonBlock() instanceof PrisonBlock ) - { - // MineResetType.normal and MineResetType.paged - pBlock = (PrisonBlock) tBlock.getPrisonBlock(); + public int getConfigAsyncResetPageSize() { + if ( configAsyncResetPageSize == -1 ) { + this.configAsyncResetPageSize = + Long.valueOf( Prison.get().getPlatform() + .getConfigLong( "prison-mines.reset-async-paging.async-page-size", + 4000 )).intValue(); } - else - { - pBlock = null; + return configAsyncResetPageSize; + } + + public int getConfigSyncSubPageSlice() { + if ( configSyncSubPageSlice == -1 ) { + this.configSyncSubPageSlice = + Long.valueOf( Prison.get().getPlatform() + .getConfigLong( "prison-mines.reset-async-paging.sync-sub-page-slice", + 200 )).intValue(); } - - return pBlock; + return configSyncSubPageSlice; } - } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockBreakEvent.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockBreakEvent.java index ba5811ce2..b4b241d5c 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockBreakEvent.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockBreakEvent.java @@ -8,9 +8,9 @@ import org.bukkit.event.HandlerList; import org.bukkit.event.block.BlockBreakEvent; +import tech.mcprison.prison.internal.block.MineTargetPrisonBlock; import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.mines.features.MineBlockEvent.BlockEventType; -import tech.mcprison.prison.mines.features.MineTargetPrisonBlock; import tech.mcprison.prison.spigot.block.SpigotBlock; import tech.mcprison.prison.spigot.game.SpigotPlayer; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockEventEvent.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockEventEvent.java index b9face552..1ff0b45cb 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockEventEvent.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockEventEvent.java @@ -6,9 +6,9 @@ import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; +import tech.mcprison.prison.internal.block.MineTargetPrisonBlock; import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.mines.features.MineBlockEvent.BlockEventType; -import tech.mcprison.prison.mines.features.MineTargetPrisonBlock; import tech.mcprison.prison.spigot.block.SpigotBlock; /** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index 08d984aae..df7a5e4f8 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -24,11 +24,11 @@ import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; import tech.mcprison.prison.autofeatures.AutoFeaturesWrapper; import tech.mcprison.prison.cache.PlayerCache; +import tech.mcprison.prison.internal.block.MineTargetPrisonBlock; import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.mines.PrisonMines; import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.mines.features.MineBlockEvent.BlockEventType; -import tech.mcprison.prison.mines.features.MineTargetPrisonBlock; import tech.mcprison.prison.modules.Module; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.output.Output.DebugTarget; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java index c78e6383d..7beef49c5 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java @@ -77,7 +77,8 @@ public String getBlockName() { } @Override public Location getLocation() { - return SpigotUtil.bukkitLocationToPrison(getWrapper().getLocation()); + return getWrapper() == null ? null : + SpigotUtil.bukkitLocationToPrison(getWrapper().getLocation()); } @Override public Block getRelative(BlockFace face) { diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotWorld.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotWorld.java index b6f6f1f92..85a93fdc6 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotWorld.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotWorld.java @@ -23,13 +23,18 @@ import java.util.stream.Collectors; import org.bukkit.Bukkit; +import org.bukkit.scheduler.BukkitRunnable; import tech.mcprison.prison.PrisonAPI; import tech.mcprison.prison.integration.CustomBlockIntegration; import tech.mcprison.prison.internal.Player; +import tech.mcprison.prison.internal.PrisonStatsElapsedTimeNanos; import tech.mcprison.prison.internal.World; import tech.mcprison.prison.internal.block.Block; +import tech.mcprison.prison.internal.block.MineResetType; +import tech.mcprison.prison.internal.block.MineTargetPrisonBlock; import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.SpigotUtil; import tech.mcprison.prison.spigot.block.SpigotBlock; import tech.mcprison.prison.spigot.compat.SpigotCompatibility; @@ -115,6 +120,53 @@ public void setBlockAsync( PrisonBlock prisonBlock, Location location ) { break; } } + + + /** + *

This list of blocks to be updated, should be ran from an asynchronous thread. + * This function will take it's code block and run it in bukkit's synchronous + * thread so the block updates will be thread safe. + *

+ * + *

The MineTargetPrisonBlock List should be a fairly short list of blocks that + * will be updated in one synchronous slice. + *

+ * + */ + @Override + public void setBlocksSynchronously( List tBlocks, MineResetType resetType, + PrisonStatsElapsedTimeNanos nanos ) { + + new BukkitRunnable() { + @Override + public void run() { + + long start = System.nanoTime(); + + for ( MineTargetPrisonBlock tBlock : tBlocks ) + { + final PrisonBlock pBlock = tBlock.getPrisonBlock( resetType ); + + if ( pBlock != null ) { + + Location location = tBlock.getLocation(); + + SpigotBlock sBlock = (SpigotBlock) location.getBlockAt(); + sBlock.setPrisonBlock( pBlock ); + } + } + + long elapsedNanos = System.nanoTime() - start; + + + if ( nanos != null ) { + nanos.addNanos( elapsedNanos ); + } + + } + }.runTaskLater( SpigotPrison.getInstance(), 0 ); + + } public org.bukkit.World getWrapper() { return bukkitWorld; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/tasks/PrisonUtilsRainbowDecay.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/tasks/PrisonUtilsRainbowDecay.java index fc458ca0a..a993c7314 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/tasks/PrisonUtilsRainbowDecay.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/tasks/PrisonUtilsRainbowDecay.java @@ -6,8 +6,8 @@ import com.cryptomorin.xseries.XMaterial; +import tech.mcprison.prison.internal.block.MineTargetBlockKey; import tech.mcprison.prison.internal.block.PrisonBlock; -import tech.mcprison.prison.mines.features.MineTargetBlockKey; import tech.mcprison.prison.spigot.SpigotUtil; import tech.mcprison.prison.spigot.api.PrisonMinesBlockEventEvent; import tech.mcprison.prison.spigot.block.SpigotBlock; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/tasks/PrisonUtilsTaskTypes.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/tasks/PrisonUtilsTaskTypes.java index 8c1dc1446..7e7028d1e 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/tasks/PrisonUtilsTaskTypes.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/tasks/PrisonUtilsTaskTypes.java @@ -4,8 +4,8 @@ import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.internal.block.Block; +import tech.mcprison.prison.internal.block.MineTargetBlockKey; import tech.mcprison.prison.internal.block.PrisonBlock; -import tech.mcprison.prison.mines.features.MineTargetBlockKey; import tech.mcprison.prison.spigot.block.SpigotBlock; import tech.mcprison.prison.tasks.PrisonCommandTask; import tech.mcprison.prison.util.Location; diff --git a/prison-spigot/src/main/resources/config.yml b/prison-spigot/src/main/resources/config.yml index 591153644..ee5a61155 100644 --- a/prison-spigot/src/main/resources/config.yml +++ b/prison-spigot/src/main/resources/config.yml @@ -149,6 +149,9 @@ prison-mines: max-page-elapsed-time-ms: 75 page-submit-delay-ticks: 1 page-timeout-check-block-count: 250 + reset-async-paging: + async-page-size: 4000 + sync-sub-page-slice: 200 tp-warmup: enabled: false movementMaxDistance: 1.0 From 590104d728bddc198227906926a35f12cae37d04 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Tue, 26 Oct 2021 07:37:56 -0400 Subject: [PATCH 097/283] Major rewrites to how auto features work. Using the PrisonMinesBlockBreakEvent object to carry all of the various parameters that are used within the auto features code. This allowed the elimination of many functions since they have been combined together. It also allowed for more efficient handling of explosions by combining similar blocks together and processing them as a single unit, so massive explosions are handled far more efficiently. If the admin chooses to break the blocks in another thread, then handling of many blocks is optimized to reduce the overhead. The state of the blocks being broken are being tracked through the MineTargetPrisonBlock such that it's flagged as soon as it starts to process the impacted blocks so as to prevent the same block from being processed more than once, even when there are many explosions occurring at the same time. Changes to the block (block break) has been moved out of the depths of the code, to be closer to the event handlers so it's easier to monitor/track. Due to the many changes and major alterations to the logic, this is a work in progress and needs more testing. --- docs/changelog_v3.3.x.md | 7 +- .../internal/block/MineTargetPrisonBlock.java | 36 + .../tech/mcprison/prison/output/Output.java | 4 +- .../mcprison/prison/mines/data/MineData.java | 7 +- .../mcprison/prison/mines/data/MineReset.java | 6 + .../data/MineResetAsyncResubmitTask.java | 33 - .../spigot/api/ExplosiveBlockBreakEvent.java | 10 + .../api/PrisonMinesBlockBreakEvent.java | 71 +- .../AutoManagerBreakBlockTask.java | 27 +- .../autofeatures/AutoManagerFeatures.java | 385 +++++---- .../spigot/block/OnBlockBreakEventCore.java | 738 +++++++++++++----- .../spigot/utils/PrisonBombListener.java | 85 +- .../spigot/utils/PrisonUtilsMineBombs.java | 136 +++- 13 files changed, 1007 insertions(+), 538 deletions(-) delete mode 100644 prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineResetAsyncResubmitTask.java diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 92a62dec2..6d5507d21 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,12 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.3 2021-10-23 +# 3.2.11-alpha.3 2021-10-26 + + +* **Major rewrites to how auto features work.** +Using the PrisonMinesBlockBreakEvent object to carry all of the various parameters that are used within the auto features code. This allowed the elimination of many functions since they have been combined together. It also allowed for more efficient handling of explosions by combining similar blocks together and processing them as a single unit, so massive explosions are handled far more efficiently. If the admin chooses to break the blocks in another thread, then handling of many blocks is optimized to reduce the overhead. The state of the blocks being broken are being tracked through the MineTargetPrisonBlock such that it's flagged as soon as it starts to process the impacted blocks so as to prevent the same block from being processed more than once, even when there are many explosions occurring at the same time. Changes to the block (block break) has been moved out of the depths of the code, to be closer to the event handlers so it's easier to monitor/track. +Due to the many changes and major alterations to the logic, this is a work in progress and needs more testing. * **Async Mine Reset performance Improvements.** Adjustments were made to improve the performance of the asynch mine resets by providing the ability to fine tune the page sizes, and also provide the ability to reset more than one block in the synchronous thread at a time. This is called a slice. Measuring the actual block reset time with nanos for better resolution. diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetPrisonBlock.java b/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetPrisonBlock.java index bc4082ec9..e8543b3f1 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetPrisonBlock.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetPrisonBlock.java @@ -14,6 +14,14 @@ public class MineTargetPrisonBlock private boolean isEdge; + private boolean mined = false; + private Block minedBlock; + +// private boolean blockEvent = false; + private boolean counted = false; + + + protected MineTargetPrisonBlock( World world, int x, int y, int z, boolean isEdge ) { this.blockKey = new MineTargetBlockKey( world, x, y, z ); @@ -104,6 +112,34 @@ public void setEdge( boolean isEdge ) { this.isEdge = isEdge; } + public boolean isMined() { + return mined; + } + public void setMined( boolean mined ) { + this.mined = mined; + } + +// public boolean isBlockEvent() { +// return blockEvent; +// } +// public void setBlockEvent( boolean blockEvent ) { +// this.blockEvent = blockEvent; +// } + + public boolean isCounted() { + return counted; + } + public void setCounted( boolean counted ) { + this.counted = counted; + } + + public Block getMinedBlock() { + return minedBlock; + } + public void setMinedBlock( Block minedBlock ) { + this.minedBlock = minedBlock; + } + @Override public int compareTo( MineTargetPrisonBlock block ) { return block.getBlockKey().compareTo( block.getBlockKey() ); diff --git a/prison-core/src/main/java/tech/mcprison/prison/output/Output.java b/prison-core/src/main/java/tech/mcprison/prison/output/Output.java index 1b3f3ac1e..179a083ec 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/output/Output.java +++ b/prison-core/src/main/java/tech/mcprison/prison/output/Output.java @@ -62,9 +62,9 @@ public enum DebugTarget { off, blockBreak, // blockBreakListeners, - blockBreakDurability, +// blockBreakDurability, blockBreakFortune, - blockBreakXpCalcs, +// blockBreakXpCalcs, // Removed since it was inlined rankup, support diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java index f1bb42da9..155c71f65 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java @@ -673,14 +673,17 @@ public void incrementBlockMiningCount( MineTargetPrisonBlock targetPrisonBlock ) // Only count the block as being broke if it was not originally air and // and it has not been broke before: - if ( targetPrisonBlock != null && !targetPrisonBlock.isAirBroke() ) { + if ( targetPrisonBlock != null && !targetPrisonBlock.isAirBroke() && !targetPrisonBlock.isCounted() ) { + targetPrisonBlock.setAirBroke( true ); + targetPrisonBlock.setCounted( true ); + targetPrisonBlock.setMined( true ); + incrementBlockBreakCount(); incrementTotalBlocksMined(); targetPrisonBlock.getPrisonBlock().incrementMiningBlockCount(); - targetPrisonBlock.setAirBroke( true ); } } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java index a8e9b03c6..6a3d2ce87 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java @@ -1323,6 +1323,8 @@ protected void runMineSweeperTask() { targetBlock.getPrisonBlock().incrementMiningBlockCount(); targetBlock.setAirBroke( true ); + targetBlock.setCounted( true ); + targetBlock.setMined( true ); blocksChanged++; } @@ -1667,6 +1669,10 @@ private void constraintsApplyMin( PrisonBlockStatusData block, boolean useNewBlo // Add the new block and increment it's count: targetBlock.setPrisonBlock( block ); + if ( block.isAir() ) { + targetBlock.setAirBroke( true ); + targetBlock.setMined( true ); + } block.incrementResetBlockCount(); } } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineResetAsyncResubmitTask.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineResetAsyncResubmitTask.java deleted file mode 100644 index 1ca335e47..000000000 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineResetAsyncResubmitTask.java +++ /dev/null @@ -1,33 +0,0 @@ -package tech.mcprison.prison.mines.data; - -public class MineResetAsyncResubmitTask -// implements PrisonRunnable -{ - -// private MineReset mine; -// private PrisonRunnable callbackAsync; -// -// private List resetActions; -// -// public MineResetAsyncResubmitTask(MineReset mine, PrisonRunnable callbackAsync, -// List resetActions ) { -// -// this.mine = mine; -// this.callbackAsync = callbackAsync; -// -// this.resetActions = resetActions; -// } -// -// @Override -// public void run() { -// -// this.mine.getCurrentJob().setResetActions( resetActions ); -// -// this.mine.refreshMineAsyncResubmitTask(); -// -// if ( this.callbackAsync != null ) { -// this.mine.submitAsyncTask( callbackAsync ); -// } -// } - -} diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/ExplosiveBlockBreakEvent.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/ExplosiveBlockBreakEvent.java index 8301952c2..66d6a2dcc 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/ExplosiveBlockBreakEvent.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/ExplosiveBlockBreakEvent.java @@ -54,6 +54,9 @@ public class ExplosiveBlockBreakEvent private MineBombData mineBomb; + private boolean forceIfAirBlock = false; + + public ExplosiveBlockBreakEvent( Block theBlock, Player player, List explodedBlocks, String triggeredBy ) { super( theBlock, player ); @@ -114,6 +117,13 @@ public void setMineBomb( MineBombData mineBomb ) { this.mineBomb = mineBomb; } + public boolean isForceIfAirBlock() { + return forceIfAirBlock; + } + public void setForceIfAirBlock( boolean forceIfAirBlock ) { + this.forceIfAirBlock = forceIfAirBlock; + } + @Override public HandlerList getHandlers(){ return handlers; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockBreakEvent.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockBreakEvent.java index b4b241d5c..89671224f 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockBreakEvent.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockBreakEvent.java @@ -12,6 +12,8 @@ import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.mines.features.MineBlockEvent.BlockEventType; import tech.mcprison.prison.spigot.block.SpigotBlock; +import tech.mcprison.prison.spigot.block.SpigotItemStack; +import tech.mcprison.prison.spigot.compat.SpigotCompatibility; import tech.mcprison.prison.spigot.game.SpigotPlayer; /** @@ -57,13 +59,21 @@ public class PrisonMinesBlockBreakEvent private Mine mine; - private SpigotBlock spigotBlock; private SpigotPlayer spigotPlayer; + private SpigotItemStack itemInHand; + + private SpigotBlock spigotBlock; + private MineTargetPrisonBlock targetBlock; + //private SpigotBlock overRideSpigotBlock; private List explodedBlocks; + // The targetBlocks are the blocks that were used to reset the mine with. + // They identify what the blocks were supposed to be. + private List targetExplodedBlocks; + private BlockEventType blockEventType; private String triggered; @@ -71,6 +81,14 @@ public class PrisonMinesBlockBreakEvent private boolean monitor = false; private boolean blockEventsOnly = false; + + // Normally the explosion will ONLY work if the center target block was non-AIR. + // This setting allows the explosion to be processed even if it is air. + private boolean forceIfAirBlock = false; + + + private List bukkitDrops; + private List unprocessedRawBlocks; @@ -84,6 +102,8 @@ public PrisonMinesBlockBreakEvent( Block theBlock, Player player, this.spigotBlock = spigotBlock; this.spigotPlayer = spigotPlayer; + this.itemInHand = SpigotCompatibility.getInstance().getPrisonItemInMainHand( player ); + this.monitor = monitor; this.blockEventsOnly = blockEventsOnly; @@ -91,8 +111,12 @@ public PrisonMinesBlockBreakEvent( Block theBlock, Player player, this.triggered = triggered; this.explodedBlocks = new ArrayList<>(); + this.targetExplodedBlocks = new ArrayList<>(); + this.unprocessedRawBlocks = new ArrayList<>(); + this.bukkitDrops = new ArrayList<>(); + } public PrisonMinesBlockBreakEvent( Block theBlock, Player player, @@ -103,15 +127,21 @@ public PrisonMinesBlockBreakEvent( Block theBlock, Player player, { super( theBlock, player ); - this.mine = mine; this.spigotBlock = spigotBlock; + this.spigotPlayer = new SpigotPlayer( player ); + + this.itemInHand = SpigotCompatibility.getInstance().getPrisonItemInMainHand( player ); + + this.mine = mine; this.explodedBlocks = explodedBlocks; this.blockEventType = blockEventType; + this.targetExplodedBlocks = new ArrayList<>(); + this.triggered = triggered; - //this.overRideSpigotBlock = null; + this.bukkitDrops = new ArrayList<>(); } @@ -177,6 +207,13 @@ public void setSpigotBlock( SpigotBlock spigotBlock ) { this.spigotBlock = spigotBlock; } + public MineTargetPrisonBlock getTargetBlock() { + return targetBlock; + } + public void setTargetBlock( MineTargetPrisonBlock targetBlock ) { + this.targetBlock = targetBlock; + } + public SpigotPlayer getSpigotPlayer() { return spigotPlayer; } @@ -184,6 +221,13 @@ public void setSpigotPlayer( SpigotPlayer spigotPlayer ) { this.spigotPlayer = spigotPlayer; } + public SpigotItemStack getItemInHand() { + return itemInHand; + } + public void setItemInHand( SpigotItemStack itemInHand ) { + this.itemInHand = itemInHand; + } + public List getExplodedBlocks() { return explodedBlocks; } @@ -191,6 +235,20 @@ public void setExplodedBlocks( List explodedBlocks ) { this.explodedBlocks = explodedBlocks; } + public List getTargetExplodedBlocks() { + return targetExplodedBlocks; + } + public void setTargetExplodedBlocks( List targetBlocks ) { + this.targetExplodedBlocks = targetBlocks; + } + + public List getBukkitDrops() { + return bukkitDrops; + } + public void setBukkitDrops( List drops ) { + this.bukkitDrops = drops; + } + public BlockEventType getBlockEventType() { return blockEventType; } @@ -240,6 +298,13 @@ public void setUnprocessedRawBlocks( List unprocessedRawBlocks ) { this.unprocessedRawBlocks = unprocessedRawBlocks; } + public boolean isForceIfAirBlock() { + return forceIfAirBlock; + } + public void setForceIfAirBlock( boolean forceIfAirBlock ) { + this.forceIfAirBlock = forceIfAirBlock; + } + @Override public HandlerList getHandlers() { return handlers; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerBreakBlockTask.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerBreakBlockTask.java index de70fee45..9e5758344 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerBreakBlockTask.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerBreakBlockTask.java @@ -1,5 +1,7 @@ package tech.mcprison.prison.spigot.autofeatures; +import java.util.List; + import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.spigot.block.SpigotBlock; import tech.mcprison.prison.tasks.PrisonRunnable; @@ -9,11 +11,20 @@ public class AutoManagerBreakBlockTask implements PrisonRunnable { private SpigotBlock block; + private List blocks; public AutoManagerBreakBlockTask( SpigotBlock block ) { super(); this.block = block; + this.blocks = null; + } + + public AutoManagerBreakBlockTask( List blocks ) { + super(); + + this.block = null; + this.blocks = blocks; } public static void submitTask( SpigotBlock block ) { @@ -23,14 +34,28 @@ public static void submitTask( SpigotBlock block ) { PrisonTaskSubmitter.runTaskLater( blockTask, 0 ); } + public static void submitTask( List blocks ) { + + AutoManagerBreakBlockTask blockTask = new AutoManagerBreakBlockTask( blocks ); + + PrisonTaskSubmitter.runTaskLater( blockTask, 0 ); + } + @Override public void run() { // // Set the broken block to AIR and cancel the event - if ( !block.isEmpty() ) { + if ( block != null && !block.isEmpty() ) { block.setPrisonBlock( PrisonBlock.AIR ); } + if ( blocks != null ) { + for ( SpigotBlock spigotBlock : blocks ) + { + spigotBlock.setPrisonBlock( PrisonBlock.AIR ); + + } + } } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java index 8514ab5ab..dc616ef75 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java @@ -21,19 +21,17 @@ import com.cryptomorin.xseries.XMaterial; -import tech.mcprison.prison.Prison; import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.mines.data.Mine; -import tech.mcprison.prison.mines.features.MineBlockEvent.BlockEventType; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.output.Output.DebugTarget; import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.SpigotUtil; +import tech.mcprison.prison.spigot.api.PrisonMinesBlockBreakEvent; import tech.mcprison.prison.spigot.block.OnBlockBreakEventCore; import tech.mcprison.prison.spigot.block.SpigotBlock; import tech.mcprison.prison.spigot.block.SpigotItemStack; -import tech.mcprison.prison.spigot.commands.PrisonSpigotSellAllCommands; import tech.mcprison.prison.spigot.compat.SpigotCompatibility; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.sellall.SellAllUtil; @@ -151,11 +149,11 @@ protected short getFortune(SpigotItemStack itemInHand){ - @Override - public boolean doAction( SpigotBlock block, Mine mine, Player player, StringBuilder debugInfo ) { - - return processAutoEvents( block, player, mine, debugInfo ); - } +// @Override +// public boolean doAction( PrisonMinesBlockBreakEvent pmEvent, StringBuilder debugInfo ) { +// +// return processAutoEvents( pmEvent, debugInfo ); +// } /** @@ -165,51 +163,50 @@ public boolean doAction( SpigotBlock block, Mine mine, Player player, StringBuil * */ @Override - public boolean doAction( Mine mine, Player player, List explodedBlocks, - BlockEventType blockEventType, String triggered, - StringBuilder debugInfo ) { - return applyAutoEvents( player, mine, explodedBlocks, blockEventType, triggered, debugInfo ); + public boolean doAction( PrisonMinesBlockBreakEvent pmEvent, StringBuilder debugInfo ) { + return applyAutoEvents( pmEvent, debugInfo ); } - private boolean processAutoEvents( SpigotBlock spigotBlock, Player player, Mine mine, StringBuilder debugInfo ) { - boolean cancel = false; - - if (isBoolean(AutoFeatures.isAutoManagerEnabled) && !spigotBlock.isEmpty() ) { - - - debugInfo.append( "(doAction autoManager processAutoEvent single-block) "); - - -// Output.get().logInfo( "#### AutoManager.applyAutoEvents: BlockBreakEvent: :: " + mine.getName() + " " + -// " blocks remaining= " + -// mine.getRemainingBlockCount() + " [" + block.toString() + "]" -// ); - - SpigotItemStack itemInHand = SpigotCompatibility.getInstance().getPrisonItemInMainHand( player ); - - int count = applyAutoEvents( player, spigotBlock, mine, debugInfo ); - - if ( count > 0 ) { - processBlockBreakage( spigotBlock, mine, player, count, BlockEventType.blockBreak, - null, itemInHand, true, debugInfo ); - - cancel = true; - } - - checkZeroBlockReset( mine ); - - } - - return cancel; - } +// private boolean processAutoEvents( PrisonMinesBlockBreakEvent pmEvent, StringBuilder debugInfo ) { +// boolean cancel = false; +// +// if (isBoolean(AutoFeatures.isAutoManagerEnabled) && !pmEvent.getSpigotBlock().isEmpty() ) { +// +// +// debugInfo.append( "(doAction autoManager processAutoEvent single-block) "); +// +// +//// Output.get().logInfo( "#### AutoManager.applyAutoEvents: BlockBreakEvent: :: " + mine.getName() + " " + +//// " blocks remaining= " + +//// mine.getRemainingBlockCount() + " [" + block.toString() + "]" +//// ); +// +// +// int count = applyAutoEventsDetails( pmEvent, debugInfo ); +// +// if ( count > 0 ) { +// processBlockBreakage( pmEvent, count, true, debugInfo ); +// +// cancel = true; +// } +// +// checkZeroBlockReset( pmEvent.getMine() ); +// +// } +// +// return cancel; +// } - private int applyAutoEvents( Player player, SpigotBlock block, Mine mine, StringBuilder debugInfo ) { + private int applyAutoEventsDetails( PrisonMinesBlockBreakEvent pmEvent, StringBuilder debugInfo ) { int count = 0; + Player player = pmEvent.getPlayer(); + Mine mine = pmEvent.getMine(); + SpigotItemStack itemInHand = SpigotCompatibility.getInstance().getPrisonItemInMainHand( player ); @@ -246,7 +243,7 @@ private int applyAutoEvents( Player player, SpigotBlock block, Mine mine, String if ( Output.get().isDebug( DebugTarget.blockBreak ) ) { debugInfo.append( "(applyAutoEvents: " ) - .append( block.getBlockName() ) + .append( pmEvent.getSpigotBlock().getBlockName() ) .append( " Pickup [") .append( isAutoPickup ? "enabled: " : "disabled:" ) @@ -283,7 +280,8 @@ private int applyAutoEvents( Player player, SpigotBlock block, Mine mine, String if ( (mine != null || mine == null && !isBoolean( AutoFeatures.pickupLimitToMines )) && isAutoPickup ) { - count = autoFeaturePickup( block, player, itemInHand, isAutoSmelt, isAutoBlock, debugInfo ); + count = autoFeaturePickup( pmEvent, isAutoSmelt, isAutoBlock, debugInfo ); +// count = autoFeaturePickup( pmEvent.getSpigotBlock(), player, itemInHand, isAutoSmelt, isAutoBlock, debugInfo ); // Cannot set to air yet, or auto smelt and auto block will only get AIR: // autoPickupCleanup( block, count ); @@ -324,13 +322,13 @@ private int applyAutoEvents( Player player, SpigotBlock block, Mine mine, String - // AutoPickup - Clean up (set block to air) - if ( (mine != null || mine == null && !isBoolean( AutoFeatures.pickupLimitToMines )) && - isAutoPickup ) { - - autoPickupCleanup( block, count ); - - } +// // AutoPickup - Clean up (set block to air) +// if ( (mine != null || mine == null && !isBoolean( AutoFeatures.pickupLimitToMines )) && +// isAutoPickup ) { +// +// autoPickupCleanup( pmEvent.getSpigotBlock(), count ); +// +// } return count; @@ -360,48 +358,47 @@ private int applyAutoEvents( Player player, SpigotBlock block, Mine mine, String * @param e * @param mine */ - private boolean applyAutoEvents( Player player, Mine mine, - List explodedBlocks, BlockEventType blockEventType, - String triggered, StringBuilder debugInfo ) { - boolean cancel = false; + private boolean applyAutoEvents( PrisonMinesBlockBreakEvent pmEvent, StringBuilder debugInfo ) { +// boolean success = false; - int totalCount = 0; + int totalDrops = applyAutoEventsDetails( pmEvent, debugInfo ); - SpigotItemStack itemInHand = SpigotCompatibility.getInstance() - .getPrisonItemInMainHand( player ); + debugInfo.append( "(autoEvents totalDropa: " + totalDrops + ") "); - - debugInfo.append( "(doAction autoManager applyAutoEvents multi-blocks: " + explodedBlocks.size() + ") "); - - - // The explodedBlocks list have already been validated as being within the mine: - boolean applyExhaustion = true; - for ( SpigotBlock spigotBlock : explodedBlocks ) { - - if ( spigotBlock != null && !spigotBlock.isEmpty() ) { - - int drop = applyAutoEvents( player, spigotBlock, mine, debugInfo ); - totalCount += drop; - - if ( drop > 0 ) { - - processBlockBreakage( spigotBlock, mine, player, drop, - blockEventType, triggered, itemInHand, - applyExhaustion, debugInfo ); - applyExhaustion = false; - } - } - } - - if ( mine != null ) { - checkZeroBlockReset( mine ); - } + return applyDropsBlockBreakage( pmEvent, totalDrops, debugInfo ); - if ( totalCount > 0 ) { - cancel = true; - } - - return cancel; +// debugInfo.append( "(doAction autoManager applyAutoEvents multi-blocks: " + pmEvent.getExplodedBlocks().size() + ") "); +// +// +// // The explodedBlocks list have already been validated as being within the mine: +// boolean applyExhaustion = true; +// +// // First process the block that was hit by the player: +// if ( pmEvent.getTargetBlock() != null ) { +// +// processBlockBreakage( pmEvent, pmEvent.getTargetBlock(), 1, applyExhaustion, debugInfo ); +// applyExhaustion = false; +// +// } +// +// // Then process all of the other blocks that were included in the explosion event, if there was one: +// for ( MineTargetPrisonBlock targetBlock : pmEvent.getTargetExplodedBlocks() ) +// { +// +// processBlockBreakage( pmEvent, targetBlock, 1, applyExhaustion, debugInfo ); +// } +// +// autosellPerBlockBreak( pmEvent.getPlayer() ); +// +// if ( pmEvent.getMine() != null ) { +// checkZeroBlockReset( pmEvent.getMine() ); +// } +// +// if ( totalDrops > 0 ) { +// success = true; +// } +// +// return success; } @@ -413,22 +410,26 @@ private boolean applyAutoEvents( Player player, Mine mine, * For older versions, a good way to get the right drops would be to use * BlockDropItemEvent.getItems(), but it's deprecated * */ - protected int autoPickup( Player player, - SpigotItemStack itemInHand, SpigotBlock block, + protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, boolean isAutoSmelt, boolean isAutoBlock, StringBuilder debugInfo ) { //, BlockBreakEvent e ) { int count = 0; + Player player = pmEvent.getPlayer(); + SpigotItemStack itemInHand = pmEvent.getItemInHand(); +// SpigotBlock block = pmEvent.getSpigotBlock(); + List drops = pmEvent.getBukkitDrops(); + // The following may not be the correct drops for all versions of spigot, // plus there are some extra items, such as flint, that will never be dropped. - List drops = new ArrayList<>( SpigotUtil.getDrops(block, itemInHand) ); +// List drops = new ArrayList<>( SpigotUtil.getDrops(block, itemInHand) ); // This clears the drops for the given block, so if the event is not canceled, it will // not result in duplicate drops. - if ( isBoolean( AutoFeatures.cancelAllBlockEventBlockDrops ) ) { - block.clearDrops(); - } +// if ( isBoolean( AutoFeatures.cancelAllBlockEventBlockDrops ) ) { +// block.clearDrops(); +// } if (drops != null && drops.size() > 0 ) { @@ -480,6 +481,21 @@ protected int autoPickup( Player player, HashMap extras = SpigotUtil.addItemToPlayerInventory( player, itemStack ); + if ( extras.size() > 0 && autosellPerBlockBreak( player ) ) { + + // Try to add the extras back to the player's inventory if they had autosellPerBlockBrean enabled: + for ( SpigotItemStack extraItemStack : extras.values() ) { + + HashMap extras2 = SpigotUtil.addItemToPlayerInventory( player, extraItemStack ); + + autosellPerBlockBreak( player ); + + // If the remainder of the extras still as too much, then just drop them and move on: + dropExtra( extras2, player ); + } + extras.clear(); + } + dropExtra( extras, player ); // dropExtra( player.getInventory().addItem(itemStack), player, block ); @@ -497,30 +513,35 @@ protected int autoPickup( Player player, - public int calculateNormalDrop( SpigotItemStack itemInHand, SpigotBlock block ) { + public int calculateNormalDrop( PrisonMinesBlockBreakEvent pmEvent ) { + + // Count should be the total number of items that are to be "dropped". + // So effectively it will be the sum of all bukkitDrops counts. int count = 0; - // The following may not be the correct drops for all versions of spigot, - // plus there are some extra items, such as flint, that will never be dropped. - List drops = new ArrayList<>( SpigotUtil.getDrops(block, itemInHand) ); - +// // The following may not be the correct drops for all versions of spigot, +// // plus there are some extra items, such as flint, that will never be dropped. +// List drops = new ArrayList<>( SpigotUtil.getDrops(block, itemInHand) ); +// +// +// // This clears the drops for the given block, so if the event is not canceled, it will +// // not result in duplicate drops. +// if ( isBoolean( AutoFeatures.cancelAllBlockEventBlockDrops ) ) { +// block.clearDrops(); +// } - // This clears the drops for the given block, so if the event is not canceled, it will - // not result in duplicate drops. - if ( isBoolean( AutoFeatures.cancelAllBlockEventBlockDrops ) ) { - block.clearDrops(); - } + List drops = pmEvent.getBukkitDrops(); if (drops != null && drops.size() > 0 ) { // Need better drop calculation that is not using the getDrops function. - short fortuneLevel = getFortune(itemInHand); + short fortuneLevel = getFortune( pmEvent.getItemInHand() ); - calculateSilkTouch( itemInHand, drops ); + calculateSilkTouch( pmEvent.getItemInHand(), drops ); // Adds in additional drop items: Add Flint with gravel drops: - calculateDropAdditions( itemInHand, drops ); + calculateDropAdditions( pmEvent.getItemInHand(), drops ); if ( isBoolean( AutoFeatures.isCalculateFortuneEnabled ) ) { @@ -550,53 +571,35 @@ public int calculateNormalDrop( SpigotItemStack itemInHand, SpigotBlock block ) } - // Drop the items where the origional block was located: + // Drop the items where the original block was located: for ( SpigotItemStack itemStack : drops ) { count += itemStack.getAmount(); - dropAtBlock( itemStack, block ); + dropAtBlock( itemStack, pmEvent.getSpigotBlock() ); } - // Break the block and change it to air: - if ( !block.isEmpty() ) { - - if ( isBoolean( AutoFeatures.applyBlockBreaksThroughSyncTask ) ) { - - AutoManagerBreakBlockTask.submitTask( block ); - } - else { - - block.setPrisonBlock( PrisonBlock.AIR ); - } - - } +// // Break the block and change it to air: +// if ( !pmEvent.getSpigotBlock().isEmpty() ) { +// +// if ( isBoolean( AutoFeatures.applyBlockBreaksThroughSyncTask ) ) { +// +// AutoManagerBreakBlockTask.submitTask( pmEvent.getSpigotBlock() ); +// } +// else { +// +// pmEvent.getSpigotBlock().setPrisonBlock( PrisonBlock.AIR ); +// } +// +// } } return count; } - - public void autosellPerBlockBreak( Player player ) { - // This won't try to sell on every item stack, but assuming that sellall will hit on very block - // break, then the odds of inventory being overflowed on one explosion would be more rare than anything - if ( isBoolean( AutoFeatures.isAutoSellPerBlockBreakEnabled ) ) { - // Run sell all - if ( isBoolean( AutoFeatures.isAutoSellPerBlockBreakInlinedEnabled ) ) { - // run sellall inline with the block break event: - if (PrisonSpigotSellAllCommands.get() != null) { - PrisonSpigotSellAllCommands.get().sellAllSellWithDelayCommand(new SpigotPlayer(player)); - } - } - else { - // Submit sellall to run in the future (0 ticks in the future): - String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "sellall sell silent" ); - Bukkit.dispatchCommand(player, registeredCmd); - } - } - } + public void playerSmelt( SpigotPlayer player ) { @@ -694,46 +697,35 @@ private List mergeDrops( List drops ) } - protected void autoPickupCleanup( SpigotBlock block, int count ) - { - // Auto pickup has been successful. Now clean up. - if ( count > 0 ) { - - -// // Set the broken block to AIR and cancel the event - if ( !block.isEmpty() ) { - - if ( isBoolean( AutoFeatures.applyBlockBreaksThroughSyncTask ) ) { - - // submit a task to change the block to air: - AutoManagerBreakBlockTask.submitTask( block ); - } - - else { - - block.setPrisonBlock( PrisonBlock.AIR ); - } - } - - } - } +// protected void autoPickupCleanupX( SpigotBlock block, int count ) +// { +// // Auto pickup has been successful. Now clean up. +// if ( count > 0 ) { +// +// +//// // Set the broken block to AIR and cancel the event +// if ( !block.isEmpty() ) { +// +// if ( isBoolean( AutoFeatures.applyBlockBreaksThroughSyncTask ) ) { +// +// // submit a task to change the block to air: +// AutoManagerBreakBlockTask.submitTask( block ); +// } +// +// else { +// +// block.setPrisonBlock( PrisonBlock.AIR ); +// } +// } +// +// } +// } - public void checkZeroBlockReset( Mine mine ) { - if ( mine != null ) { - - // submit a mine sweeper task. It will only run if it is enabled and another - // mine sweeper task has not been submitted. - mine.submitMineSweeperTask(); - - // Checks to see if the mine ran out of blocks, and if it did, then - // it will reset the mine: - mine.checkZeroBlockReset(); - } - } + protected boolean checkLore( SpigotItemStack itemInHand, String loreValue ) { boolean results = false; @@ -1064,13 +1056,14 @@ protected double getLoreValue( SpigotItemStack itemInHand, String loreValue ) { * @param debugInfo * @return */ - protected int autoFeaturePickup( SpigotBlock block, Player p, SpigotItemStack itemInHand, + protected int autoFeaturePickup( PrisonMinesBlockBreakEvent pmEvent, + // SpigotBlock block, Player p, SpigotItemStack itemInHand, boolean isAutoSmelt, boolean isAutoBlock, StringBuilder debugInfo ) { int count = 0; boolean isAll = isBoolean( AutoFeatures.pickupAllBlocks ); - PrisonBlock prisonBlock = block.getPrisonBlock(); + PrisonBlock prisonBlock = pmEvent.getSpigotBlock().getPrisonBlock(); // Use this is a block name list based upon the following: blockType:blockName if not minecraft, or blockName List pickupBlockNameList = @@ -1078,13 +1071,13 @@ protected int autoFeaturePickup( SpigotBlock block, Player p, SpigotItemStack it getListString( AutoFeatures.pickupBlockNameList ) : null; if ( isAll ) { - count += autoPickup( p, itemInHand, block, isAutoSmelt, isAutoBlock, debugInfo ); + count += autoPickup( pmEvent, isAutoSmelt, isAutoBlock, debugInfo ); } else if ( isBoolean( AutoFeatures.pickupBlockNameListEnabled ) && pickupBlockNameList.size() > 0 && pickupBlockNameList.contains( prisonBlock.getBlockName() ) ) { - count += autoPickup( p, itemInHand, block, isAutoSmelt, isAutoBlock, debugInfo ); + count += autoPickup( pmEvent, isAutoSmelt, isAutoBlock, debugInfo ); } else { @@ -1092,67 +1085,67 @@ else if ( isBoolean( AutoFeatures.pickupBlockNameListEnabled ) && pickupBlockNam switch ( prisonBlock.getBlockName() ) { case "cobblestone": - count += autoPickup( p, itemInHand, block, isAutoSmelt, isAutoBlock, debugInfo ); + count += autoPickup( pmEvent, isAutoSmelt, isAutoBlock, debugInfo ); break; case "stone": - count += autoPickup( p, itemInHand, block, isAutoSmelt, isAutoBlock, debugInfo ); + count += autoPickup( pmEvent, isAutoSmelt, isAutoBlock, debugInfo ); break; case "gold_ore": case "nether_gold_ore": case "deepslate_gold_ore": case "raw_gold": - count += autoPickup( p, itemInHand, block, isAutoSmelt, isAutoBlock, debugInfo ); + count += autoPickup( pmEvent, isAutoSmelt, isAutoBlock, debugInfo ); break; case "iron_ore": case "deepslate_iron_ore": case "raw_iron": - count += autoPickup( p, itemInHand, block, isAutoSmelt, isAutoBlock, debugInfo ); + count += autoPickup( pmEvent, isAutoSmelt, isAutoBlock, debugInfo ); break; case "coal_ore": case "deepslate_coal_ore": - count += autoPickup( p, itemInHand, block, isAutoSmelt, isAutoBlock, debugInfo ); + count += autoPickup( pmEvent, isAutoSmelt, isAutoBlock, debugInfo ); break; case "diamond_ore": case "deepslate_diamond_ore": - count += autoPickup( p, itemInHand, block, isAutoSmelt, isAutoBlock, debugInfo ); + count += autoPickup( pmEvent, isAutoSmelt, isAutoBlock, debugInfo ); break; case "redstone_ore": case "deepslate_redstone_ore": - count += autoPickup( p, itemInHand, block, isAutoSmelt, isAutoBlock, debugInfo ); + count += autoPickup( pmEvent, isAutoSmelt, isAutoBlock, debugInfo ); break; case "emerald_ore": case "deepslate_emerald_ore": - count += autoPickup( p, itemInHand, block, isAutoSmelt, isAutoBlock, debugInfo ); + count += autoPickup( pmEvent, isAutoSmelt, isAutoBlock, debugInfo ); break; case "quartz_ore": - count += autoPickup( p, itemInHand, block, isAutoSmelt, isAutoBlock, debugInfo ); + count += autoPickup( pmEvent, isAutoSmelt, isAutoBlock, debugInfo ); break; case "lapis_ore": case "deepslate_lapis_ore": - count += autoPickup( p, itemInHand, block, isAutoSmelt, isAutoBlock, debugInfo ); + count += autoPickup( pmEvent, isAutoSmelt, isAutoBlock, debugInfo ); break; case "snow_ball": - count += autoPickup( p, itemInHand, block, isAutoSmelt, isAutoBlock, debugInfo ); + count += autoPickup( pmEvent, isAutoSmelt, isAutoBlock, debugInfo ); break; case "glowstone_dust": // works 1.15.2 - count += autoPickup( p, itemInHand, block, isAutoSmelt, isAutoBlock, debugInfo ); + count += autoPickup( pmEvent, isAutoSmelt, isAutoBlock, debugInfo ); break; case "copper_ore": case "deepslate_copper_ore": case "raw_copper": - count += autoPickup( p, itemInHand, block, isAutoSmelt, isAutoBlock, debugInfo ); + count += autoPickup( pmEvent, isAutoSmelt, isAutoBlock, debugInfo ); break; default: diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index df7a5e4f8..6bd1b5ab7 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -33,9 +33,12 @@ import tech.mcprison.prison.output.Output; import tech.mcprison.prison.output.Output.DebugTarget; import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.SpigotUtil; import tech.mcprison.prison.spigot.api.ExplosiveBlockBreakEvent; import tech.mcprison.prison.spigot.api.PrisonMinesBlockBreakEvent; +import tech.mcprison.prison.spigot.autofeatures.AutoManagerBreakBlockTask; import tech.mcprison.prison.spigot.autofeatures.AutoManagerFeatures; +import tech.mcprison.prison.spigot.commands.PrisonSpigotSellAllCommands; import tech.mcprison.prison.spigot.compat.Compatibility; import tech.mcprison.prison.spigot.compat.SpigotCompatibility; import tech.mcprison.prison.spigot.game.SpigotPlayer; @@ -357,7 +360,8 @@ else if ( pmEvent.getMine() != null || pmEvent.getMine() == null && else { // doAction returns a boolean that indicates if the event should be canceled or not: - if ( doAction( sBlock, pmEvent.getMine(), pmEvent.getPlayer(), debugInfo ) ) { + if ( doAction( pmEvent, debugInfo ) ) { +// if ( doAction( sBlock, pmEvent.getMine(), pmEvent.getPlayer(), debugInfo ) ) { if ( isBoolean( AutoFeatures.cancelAllBlockBreakEvents ) ) { e.setCancelled( true ); @@ -367,6 +371,8 @@ else if ( pmEvent.getMine() != null || pmEvent.getMine() == null && debugInfo.append( "(event was not canceled) " ); } + finalizeBreakTheBlocks( pmEvent ); + } else { @@ -392,6 +398,45 @@ else if ( pmEvent.getMine() != null || pmEvent.getMine() == null && } + private void finalizeBreakTheBlocks( PrisonMinesBlockBreakEvent pmEvent ) + { + List blocks = finalizeBreakTheBlocksCollectEm( pmEvent ); + + if ( isBoolean( AutoFeatures.applyBlockBreaksThroughSyncTask ) ) { + + AutoManagerBreakBlockTask.submitTask( blocks ); + } + else { + + for ( SpigotBlock spigotBlock : blocks ) { + + spigotBlock.setPrisonBlock( PrisonBlock.AIR ); + } + } + + } + private List finalizeBreakTheBlocksCollectEm( PrisonMinesBlockBreakEvent pmEvent ) { + List blocks = new ArrayList<>(); + + if ( pmEvent.getTargetBlock() != null && pmEvent.getTargetBlock().getMinedBlock() != null ) { + blocks.add( ((SpigotBlock) pmEvent.getTargetBlock().getMinedBlock()) ); + pmEvent.getTargetBlock().setAirBroke( true ); + pmEvent.getTargetBlock().setMinedBlock( null ); + } + + for ( MineTargetPrisonBlock targetBlock : pmEvent.getTargetExplodedBlocks() ) { + + if ( targetBlock != null && targetBlock.getMinedBlock() != null ) { + blocks.add( ((SpigotBlock) targetBlock.getMinedBlock()) ); + targetBlock.setAirBroke( true ); + targetBlock.setMinedBlock( null ); + } + } + + return blocks; + } + + /** *

This function an attempt to provide a uniform procedure to validate if the event should * be processed. This will eliminate a lot of duplicate code, and will make supporting other @@ -425,13 +470,16 @@ private boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent, StringBuilder // Thanks to CrazyEnchant, where they do not identify the block the player breaks, we // have to go through all of the unprecessedRawBlocks to see if any are within a mine. // If we find a block that's in a mine, then use that block as the primary block. - for ( Block bBlock : pmEvent.getUnprocessedRawBlocks() ) - { - SpigotBlock sBlock = new SpigotBlock( bBlock ); - mine = findMineLocation( sBlock ); - if ( mine != null ) { - pmEvent.setSpigotBlock( sBlock ); - break; + if ( mine == null ) { + + for ( Block bBlock : pmEvent.getUnprocessedRawBlocks() ) + { + SpigotBlock sBlock = new SpigotBlock( bBlock ); + mine = findMineLocation( sBlock ); + if ( mine != null ) { + pmEvent.setSpigotBlock( sBlock ); + break; + } } } @@ -446,9 +494,50 @@ private boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent, StringBuilder // validate the blocks, if there are some. Add them to the exploded blocks list - if ( mine != null && pmEvent.getUnprocessedRawBlocks().size() > 0 ) { + if ( mine != null ) { int unbreakable = 0; int outsideOfMine = 0; + int alreadyMined = 0; + int noTargetBlock = 0; + + // Get the mine's targetBlock: + MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( pmEvent.getSpigotBlock() ); + + // NOTE: for the primary block pmEvent.getSpigotBlock() the unbreakable will be checked later: + if ( targetBlock != null && targetBlock.getPrisonBlock() != null ) { + + if ( !targetBlock.isMined() || !targetBlock.isAirBroke() ) { + + // If a chain reaction on explosions, this will prevent the same block from + // being processed more than once: + targetBlock.setMined( true ); + + targetBlock.setMinedBlock( pmEvent.getSpigotBlock() ); + pmEvent.setTargetBlock( targetBlock ); + } + else { + alreadyMined++; + + if ( !targetBlock.isMined() ) { + targetBlock.setMined( true ); + } + + if ( !pmEvent.isForceIfAirBlock() ) { + + debugInfo.append( "VALIDATION_FAILED_BLOCK_ALREADY_MINED " ); + + results = false; + } + + } + } + else { + noTargetBlock++; + + debugInfo.append( "VALIDATION_FAILED_NO_TARGETBLOCK " ); + + results = false; + } for ( Block bukkitBlock : pmEvent.getUnprocessedRawBlocks() ) { @@ -465,7 +554,34 @@ private boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent, StringBuilder } else if ( mine.isInMineExact( sBlock.getLocation() ) ) { - pmEvent.getExplodedBlocks().add( sBlock ); + // Get the mine's targetBlock: + MineTargetPrisonBlock targetExplodedBlock = mine.getTargetPrisonBlock( sBlock ); + + if ( targetExplodedBlock != null && targetExplodedBlock.getPrisonBlock() != null ) { + + if ( targetExplodedBlock.isMined() ) { + + alreadyMined++; + } + else if ( results && !targetExplodedBlock.isMined() ) { + + // If a chain reaction on explosions, this will prevent the same block from + // being processed more than once: + targetExplodedBlock.setMined( true ); + + targetExplodedBlock.setMinedBlock( sBlock ); + + pmEvent.getExplodedBlocks().add( sBlock ); + pmEvent.getTargetExplodedBlocks().add( targetExplodedBlock ); + + } + } + else if ( results ) { + // No targetBlock so add it anyway: + pmEvent.getExplodedBlocks().add( sBlock ); + + noTargetBlock++; + } } else { outsideOfMine++; @@ -491,6 +607,16 @@ else if ( mine.isInMineExact( sBlock.getLocation() ) ) { debugInfo.append( "BLOCKS_OUTSIDE_OF_MINE (" + outsideOfMine + " blocks, event not canceled) " ); } + if ( alreadyMined > 0 ) { + + debugInfo.append( "BLOCKS_ALREADY_MINED (" + alreadyMined + + " ) " ); + } + if ( noTargetBlock > 0 ) { + + debugInfo.append( "NO_TARGET_BLOCKS (" + noTargetBlock + + " ) " ); + } } @@ -513,23 +639,24 @@ else if ( mine.isInMineExact( sBlock.getLocation() ) ) { debugInfo.append( "UNUSABLE_TOOL__WORN_OUT (event canceled) " ); results = false; } - else if ( mine != null && BlockUtils.getInstance().isUnbreakable( pmEvent.getSpigotBlock() ) ) { + if ( mine != null && BlockUtils.getInstance().isUnbreakable( pmEvent.getSpigotBlock() ) ) { // The block is unbreakable because a utility has it locked: pmEvent.setCancelOriginalEvent( true ); debugInfo.append( "UNBREAKABLE_BLOCK_UTILS (event canceled) " ); results = false; } - else if ( mine != null && (mine.isMineAccessByRank() || mine.isAccessPermissionEnabled()) && + if ( mine != null && (mine.isMineAccessByRank() || mine.isAccessPermissionEnabled()) && !mine.hasMiningAccess( pmEvent.getSpigotPlayer() ) ) { // The player does not have permission to access this mine, so do not process // pmEvent.setCancelOriginalEvent( true ); - debugInfo.append( "ACCESS_DENIED (event canceled) " ); + debugInfo.append( "ACCESS_DENIED (event canceled - Access by rank/perm/perms) " ); results = false; } - else if ( pmEvent.isBlockEventsOnly() ) { + + if ( results && pmEvent.isBlockEventsOnly() ) { String triggered = null; @@ -553,13 +680,13 @@ else if ( pmEvent.isBlockEventsOnly() ) { results = false; } - else if ( pmEvent.isMonitor() && mine == null ) { + else if ( results && pmEvent.isMonitor() && mine == null ) { // bypass all processing since the block break is outside any mine: debugInfo.append( "(bypassed monitor no mine) " ); results = false; } - else if ( pmEvent.isMonitor() && mine != null ) { + else if ( results && pmEvent.isMonitor() && mine != null ) { doActionMonitor( pmEvent.getSpigotBlock(), mine ); @@ -577,7 +704,26 @@ else if ( pmEvent.isMonitor() && mine != null ) { " Exploded Blocks - finalized) " ); } - results = false; + // should be true at this point: + //results = true; + } + + + if ( results ) { + // Collect the bukkit drops && cancel the drops if needed + + collectBukkitDrops( pmEvent.getBukkitDrops(), pmEvent.getSpigotBlock(), + pmEvent.getItemInHand() ); + + for ( SpigotBlock explodedBlock : pmEvent.getExplodedBlocks() ) + { + collectBukkitDrops( pmEvent.getBukkitDrops(), explodedBlock, + pmEvent.getItemInHand() ); + + } + + // Need to compress the drops to eliminate duplicates: + pmEvent.setBukkitDrops( mergeDrops( pmEvent.getBukkitDrops() ) ); } @@ -592,6 +738,50 @@ else if ( pmEvent.isMonitor() && mine != null ) { return results; } + private void collectBukkitDrops( List bukkitDrops, SpigotBlock spigotBlock, + SpigotItemStack itemInHand ) + { + List drops = SpigotUtil.getDrops(spigotBlock, itemInHand); + + bukkitDrops.addAll( drops ); + + // This clears the drops for the given block, so if the event is not canceled, it will + // not result in duplicate drops. + if ( isBoolean( AutoFeatures.cancelAllBlockEventBlockDrops ) ) { + spigotBlock.clearDrops(); + } + + } + + /** + *

The List of drops must have only one ItemStack per block type (name). + * This function combines multiple occurrences together and adds up their + * counts to properly represent the total quantity in the original drops collection + * that had duplicate entries. + *

+ * + * @param List of SpigotItemStack drops with duplicate entries + * @return List of SpigotItemStack drops without duplicates + */ + private List mergeDrops( List drops ) + { + TreeMap results = new TreeMap<>(); + + for ( SpigotItemStack drop : drops ) { + String key = drop.getName(); + if ( !results.containsKey( key ) ) { + results.put( key, drop ); + } + else { + SpigotItemStack sItemStack = results.get( key ); + + sItemStack.setAmount( sItemStack.getAmount() + drop.getAmount() ); + } + } + + return new ArrayList<>( results.values() ); + } + /** *

Since there are multiple blocks associated with this event, pull out the player first and * get the mine, then loop through those blocks to make sure they are within the mine. @@ -703,8 +893,7 @@ else if ( isTEExplosiveEnabled && else { // This is where the processing actually happens: - if ( doAction( pmEvent.getMine(), pmEvent.getPlayer(), - pmEvent.getExplodedBlocks(), BlockEventType.TEXplosion, triggered, debugInfo ) ) { + if ( doAction( pmEvent, debugInfo ) ) { if ( isBoolean( AutoFeatures.cancelAllBlockBreakEvents ) ) { @@ -714,6 +903,8 @@ else if ( isTEExplosiveEnabled && debugInfo.append( "(event was not canceled) " ); } + + finalizeBreakTheBlocks( pmEvent ); } else { @@ -905,8 +1096,7 @@ else if ( isCEBlockExplodeEnabled && } else { - if ( doAction( pmEvent.getMine(), e.getPlayer(), pmEvent.getExplodedBlocks(), - BlockEventType.CEXplosion, triggered, debugInfo ) ) { + if ( doAction( pmEvent, debugInfo ) ) { if ( isBoolean( AutoFeatures.cancelAllBlockBreakEvents ) ) { @@ -916,6 +1106,8 @@ else if ( isCEBlockExplodeEnabled && debugInfo.append( "(event was not canceled) " ); } + + finalizeBreakTheBlocks( pmEvent ); } else { @@ -1036,8 +1228,7 @@ else if ( isPEExplosiveEnabled && } else { - if ( doAction( pmEvent.getMine(), e.getPlayer(), pmEvent.getExplodedBlocks(), - BlockEventType.PEExplosive, triggered, debugInfo ) ) { + if ( doAction( pmEvent, debugInfo ) ) { if ( isBoolean( AutoFeatures.cancelAllBlockBreakEvents ) ) { @@ -1047,6 +1238,8 @@ else if ( isPEExplosiveEnabled && debugInfo.append( "(event was not canceled) " ); } + + finalizeBreakTheBlocks( pmEvent ); } else { @@ -1110,6 +1303,7 @@ protected void genericExplosiveEvent( ExplosiveBlockBreakEvent e, boolean monito sBlock, sPlayer, monitor, blockEventsOnly, eventType, triggered ); pmEvent.setUnprocessedRawBlocks( e.getExplodedBlocks() ); + pmEvent.setForceIfAirBlock( e.isForceIfAirBlock() ); if ( !validateEvent( pmEvent, debugInfo ) ) { @@ -1140,8 +1334,7 @@ else if ( isPPrisonExplosiveBlockBreakEnabled && } else { - if ( doAction( pmEvent.getMine(), e.getPlayer(), pmEvent.getExplodedBlocks(), - BlockEventType.PrisonExplosion, triggered, debugInfo ) ) { + if ( doAction( pmEvent, debugInfo ) ) { if ( isBoolean( AutoFeatures.cancelAllBlockBreakEvents ) ) { @@ -1151,6 +1344,8 @@ else if ( isPPrisonExplosiveBlockBreakEnabled && debugInfo.append( "(event was not canceled) " ); } + + finalizeBreakTheBlocks( pmEvent ); } else { @@ -1185,8 +1380,17 @@ public void doActionMonitor( SpigotBlock block, Mine mine ) { // Good chance the block was already counted, but just in case it wasn't: MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( block ); - // Record the block break: - mine.incrementBlockMiningCount( targetBlock ); + + if ( targetBlock != null && !targetBlock.isCounted() ) { + targetBlock.setCounted( true ); + + // Record the block break: + mine.incrementBlockMiningCount( targetBlock ); + + if ( !targetBlock.isMined() ) { + targetBlock.setMined( true ); + } + } // Never process BlockEvents in a monitor. @@ -1206,7 +1410,10 @@ public void doActionBlockEventOnly( SpigotBlock spigotBlock, Mine mine, Player p MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( spigotBlock ); - if ( targetBlock != null && targetBlock.getPrisonBlock() != null ) { + if ( targetBlock != null && targetBlock.getPrisonBlock() != null && !targetBlock.isCounted() ) { + + targetBlock.setCounted( true ); +// targetBlock.setBlockEvent( true ); // String targetBlockName = mine == null ? // spigotBlock.getPrisonBlock().getBlockName() @@ -1215,57 +1422,65 @@ public void doActionBlockEventOnly( SpigotBlock spigotBlock, Mine mine, Player p // Process mine block break events: SpigotPlayer sPlayer = new SpigotPlayer( player ); - PrisonBlock prisonBlock = spigotBlock.getPrisonBlock(); - + mine.incrementBlockMiningCount( targetBlock ); + PlayerCache.getInstance().addPlayerBlocks( sPlayer, mine.getName(), targetBlock.getPrisonBlock(), 1 ); + + PrisonBlock prisonBlock = spigotBlock.getPrisonBlock(); mine.processBlockBreakEventCommands( prisonBlock, targetBlock, sPlayer, blockEventType, triggered ); + + if ( !targetBlock.isMined() ) { + targetBlock.setMined( true ); + } + +// if ( targetBlock.getMinedBlock() != null ) { +// targetBlock.setMinedBlock( null ); +// } } } } - public boolean doAction( SpigotBlock spigotBlock, Mine mine, Player player, StringBuilder debugInfo ) { - boolean cancel = false; - debugInfo.append( "(doAction: starting EventCore) " ); - - SpigotItemStack itemInHand = SpigotCompatibility.getInstance().getPrisonItemInMainHand( player ); - - AutoManagerFeatures aMan = SpigotPrison.getInstance().getAutoFeatures(); - - - // Do not have to check if auto manager is enabled because it isn't if it's calling this function: -// boolean isAutoManagerEnabled = aMan.isBoolean( AutoFeatures.isAutoManagerEnabled ); - boolean isProcessNormalDropsEnabled = isBoolean( AutoFeatures.handleNormalDropsEvents ); - - int drop = 1; - - if ( isProcessNormalDropsEnabled ) { - - debugInfo.append( "(doAction calculateNormalDrop) " ); - - // Drop the contents of the individual block breaks - drop = aMan.calculateNormalDrop( itemInHand, spigotBlock ); - - } - - if ( drop > 0 ) { - debugInfo.append( "(doAction processBlockBreakage) " ); - - aMan.processBlockBreakage( spigotBlock, mine, player, drop, BlockEventType.blockBreak, - null, itemInHand, true, debugInfo ); - - cancel = true; - - aMan.autosellPerBlockBreak( player ); - } - - if ( mine != null ) { - aMan.checkZeroBlockReset( mine ); - } - - return cancel; - } +// public boolean doActionX( PrisonMinesBlockBreakEvent pmEvent, StringBuilder debugInfo ) { +// boolean cancel = false; +// debugInfo.append( "(doAction: starting EventCore) " ); +// +// +// AutoManagerFeatures aMan = SpigotPrison.getInstance().getAutoFeatures(); +// +// +// // Do not have to check if auto manager is enabled because it isn't if it's calling this function: +//// boolean isAutoManagerEnabled = aMan.isBoolean( AutoFeatures.isAutoManagerEnabled ); +// boolean isProcessNormalDropsEnabled = isBoolean( AutoFeatures.handleNormalDropsEvents ); +// +// int drop = 1; +// +// if ( isProcessNormalDropsEnabled ) { +// +// debugInfo.append( "(doAction calculateNormalDrop) " ); +// +// // Drop the contents of the individual block breaks +// drop = aMan.calculateNormalDrop( pmEvent ); +// +// } +// +// if ( drop > 0 ) { +// debugInfo.append( "(doAction processBlockBreakage) " ); +// +// aMan.processBlockBreakage( pmEvent, drop, true, debugInfo ); +// +// cancel = true; +// +// aMan.autosellPerBlockBreak( pmEvent.getPlayer() ); +// } +// +// if ( pmEvent.getMine() != null ) { +// aMan.checkZeroBlockReset( pmEvent.getMine() ); +// } +// +// return cancel; +// } /** @@ -1278,48 +1493,40 @@ public boolean doAction( SpigotBlock spigotBlock, Mine mine, Player player, Stri * @param e * @param teExplosiveBlocks */ - public boolean doAction( Mine mine, Player player, List explodedBlocks, - BlockEventType blockEventType, String triggered, StringBuilder debugInfo ) { - boolean cancel = false; - - int totalCount = 0; - - SpigotItemStack itemInHand = SpigotCompatibility.getInstance().getPrisonItemInMainHand( player ); + public boolean doAction( PrisonMinesBlockBreakEvent pmEvent, StringBuilder debugInfo ) { AutoManagerFeatures aMan = SpigotPrison.getInstance().getAutoFeatures(); + int totalDrops = aMan.calculateNormalDrop( pmEvent ); - debugInfo.append( "(doAction normalDrop multi-blocks: " + explodedBlocks.size() + ") "); + debugInfo.append( "(normalDrops totalDrops: " + totalDrops + ") "); + return applyDropsBlockBreakage( pmEvent, totalDrops, debugInfo ); + } + + + public boolean applyDropsBlockBreakage( PrisonMinesBlockBreakEvent pmEvent, int totalDrops, StringBuilder debugInfo ) { + boolean success = false; + // The explodedBlocks list have already been validated as being within the mine: - boolean applyExhaustion = true; - for ( SpigotBlock spigotBlock : explodedBlocks ) { - - - // Drop the contents of the individual block breaks - int drop = aMan.calculateNormalDrop( itemInHand, spigotBlock ); - totalCount += drop; - - if ( drop > 0 ) { - - aMan.processBlockBreakage( spigotBlock, mine, player, drop, - blockEventType, triggered, itemInHand, - applyExhaustion, debugInfo ); - applyExhaustion = false; - - aMan.autosellPerBlockBreak( player ); - } - - } + debugInfo.append( "(applyDropsBlockBreakage multi-blocks: " + pmEvent.getTargetExplodedBlocks().size() + ") "); - if ( mine != null ) { - aMan.checkZeroBlockReset( mine ); - } + + // Process the blockBreakage which actually breaks the block, calculates and gives the player xp, + // calculates the durability, applies food exhaustion: + processBlockBreakage( pmEvent, debugInfo ); + + + autosellPerBlockBreak( pmEvent.getPlayer() ); + +// if ( pmEvent.getMine() != null ) { +// checkZeroBlockReset( pmEvent.getMine() ); +// } - if ( totalCount > 0 ) { - cancel = true; + if ( totalDrops > 0 ) { + success = true; } - return cancel; + return success; } @@ -1406,37 +1613,26 @@ public boolean doAction( Mine mine, Player player, List explodedBlo - public void processBlockBreakage( SpigotBlock spigotBlock, - Mine mine, Player player, int count, - BlockEventType blockEventType, String triggered, SpigotItemStack itemInHand, - boolean applyExhaustion, StringBuilder debugInfo ) + public void processBlockBreakage( PrisonMinesBlockBreakEvent pmEvent, StringBuilder debugInfo ) { - MineTargetPrisonBlock targetBlock = null; - - if ( mine != null ) { - targetBlock = mine.getTargetPrisonBlock( spigotBlock ); - } - // If this block is not in the mine (if null) and it has not been broke before // and wasn't originally air, then process the breakage: - if ( mine == null || targetBlock != null && !targetBlock.isAirBroke() ) { + if ( pmEvent.getMine() != null ) { + + - String targetBlockName = mine == null ? - spigotBlock.getPrisonBlock().getBlockName() - : targetBlock.getPrisonBlock().getBlockName(); - - debugInfo.append( "(processBlockBreakage targetBlock: " + targetBlockName + ")" ); + // Calculate XP for all blocks if enabled: + int totalXp = xpCalculateXP( pmEvent, debugInfo ); + xpGivePlayerXp( pmEvent.getSpigotPlayer(), totalXp, debugInfo ); - // Process mine block break events: - SpigotPlayer sPlayer = new SpigotPlayer( player ); + int blocksMined = (pmEvent.getTargetBlock() == null ? 0 : 1 ) + pmEvent.getTargetExplodedBlocks().size(); - int bonusXp = checkCrazyEnchant( player, spigotBlock.getWrapper(), ( itemInHand == null ? null : itemInHand.getBukkitStack()) ); + // A block was broke... so record that event on the tool: + itemLoreCounter( pmEvent.getItemInHand(), getMessage( AutoFeatures.loreBlockBreakCountName ), blocksMined ); - // Calculate XP on block break if enabled: - calculateAndGivePlayerXP( sPlayer, targetBlockName, count, bonusXp, debugInfo ); // calculate durability impact: Include item durability resistance. if ( isBoolean( AutoFeatures.isCalculateDurabilityEnabled ) ) { @@ -1444,87 +1640,212 @@ public void processBlockBreakage( SpigotBlock spigotBlock, // value of 0 = normal durability. Value 100 = never calculate durability. int durabilityResistance = 0; if ( isBoolean( AutoFeatures.loreDurabiltyResistance ) ) { - durabilityResistance = getDurabilityResistance( itemInHand, + durabilityResistance = getDurabilityResistance( pmEvent.getItemInHand(), getMessage( AutoFeatures.loreDurabiltyResistanceName ) ); } - calculateAndApplyDurability( player, itemInHand, durabilityResistance ); + calculateAndApplyDurability( pmEvent.getPlayer(), pmEvent.getItemInHand(), + blocksMined, durabilityResistance, debugInfo ); } - if ( applyExhaustion && isBoolean( AutoFeatures.isCalculateFoodExhustion ) ) { - sPlayer.incrementFoodExhaustionBlockBreak(); - } - // A block was broke... so record that event on the tool: - itemLoreCounter( itemInHand, getMessage( AutoFeatures.loreBlockBreakCountName ), 1 ); - if ( mine != null ) { + // Only calculate once, no matter how many blocks are included in the explosion blocks: + if ( isBoolean( AutoFeatures.isCalculateFoodExhustion ) ) { + pmEvent.getSpigotPlayer().incrementFoodExhaustionBlockBreak(); + } + + + if ( pmEvent.getMine() != null ) { // Record the block break: - mine.incrementBlockMiningCount( targetBlock ); - PrisonBlock prisonBlock = spigotBlock.getPrisonBlock(); + // apply to ALL blocks including exploded: + applyBlockFinalizations( pmEvent, pmEvent.getTargetBlock() ); + - PlayerCache.getInstance().addPlayerBlocks( sPlayer, mine.getName(), targetBlock.getPrisonBlock(), 1 ); + for ( MineTargetPrisonBlock teBlock : pmEvent.getTargetExplodedBlocks() ) { + + applyBlockFinalizations( pmEvent, teBlock ); + } - mine.processBlockBreakEventCommands( prisonBlock, - targetBlock, sPlayer, blockEventType, triggered ); + checkZeroBlockReset( pmEvent.getMine() ); } } } - protected void calculateAndGivePlayerXP(SpigotPlayer player, String blockName, - int count, int bonusXp, StringBuilder debugInfo ) { - - int totalXp = 0; + + + public boolean autosellPerBlockBreak( Player player ) { + boolean enabled = false; - if (isBoolean(AutoFeatures.isCalculateXPEnabled) && blockName != null ) { - -// String blockName = block.getPrisonBlock() == null ? null : block.getPrisonBlock().getBlockName(); - - if ( blockName != null ) { - - int xp = bonusXp; - for ( int i = 0; i < count; i++ ) { - xp += calculateXP( blockName ); + // This won't try to sell on every item stack, but assuming that sellall will hit on very block + // break, then the odds of inventory being overflowed on one explosion would be more rare than anything + if ( isBoolean( AutoFeatures.isAutoSellPerBlockBreakEnabled ) ) { + + enabled = true; + + // Run sell all + if ( isBoolean( AutoFeatures.isAutoSellPerBlockBreakInlinedEnabled ) ) { + // run sellall inline with the block break event: + if (PrisonSpigotSellAllCommands.get() != null) { + PrisonSpigotSellAllCommands.get().sellAllSellWithDelayCommand(new SpigotPlayer(player)); } + } + else { + // Submit sellall to run in the future (0 ticks in the future): + String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "sellall sell silent" ); + Bukkit.dispatchCommand(player, registeredCmd); + } + } + + return enabled; + } + + + public void checkZeroBlockReset( Mine mine ) { + if ( mine != null ) { + + // submit a mine sweeper task. It will only run if it is enabled and another + // mine sweeper task has not been submitted. + mine.submitMineSweeperTask(); + + // Checks to see if the mine ran out of blocks, and if it did, then + // it will reset the mine: + mine.checkZeroBlockReset(); + } + } + + private void applyBlockFinalizations( PrisonMinesBlockBreakEvent pmEvent, MineTargetPrisonBlock targetBlock ) { - if (xp > 0) { + if ( targetBlock != null ) { + + if ( !targetBlock.isCounted() ) { + targetBlock.setCounted( true ); + + pmEvent.getMine().incrementBlockMiningCount( targetBlock ); + PlayerCache.getInstance().addPlayerBlocks( pmEvent.getSpigotPlayer(), pmEvent.getMine().getName(), targetBlock.getPrisonBlock(), 1 ); + + } + + + SpigotBlock sBlock = (SpigotBlock) targetBlock.getMinedBlock(); + + pmEvent.getMine().processBlockBreakEventCommands( sBlock.getPrisonBlock(), + targetBlock, pmEvent.getSpigotPlayer(), pmEvent.getBlockEventType(), pmEvent.getTriggered() ); + + + // if isMined has not been set, set it: + if ( !targetBlock.isMined() ) { + targetBlock.setMined( true ); + } + +// if ( targetBlock.getMinedBlock() != null ) { +// targetBlock.setMinedBlock( null ); +// } + + } + } + + protected int xpCalculateXP( PrisonMinesBlockBreakEvent pmEvent, StringBuilder debugInfo ) { + int xp = 0; + + if (isBoolean(AutoFeatures.isCalculateXPEnabled) ) { + + int totalXp = 0; + int totalBonusXp = 0; + int totalBlocks = 0; + + SpigotPlayer player = pmEvent.getSpigotPlayer(); + ItemStack itemInHand = pmEvent.getItemInHand() == null ? null : pmEvent.getItemInHand().getBukkitStack(); - totalXp += xp; - if ( isBoolean( AutoFeatures.givePlayerXPAsOrbDrops )) { + // Calculate the XP for the primary block: + MineTargetPrisonBlock targetBlock = pmEvent.getTargetBlock(); + totalXp = xpCalculateBlockXP( targetBlock, player ); + totalBlocks += (totalXp == 0 ? 0 : 1 ); + + // Calculate the XP for any exploded block: + for ( MineTargetPrisonBlock targetExplodedBlock : pmEvent.getTargetExplodedBlocks() ) { + + totalXp += xpCalculateBlockXP( targetExplodedBlock, player ); + totalBonusXp += xpCalculateBonusXP( targetExplodedBlock, player, itemInHand ); + + totalBlocks++; + } + + xp = totalXp + totalBonusXp; + + if ( totalXp > 0 || totalBonusXp > 0 ) { + + String message = String.format( "(XP calcs: blocks: %d xp: %d bonusXp: %d) ", + totalBlocks, totalXp, totalBonusXp ); + + debugInfo.append( message ); - player.dropXPOrbs( xp ); -// tech.mcprison.prison.util.Location dropPoint = player.getLocation().add( player.getLocation().getDirection()); -// ((ExperienceOrb) player.getWorld().spawn(dropPoint, ExperienceOrb.class)).setExperience(xp); - } - else { - player.giveExp( xp ); - } - } } } - if ( Output.get().isDebug() || Output.get().isDebug( DebugTarget.blockBreak ) || - Output.get().isDebug( DebugTarget.blockBreakXpCalcs )) { + + return xp; + } + + private int xpCalculateBlockXP( MineTargetPrisonBlock targetBlock, SpigotPlayer player ) + { + int xp = 0; + + if ( targetBlock != null && targetBlock.getMinedBlock() != null ) { - String message = String.format( "XP calculations: %s %s blocks: %d xp: %d bonusXp: %d " + - " isCalculateXPEnabled: %s givePlayerXPAsOrbDrops %s ", - player.getName(), blockName, count, totalXp, bonusXp, - Boolean.toString( isBoolean(AutoFeatures.isCalculateXPEnabled) ), - Boolean.toString( isBoolean( AutoFeatures.givePlayerXPAsOrbDrops ) ) ); + SpigotBlock sBlock = ((SpigotBlock) targetBlock.getMinedBlock()); - if ( Output.get().isDebug() || Output.get().isDebug( DebugTarget.blockBreak ) ) { - debugInfo.append( "(" ).append( message ).append( ")" ); + xp += calculateXP( sBlock.getPrisonBlock().getBlockName() ); + + } + return xp; + } + private int xpCalculateBonusXP( MineTargetPrisonBlock targetBlock, SpigotPlayer player, ItemStack itemInHand ) + { + int xp = 0; + + if ( targetBlock != null && targetBlock.getMinedBlock() != null ) { + + SpigotBlock sBlock = ((SpigotBlock) targetBlock.getMinedBlock()); + + // Bonus XP: + xp = checkCrazyEnchant( player.getWrapper(), sBlock.getWrapper(), itemInHand ); + + } + return xp; + } + + + /** + *

Gives XP to the player, either as Orbs or directly. + *

+ * + * @param player + * @param totalXp + * @param debugInfo + */ + protected void xpGivePlayerXp(SpigotPlayer player, int totalXp, StringBuilder debugInfo ) { + + if ( totalXp > 0 ) { + + boolean giveXpOrbs = isBoolean( AutoFeatures.givePlayerXPAsOrbDrops ); + + if ( giveXpOrbs ) { + player.dropXPOrbs( totalXp ); +// tech.mcprison.prison.util.Location dropPoint = player.getLocation().add( player.getLocation().getDirection()); +// ((ExperienceOrb) player.getWorld().spawn(dropPoint, ExperienceOrb.class)).setExperience(xp); } - if ( Output.get().isDebug( DebugTarget.blockBreakXpCalcs ) ) { - - Output.get().logDebug( DebugTarget.blockBreakXpCalcs, message ); + else { + player.giveExp( totalXp ); } + debugInfo.append( "(xp " + totalXp + ( giveXpOrbs ? "Orbs" : "direct") + ") " ); } + } @@ -1708,6 +2029,10 @@ private boolean isToolDisabled( Player player ) { } /** + *

This is calculated only once per block break event, no matter how many blocks + * are involved. + *

+ * *

This should calculate and apply the durability consumption on the tool. *

* @@ -1744,45 +2069,55 @@ private boolean isToolDisabled( Player player ) { * Zero always disables this calculation and allows normal durability calculations * to be performed. 100 always prevents wear. */ - protected void calculateAndApplyDurability(Player player, SpigotItemStack itemInHand, int durabilityResistance) { + protected void calculateAndApplyDurability(Player player, SpigotItemStack itemInHand, int blocksMined, + int durabilityResistance, StringBuilder debugInfo ) { - if ( itemInHand != null && !itemInHand.isAir() ) { + // If no tool, or durabilityResistance is less than 100: + if ( itemInHand != null && !itemInHand.isAir() && durabilityResistance < 100 ) { Compatibility compat = SpigotCompatibility.getInstance(); int maxDurability = compat.getDurabilityMax( itemInHand ); int durability = compat.getDurability( itemInHand ); - short damage = 1; // Generally 1 unless instant break block then zero. + short totalDamage = 1; // Generally 1 unless instant break block then zero. int durabilityLevel = 0; boolean toolBreak = false; // Need to skip processing on empty item stacks and items that have no max durability if ( maxDurability > 0 ) { + short damage = 1; + if ( itemInHand.getBukkitStack().containsEnchantment( Enchantment.DURABILITY)) { + durabilityLevel = itemInHand.getBukkitStack().getEnchantmentLevel( Enchantment.DURABILITY ); + } - if ( durabilityResistance >= 100 ) { - damage = 0; - } else if ( durabilityResistance > 0 ) { - if ( getRandom().nextInt( 100 ) <= durabilityResistance ) { + for ( int y = 0; y < blocksMined; y++ ) { + if ( durabilityResistance >= 100 ) { damage = 0; + } + else if ( durabilityResistance > 0 ) { + if ( getRandom().nextInt( 100 ) <= durabilityResistance ) { + damage = 0; + } } - } - - if ( damage > 0 && itemInHand.getBukkitStack().containsEnchantment( Enchantment.DURABILITY)) { - durabilityLevel = itemInHand.getBukkitStack().getEnchantmentLevel( Enchantment.DURABILITY ); - // the chance of losing durability is 1 in (1+level) - // So if the random int == 0, then take damage, otherwise none. - if (getRandom().nextInt( 1 + durabilityLevel ) > 0) { - damage = 0; + if ( damage > 0 && durabilityLevel > 0 ) { + + // the chance of losing durability is 1 in (1+level) + // So if the random int == 0, then take damage, otherwise none. + if (getRandom().nextInt( 1 + durabilityLevel ) > 0) { + damage = 0; + } } + + totalDamage += damage; } - int newDurability = durability + damage; + int newDurability = durability + totalDamage; int remainingDurability = maxDurability - newDurability; - if (damage > 0 && + if (totalDamage > 0 && (!isBoolean( AutoFeatures.isPreventToolBreakage ) || isBoolean( AutoFeatures.isPreventToolBreakage ) && remainingDurability >= getInteger( AutoFeatures.preventToolBreakageThreshold ) ) ) { @@ -1803,21 +2138,12 @@ protected void calculateAndApplyDurability(Player player, SpigotItemStack itemIn } } - - if ( Output.get().isDebug( DebugTarget.blockBreakDurability ) ) { - - String message = String.format( "calculateAndApplyDurability: %s: maxDurability= %d " + - "durability: %d damage: %d durResistance: %d toolDurabilityLvl: %d %s", - itemInHand.getName(), maxDurability, durability, damage, - durabilityResistance, durabilityLevel, - (toolBreak ? "[Broke]" : "") ); - -// if ( Output.get().isDebug() || Output.get().isDebug( DebugTarget.blockBreak ) ) { -// debugInfo.append( "(" ).append( message ).append( ")" ); -// -// } - Output.get().logDebug( DebugTarget.blockBreakDurability, message ); - } + String message = String.format( "(calcDurability: %s: maxDurability= %d " + + "durability: %d damage: %d durResistance: %d toolDurabilityLvl: %d %s) ", + itemInHand.getName(), maxDurability, durability, totalDamage, + durabilityResistance, durabilityLevel, + (toolBreak ? "[Broke]" : "") ); + debugInfo.append( message ); } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java index e98316b7a..7327c0e6f 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java @@ -1,10 +1,5 @@ package tech.mcprison.prison.spigot.utils; -import java.text.DecimalFormat; - -import org.bukkit.attribute.Attribute; -import org.bukkit.attribute.AttributeModifier; -import org.bukkit.entity.Item; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -15,16 +10,9 @@ import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.metadata.FixedMetadataValue; - -import com.google.common.collect.Multimap; -import tech.mcprison.prison.bombs.MineBombData; import tech.mcprison.prison.output.Output; -import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.block.SpigotBlock; -import tech.mcprison.prison.spigot.block.SpigotItemStack; -import tech.mcprison.prison.spigot.game.SpigotPlayer; /** *

This listener class handles the player's interaction with using a bomb. @@ -42,83 +30,32 @@ public class PrisonBombListener { -// @EventHandler( priority = EventPriority.LOW ) + @EventHandler( priority = EventPriority.LOW ) public void onInteract( PlayerInteractEvent event ) { // if ( !event.getPlayer().hasPermission("prison.minebombs.use") ) { // return; // } - Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent 01 " ); + //Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent 01 " ); if ( event.getAction().equals(Action.RIGHT_CLICK_BLOCK) || event.getAction().equals(Action.RIGHT_CLICK_AIR) ) { // If the player is holding a mine bomb, then get the bomb and decrease the // ItemStack in the player's hand by 1: - MineBombData bomb = PrisonUtilsMineBombs.getBombInHand( event.getPlayer() ); - Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent 02 is bomb null " + (bomb == null) ); - - if ( bomb != null ) { - - Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent 03 " ); - - Player player = event.getPlayer(); - - SpigotPlayer sPlayer = new SpigotPlayer( player ); - - // if the bomb is not activated, then that indicates that the players is - // under a cooldown and the bomb cannot be used, nor has it been removed from their - // inventory. - if ( bomb.isActivated() ) { - -// Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent 04 " ); + Player player = event.getPlayer(); + SpigotBlock sBlock = new SpigotBlock( event.getClickedBlock() ); + +// Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent 02 " ); + if ( PrisonUtilsMineBombs.setBombInHand( player, sBlock ) ) { - SpigotItemStack bombs = PrisonUtilsMineBombs.getItemStackBomb( bomb ); - - if ( bombs != null ) { - - Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent 05 " ); - - SpigotBlock sBlock = new SpigotBlock( event.getClickedBlock() ); - - Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent dropping block " ); - - int throwSpeed = 2; - -// final Item dropped = player.getWorld().dropItem(player.getLocation(), bombs.getBukkitStack() ); -// dropped.setVelocity(player.getLocation().getDirection().multiply( throwSpeed ).normalize() ); -// dropped.setPickupDelay( 50000 ); -// -// dropped.setGlowing( bomb.isGlowing() ); -// dropped.setCustomName( bomb.getName() ); -// -// dropped.setMetadata( "prisonMineBomb", new FixedMetadataValue( SpigotPrison.getInstance(), true ) ); -// //dropped.setMetadata( "prisonMineName", new FixedMetadataValue( SpigotPrison.getInstance(), "mineName" ) ); -// -// -// PrisonUtilsMineBombs.setoffBombDelayed( sPlayer, bomb, dropped, sBlock, throwSpeed ); - - } - } - else { - - String playerUUID = player.getUniqueId().toString(); - int cooldownTicks = PrisonUtilsMineBombs.checkPlayerCooldown( playerUUID ); - float cooldownSeconds = cooldownTicks / 2.0f; - DecimalFormat dFmt = new DecimalFormat( "0.0" ); - - String message = - String.format( "You cannot use another Prison Mine Bomb for %s seconds.", - dFmt.format( cooldownSeconds ) ); - sPlayer.sendMessage( message ); - } + // The item was a bomb and it was activated. + // Cancel the event so the item will not be placed or processed farther. + Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent 03 Bomb activated " ); + event.setCancelled( true ); } - else { - - // Do nothing since this means the event is not Prison Mine Bomb related. - } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java index a195b6abc..03218096d 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java @@ -1,5 +1,6 @@ package tech.mcprison.prison.spigot.utils; +import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -13,11 +14,14 @@ import com.cryptomorin.xseries.XMaterial; +import tech.mcprison.prison.autofeatures.AutoFeaturesWrapper; +import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; import tech.mcprison.prison.bombs.MineBombData; import tech.mcprison.prison.bombs.MineBombs; import tech.mcprison.prison.commands.Arg; import tech.mcprison.prison.commands.Command; import tech.mcprison.prison.internal.CommandSender; +import tech.mcprison.prison.internal.block.BlockFace; import tech.mcprison.prison.output.LogLevel; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.SpigotPrison; @@ -28,6 +32,7 @@ import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.game.SpigotWorld; import tech.mcprison.prison.util.Location; +import tech.mcprison.prison.util.Text; public class PrisonUtilsMineBombs extends PrisonUtils @@ -380,7 +385,8 @@ public static SpigotItemStack getItemStackBomb( MineBombData bomb ) { lore.add( "Size, Diameter: " + ( 1 + 2 * bomb.getRadius()) ); lore.add( "Shape: " + bomb.getExplosionShape() ); - String[] desc = bomb.getDescription().split( " " ); + String bombDesc = bomb.getDescription(); + String[] desc = ( bombDesc == null ? "" : bombDesc ).split( " " ); StringBuilder sb = new StringBuilder(); for ( String d : desc ) { @@ -422,44 +428,121 @@ public static SpigotItemStack getItemStackBomb( MineBombData bomb ) { * @param player * @return */ - public static MineBombData getBombInHand( Player player ) { - MineBombData results = null; + public static boolean setBombInHand( Player player, SpigotBlock sBlock ) { + boolean isABomb = false; + SpigotItemStack itemInHand = SpigotCompatibility.getInstance().getPrisonItemInMainHand( player ); if ( itemInHand != null ) { List lore = itemInHand.getLore(); - if ( lore.size() > 1 && - lore.get( 0 ).equalsIgnoreCase( MINE_BOMBS_LORE_1 ) && - lore.get( 1 ).startsWith( MINE_BOMBS_LORE_2_PREFIX )) { + String prisonBombId = lore.size() > 0 ? Text.stripColor( lore.get( 0 ) ) : ""; + String bombName = lore.size() > 1 ? Text.stripColor( lore.get( 1 ) ).trim() : ""; + + if ( prisonBombId.equalsIgnoreCase( Text.stripColor( MINE_BOMBS_LORE_1 )) ) { - String bombName = lore.get( 1 ).replace( MINE_BOMBS_LORE_2_PREFIX, "" ); + + + // String bombName = lore1.trim(); MineBombs mBombs = MineBombs.getInstance(); - results = mBombs.findBomb( bombName ); + MineBombData bomb = mBombs.findBomb( bombName ); + + String prisonExplosiveHandlerPriority = AutoFeaturesWrapper.getInstance().getMessage( + AutoFeatures.ProcessPrisons_ExplosiveBlockBreakEventsPriority ); + + if ( bomb != null && "DISABLED".equalsIgnoreCase( prisonExplosiveHandlerPriority ) ) { + Output.get().logWarn( "A Prison Mine Bomb was attempted to be used, but the " + + "handling of its explosion is DISABLED. Edit the 'autoFeaturesConfig.yml' " + + "file and set 'ProcessPrisons_ExplosiveBlockBreakEventsPriority: NORMAL'." ); + } - String playerUUID = player.getUniqueId().toString(); + else if ( bomb != null ) { + + SpigotPlayer sPlayer = new SpigotPlayer( player ); + + String playerUUID = player.getUniqueId().toString(); + int cooldownTicks = checkPlayerCooldown( playerUUID ); - if ( results != null && - checkPlayerCooldown( playerUUID ) == 0 ) { + if ( cooldownTicks == 0 ) { + + isABomb = true; + + // Setting activated to true indicates the bomb is live and it has + // been removed from the player's inventory: + bomb.setActivated( true ); + itemInHand.setAmount( itemInHand.getAmount() - 1 ); + + // Remove from inventory: + SpigotCompatibility.getInstance().setItemInMainHand( player, itemInHand.getBukkitStack() ); + + // Set cooldown: + PrisonUtilsMineBombs.addPlayerCooldown( playerUUID ); + + SpigotItemStack bombs = PrisonUtilsMineBombs.getItemStackBomb( bomb ); + + if ( bombs != null ) { + + Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent 05 " ); + + // SpigotBlock sBlock = new SpigotBlock( event.getClickedBlock() ); + + Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent dropping block " ); + + int throwSpeed = 2; + + // This places the item so it will float: + final Item dropped = player.getWorld().dropItem(player.getLocation(), bombs.getBukkitStack() ); + dropped.setPickupDelay( Integer.MAX_VALUE ); + dropped.setCustomName( bomb.getName() ); + dropped.setVelocity(player.getLocation().getDirection().multiply( throwSpeed ).normalize() ); + + int delayInTicks = 5 * 20; // 5 secs + + + // Get the block that is y - 1 lower than the original block: + SpigotBlock bombBlock = (SpigotBlock) sBlock.getRelative( BlockFace.DOWN ); + + // Submit the bomb's task to go off: + PrisonUtilsMineBombs.setoffBombDelayed( sPlayer, bomb, dropped, bombBlock, delayInTicks ); + - // Setting activated to true indicates the bomb is live and it has - // been removed from the player's inventory: - results.setActivated( true ); - itemInHand.setAmount( itemInHand.getAmount() - 1 ); + + + // setGlow is invalid for spigot 1.8.8: + //dropped.setGlowing( bomb.isGlowing() ); + + // setGravity is invalid for spigot 1.8.8: +// dropped.setGravity( false ); + + + +// dropped.setMetadata( "prisonMineBomb", new FixedMetadataValue( SpigotPrison.getInstance(), true ) ); + //dropped.setMetadata( "prisonMineName", new FixedMetadataValue( SpigotPrison.getInstance(), "mineName" ) ); + + + } + } - // Remove from inventory: - SpigotCompatibility.getInstance().setItemInMainHand( player, itemInHand.getBukkitStack() ); + else { + + float cooldownSeconds = cooldownTicks / 2.0f; + DecimalFormat dFmt = new DecimalFormat( "0.0" ); + + String message = + String.format( "You cannot use another Prison Mine Bomb for %s seconds.", + dFmt.format( cooldownSeconds ) ); + sPlayer.sendMessage( message ); - // Set cooldown: - PrisonUtilsMineBombs.addPlayerCooldown( playerUUID ); + } + } } } - return results; + return isABomb; } public static boolean addPlayerCooldown( String playerUUID ) { @@ -531,6 +614,11 @@ public void run() { droppedBomb.remove(); Location location = sBlock.getLocation(); + + if ( location == null ) { + location = sPlayer.getLocation(); + } + SpigotWorld world = (SpigotWorld) location.getWorld(); MineBombs mBombs = MineBombs.getInstance(); @@ -559,8 +647,16 @@ public void run() { explodeEvent.setTriggeredBy( bomb.getName() ); explodeEvent.setMineBomb( bomb ); + + // Normally the explosion will ONLY work if the center target block was non-AIR. + // This setting allows the explosion to be processed even if it is air. + explodeEvent.setForceIfAirBlock( true ); + Bukkit.getServer().getPluginManager().callEvent( explodeEvent ); + if ( !explodeEvent.isCancelled() ) { + // If it wasn't canceled, then it may not have been handled + } } From 08ac200612fafe2d9f8f738bbde6c3ace3390874 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Thu, 28 Oct 2021 00:11:25 -0400 Subject: [PATCH 098/283] Fixed an issue with adding a non-block item to a mine. It now validates that the specified item is a block. Also if a specified block is not in a mine when trying to remove it, it will now display a message indicating that nothing was removed. --- docs/changelog_v3.3.x.md | 6 +++++- .../prison/mines/commands/MinesBlockCommands.java | 12 ++++++++++++ .../tech/mcprison/prison/mines/data/MineData.java | 11 +++++++---- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 6d5507d21..fe7b326ba 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,11 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.3 2021-10-26 +# 3.2.11-alpha.3 2021-10-28 + + +* **Fixed an issue with adding a non-block item to a mine.** +It now validates that the specified item is a block. Also if a specified block is not in a mine when trying to remove it, it will now display a message indicating that nothing was removed. * **Major rewrites to how auto features work.** diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesBlockCommands.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesBlockCommands.java index 1a473f3bd..b3998c782 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesBlockCommands.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesBlockCommands.java @@ -71,6 +71,12 @@ public void addBlockCommand(CommandSender sender, return; } + if ( !prisonBlock.isBlock() ) { + pMines.getMinesMessages().getLocalizable("not_a_block"). + withReplacements(block).sendTo(sender); + return; + } + // if (m.isInMine(prisonBlock)) { // pMines.getMinesMessages().getLocalizable("block_already_added"). @@ -622,6 +628,12 @@ public void delBlockCommand(CommandSender sender, deleteBlock( sender, pMines, m, preexistingPrisonBlock ); } + else { + + pMines.getMinesMessages().getLocalizable("block_not_removed") + .sendTo(sender); + return; + } } else { diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java index 155c71f65..88f85b32b 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java @@ -867,10 +867,13 @@ public boolean isInMine(PrisonBlock blockType) { public PrisonBlock getPrisonBlock( PrisonBlock blockType ) { PrisonBlock results = null; - for (PrisonBlock block : getPrisonBlocks()) { - if (blockType.getBlockNameFormal().equalsIgnoreCase( block.getBlockNameFormal())) { - results = block; - break; + if ( blockType != null && blockType.getBlockNameFormal() != null ) { + + for (PrisonBlock block : getPrisonBlocks()) { + if ( block.getBlockNameFormal().equalsIgnoreCase( blockType.getBlockNameFormal() )) { + results = block; + break; + } } } From 9bcef33e4d149d44c29f6aa67663f53ca8ed7d59 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 29 Oct 2021 02:38:17 -0400 Subject: [PATCH 099/283] Starting to add some video documents for prison. --- docs/changelog_v3.3.x.md | 5 +- docs/prison_video_000_video_list.md | 32 ++++++ docs/prison_video_001_auto_configure.md | 108 +++++++++++++++++++++ docs/prison_video_002_after_auto_config.md | 36 +++++++ 4 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 docs/prison_video_000_video_list.md create mode 100644 docs/prison_video_001_auto_configure.md create mode 100644 docs/prison_video_002_after_auto_config.md diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index fe7b326ba..4256375f4 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,10 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.3 2021-10-28 +# 3.2.11-alpha.3 2021-10-29 + + +* **Starting to add some video documents for prison.** * **Fixed an issue with adding a non-block item to a mine.** diff --git a/docs/prison_video_000_video_list.md b/docs/prison_video_000_video_list.md new file mode 100644 index 000000000..013f4784d --- /dev/null +++ b/docs/prison_video_000_video_list.md @@ -0,0 +1,32 @@ +# Prison Video Listings + +


+ +[Prison Documents - Table of Contents](prison_docs_000_toc.md) + + +## Prison Videos - Basic Setup + + +* **[Prison Video - Auto Configure](prison_video_001_auto_configure.md)** + +This video covers the very basics on what you need to do to get your Prison server up and running. Prison has an Auto Configure feature that will setup almost everything you need to run the most basic Prison Server. + + +* **[Prison Video - After Running Auto Configure - Setting Up The Physical Mines](prison_video_002_after_auto_config.md)** + +Prison's Auto Configure configures almost everything needed to run a basic Prison Server, including creating all of the virtual mines with assigned blocks, a mine liner, and links the mines to the proper ranks. This video covers how to place a mine, which takes a virtual mine and turns it in to a physical mine. This video covers the different ways you can place a mine. + + + +## Future Videos Coming Soon + + +* **Prison Video - Mine Liners** + + +* **Prison Video - Adjusting the Size of Your Mines** + + + +
\ No newline at end of file diff --git a/docs/prison_video_001_auto_configure.md b/docs/prison_video_001_auto_configure.md new file mode 100644 index 000000000..5d00bcf9e --- /dev/null +++ b/docs/prison_video_001_auto_configure.md @@ -0,0 +1,108 @@ +# Prison Videos + +
+ +[Prison Documents - Table of Contents](prison_docs_000_toc.md) + +[Prison Video Listings](prison_video_000_video_list.md) + + +# Prison Videos - Basic Setup - Auto Configure + +This video covers the very basics on what you need to do to get your Prison server up and running. Prison has an Auto Configure feature that will setup almost everything you need to run the most basic Prison Server. + + +[video url goes here](url.to.video.com) + + +This document is the transcript for this video. It includes a few screen prints, URLs to resources, and copy and pastable commands. This document will also contain some updates, more information, and clarifications if they are needed. + + +
+ + +#Video Transcript + +> "Hello, this is RoyalBlueRanger and I'm the lead developer of the Prison Plugin. Thank you for your interest in Prison, and for taking the time to view this video. This video will cover the basic setup of a Prison server, which can serve as the foundation of building a uniquely customized server of your own." +> +> +> "If you ever need help with Prison, Please visit our Discord server. You will also find on our Discord server the latest alpha releases, which not only fixes any bugs or issues found, but also contains the new updates that will be included in Prison's next release." +> + +Prison's Discord server: +[![Discord](https://discordapp.com/api/guilds/332602419483770890/widget.png)](https://discord.gg/DCJ3j6r) + +> +> "Prison works great on Spigot 1.8.8 through Spigot 1.17.1. Since it's built on Spigot, it will also work great on other platforms based upon Bukkit and Spigot, such as paper. For the purpose of this demonstration video, I'm using Spigot 1.8.8." +> +> +> "I should point out that this video will not cover the details on how to build a Spigot server; that would be the subject of a future video. For this video it is assumed you have your sever built and it's ready to be started. But before you start your server, let's first go over some of the basic plugins you will need." +> +> +> "All plugins will need to be placed in the **plugins** directory within your Spigot server's directory. If you do not see that directory, go ahead and create it manually, or just start the server for the first time and spigot will create it for you." +> +> +> "Download the following plugins, which will be in **jar** files. You can find the URLs for these resources within this video's description below, and also within Prison's documentation for this video. You will need this plugin, which is of course **Prison**. Plus **EssentialsX**, **Vault**, **LuckPerms**, **WorldEdit**, and **WorldGuard**. Please note for all of these listed plugins, download the latest version that is available, except for Vault, WorldEdit and WorldGuard, of which you must use the version that is designed for your version of Spigot." +> + +(URLs to all mentioned plugins) + * Prison + - Download - https://www.spigotmc.org/resources/prison.1223/ + * EssentialsX + - https://www.spigotmc.org/resources/essentialsx.9089/ + - Download - https://essentialsx.net/downloads.html?branch=stable - Download only the stable release of the "core" component. + * Vault + - Download - 1.13 to 1.17 - https://www.spigotmc.org/resources/vault.34315/ + - Download - 1.8 to 1.11 use v1.5.6 - https://dev.bukkit.org/projects/vault/files + * LuckPerms + - Download - https://www.spigotmc.org/resources/luckperms.28140/ + - Download - https://luckperms.net/ + * WorldEdit + - Download - https://dev.bukkit.org/projects/worldedit/files + * WorldGuard + - Download - https://dev.bukkit.org/projects/worldguard/files + +(Screen prints of basic directories prior to starting the server the first time) + +> +> "Let me show you the directories of this test server. As you can see, in the server's directory is the plugins folder, the eula.txt file that has been set to `true` so the server starts up fully for the first time, and the spigot jar file along with the startup script to start the server. As you can also see in the plugins directory, are the previously listed plugins." +> +> +> +> "Once you have placed all of these plugins in the server's **plugin** directory, you can can then start your server. Let it fully startup. It may be a good idea to review the startup messages to ensure everything loaded successfully. Every time you add a new plugin, or make significant changes, you should review the startup messages in the console if something appears to be misbehaving. With these few plugins, the server should startup with no issues, especially if you are using the correct version of Vault, WorldEdit and WorldGuard." +> +> +> "Before we configure Prison, let me first introduce you to some very basic details about Prison. For the purpose of this video, and when using most Prison commands that generate a lot of text and information, it's best to run them within the server's console, instead of in-game." +> +> +> "First off, it is important to know that all commands within Prison can be reviewed with the command `/prison`. This command lists all of Prison's root commands that are available, including any commands that had a conflict with another plugin's commands when prison was registering it's commands. If a listed command has subcommands, it will be indicated in that list. You can then enter that command to drill down to see the list of subcommands." +> + +(Screen print of `/prison`) + +> +> "Another important feature with Prison, is that Prison's command handler is able to provide detailed information about the command, including all parameters, permissions, and even links to some online documentation. To view the **help**, all you need to do is to add the `help` keyword to any command. For example: `/ranks autoConfigure help` provides detailed information on the autoConfigure command. +> + +(Screen print of `/prison autoConfigure help`) + +> +> "Finally let's get to the purpose of this video, running Prison's autoConfigure command." +> +> "From the server's console, enter the command:" +> `/ranks autoConfigure` +> +> "The command will run for a few seconds, generate a lot of text, which documents all of the configurations that it sets up. Review the generated text in the console if you like." +> +> +> "And that's it. This is the end of the video, which just covered the basics of running the command `/prison autoConfigure`. The Prison server is now using the most common features and settings enabled that will allow your server to work properly." +> +> +> "In the next video we will cover what you need to do in-game to finalize your server setup, which is also very simple. The details that will be covered is configuring WorldGuard to protect your Prison world so players cannot break blocks outside of the mines. It will also explain the various ways you can **set the mines** which will turn the virtual mines in to fully functional physical mines. At the end of that video, we will have a fully functional Prison server." + + +(end of video) + +
+ + diff --git a/docs/prison_video_002_after_auto_config.md b/docs/prison_video_002_after_auto_config.md new file mode 100644 index 000000000..881d37975 --- /dev/null +++ b/docs/prison_video_002_after_auto_config.md @@ -0,0 +1,36 @@ +# Prison Videos + +
+ +[Prison Documents - Table of Contents](prison_docs_000_toc.md) + +[Prison Video Listings](prison_video_000_video_list.md) + + +# Prison Videos - Basic Setup +# After Running Auto Configure - Setting Up The Physical Mines + +This video covers the very basics on what you need to do to get your Prison server up and running. Prison has an Auto Configure feature that will setup almost everything you need to run the most basic Prison Server. + + +[video url goes here](url.to.video.com) + + +This document is the transcript for this video. It includes a few screen prints, URLs to resources, and copy and pastable commands. This document will also contain some updates, more information, and clarifications if they are needed. + + +
+ + +#Video Transcript + +> "Hello, this is RoyalBlueRanger and I'm the lead developer of the Prison Plugin. Thank you for your interest in Prison, and for taking the time to view this video. This video will cover the basic setup of a Prison server, which can serve as the foundation of building a uniquely customized server of your own." +> +> +> "If you ever need help with Prison, Please visit our Discord server. You will also find on our Discord server the latest alpha releases, which not only fixes any bugs or issues found, but also contains the new updates that will be included in Prison's next release." +> +> + (to be determined...) + + +
\ No newline at end of file From 8a242d7fd6cb5d0fdde10fe9f72c31e013d1d039 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sat, 30 Oct 2021 03:50:15 -0400 Subject: [PATCH 100/283] Fixed an issue with /mines block list when an incorrect mine name is used. Now displays an error stating the name is invalid. --- docs/changelog_v3.3.x.md | 6 +++++- .../mcprison/prison/mines/commands/MinesBlockCommands.java | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 4256375f4..3cf901438 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,11 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.3 2021-10-29 +# 3.2.11-alpha.3 2021-10-30 + + +* **Fixed an issue with /mines block list when an incorrect mine name is used.** +Now displays an error stating the name is invalid. * **Starting to add some video documents for prison.** diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesBlockCommands.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesBlockCommands.java index b3998c782..44041d8e8 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesBlockCommands.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesBlockCommands.java @@ -909,6 +909,11 @@ public void listBlockCommand(CommandSender sender, PrisonMines pMines = PrisonMines.getInstance(); Mine m = pMines.getMine(mineName); + if ( m == null ) { + sender.sendMessage( "Invalid mine name." ); + return; + } + DecimalFormat dFmt = new DecimalFormat("#,##0"); DecimalFormat fFmt = new DecimalFormat("#,##0.00"); From adafc39a77d056c667b451cca27fcdd7d0f40b09 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sat, 30 Oct 2021 03:53:26 -0400 Subject: [PATCH 101/283] Changed the location usage with block event placeholders, which now uses the location that is tied to the targetBlock instead of the mined block. The mined block may be null so it's not stable. --- docs/changelog_v3.3.x.md | 4 +++ .../prison/mines/data/MineScheduler.java | 32 ++++++++++++------- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 3cf901438..16844fa4e 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.3 2021-10-30 +* **Changed the location usage with block event placeholders, which now uses the location that is tied to the targetBlock instead of the mined block.** +The mined block may be null so it's not stable. + + * **Fixed an issue with /mines block list when an incorrect mine name is used.** Now displays an error stating the name is invalid. diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineScheduler.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineScheduler.java index a56cfdc82..503f70ac2 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineScheduler.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineScheduler.java @@ -24,6 +24,7 @@ import tech.mcprison.prison.tasks.PrisonCommandTask.CustomPlaceholders; import tech.mcprison.prison.tasks.PrisonRunnable; import tech.mcprison.prison.tasks.PrisonTaskSubmitter; +import tech.mcprison.prison.util.Location; public abstract class MineScheduler extends MineTasks @@ -573,6 +574,7 @@ private void processBlockEventDetails( Player player, PrisonBlock prisonBlock, boolean fireEvent = blockEvent.isFireEvent( chance, eventType, targetBlock, triggered ); + if ( fireEvent ) { // If perms are set, check them, otherwise ignore perm check: @@ -591,17 +593,21 @@ private void processBlockEventDetails( Player player, PrisonBlock prisonBlock, cmdTask.addCustomPlaceholder( CustomPlaceholders.blockName, originalBlock.getBlockName() ); cmdTask.addCustomPlaceholder( CustomPlaceholders.mineName, getName() ); - if ( prisonBlock.getLocation() != null ) { - cmdTask.addCustomPlaceholder( CustomPlaceholders.locationWorld, prisonBlock.getLocation().getWorld().getName() ); - cmdTask.addCustomPlaceholder( CustomPlaceholders.locationX, Integer.toString( prisonBlock.getLocation().getBlockX() )); - cmdTask.addCustomPlaceholder( CustomPlaceholders.locationY, Integer.toString( prisonBlock.getLocation().getBlockY() )); - cmdTask.addCustomPlaceholder( CustomPlaceholders.locationZ, Integer.toString( prisonBlock.getLocation().getBlockZ() )); + if ( targetBlock.getLocation() != null ) { + Location location = targetBlock.getLocation(); + + cmdTask.addCustomPlaceholder( CustomPlaceholders.locationWorld, location.getWorld().getName() ); + cmdTask.addCustomPlaceholder( CustomPlaceholders.locationX, Integer.toString( location.getBlockX() )); + cmdTask.addCustomPlaceholder( CustomPlaceholders.locationY, Integer.toString( location.getBlockY() )); + cmdTask.addCustomPlaceholder( CustomPlaceholders.locationZ, Integer.toString( location.getBlockZ() )); + + cmdTask.addCustomPlaceholder( CustomPlaceholders.coordinates, location.toCoordinates() ); + cmdTask.addCustomPlaceholder( CustomPlaceholders.worldCoordinates, location.toWorldCoordinates() ); - cmdTask.addCustomPlaceholder( CustomPlaceholders.coordinates, prisonBlock.getLocation().toCoordinates() ); - cmdTask.addCustomPlaceholder( CustomPlaceholders.worldCoordinates, prisonBlock.getLocation().toWorldCoordinates() ); + cmdTask.addCustomPlaceholder( CustomPlaceholders.blockCoordinates, targetBlock.getBlockCoordinates() ); } - cmdTask.addCustomPlaceholder( CustomPlaceholders.blockCoordinates, prisonBlock.getBlockCoordinates() ); +// cmdTask.addCustomPlaceholder( CustomPlaceholders.blockCoordinates, prisonBlock.getBlockCoordinates() ); cmdTask.addCustomPlaceholder( CustomPlaceholders.blockChance, dFmt.format( originalBlock.getChance() ) ); @@ -619,10 +625,12 @@ private void processBlockEventDetails( Player player, PrisonBlock prisonBlock, cmdTask.addCustomPlaceholder( CustomPlaceholders.blockIsAir, Boolean.toString( targetBlock.getPrisonBlock().isAir() )); - - cmdTask.addCustomPlaceholder( CustomPlaceholders.blockMinedName, prisonBlock.getBlockName() ); - cmdTask.addCustomPlaceholder( CustomPlaceholders.blockMinedNameFormal, prisonBlock.getBlockNameFormal() ); - cmdTask.addCustomPlaceholder( CustomPlaceholders.blockMinedBlockType, prisonBlock.getBlockType().name() ); + if ( prisonBlock != null ) { + + cmdTask.addCustomPlaceholder( CustomPlaceholders.blockMinedName, prisonBlock.getBlockName() ); + cmdTask.addCustomPlaceholder( CustomPlaceholders.blockMinedNameFormal, prisonBlock.getBlockNameFormal() ); + cmdTask.addCustomPlaceholder( CustomPlaceholders.blockMinedBlockType, prisonBlock.getBlockType().name() ); + } cmdTask.addCustomPlaceholder( CustomPlaceholders.eventType, eventType.name() ); cmdTask.addCustomPlaceholder( CustomPlaceholders.eventTriggered, triggered ); From d3ec16a7eed81925c1514e6e66b6ee0d14c25e20 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sat, 30 Oct 2021 03:54:02 -0400 Subject: [PATCH 102/283] Changed the location usage with block event placeholders, which now uses the location that is tied to the targetBlock instead of the mined block. The mined block may be null so it's not stable. --- .../internal/block/MineTargetPrisonBlock.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetPrisonBlock.java b/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetPrisonBlock.java index e8543b3f1..667885713 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetPrisonBlock.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetPrisonBlock.java @@ -87,6 +87,21 @@ public MineTargetBlockKey getBlockKey() { return blockKey; } + public String getBlockCoordinates() { + StringBuilder sb = new StringBuilder(); + + sb.append( getPrisonBlock().getBlockName() ); +// sb.append( getPrisonBlock().getBlockNameFormal() ); + + if ( getLocation() != null ) { + sb.append( "::" ); + + sb.append( getLocation().toWorldCoordinates() ); + } + + return sb.toString(); + } + /** *

This is a quick way to check to see if the block was originally set to air, or if * the block was previously broke and "counted". This field, airBroke, needs to be From cd43a8596de19af4056f5891e0c906c84ae01889 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sat, 30 Oct 2021 04:58:36 -0400 Subject: [PATCH 103/283] Adjustments to get block events, such as decays, to work correctly with the new auto feature block event handlers. Block events were moved to be processed after the block is broke. Also if a block has already been processed, it now will cancel the event to prevent normal block breakage when none should happen. At this point, the new auto manager appears to be working really well. --- docs/changelog_v3.3.x.md | 5 + .../api/PrisonMinesBlockBreakEvent.java | 5 + .../spigot/block/OnBlockBreakEventCore.java | 110 ++++++++++++++---- 3 files changed, 99 insertions(+), 21 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 16844fa4e..1dfc3d6aa 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,11 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.3 2021-10-30 +* **Adjustments to get block events, such as decays, to work correctly with the new auto feature block event handlers.** + Block events were moved to be processed after the block is broke. Also if a block has already been processed, it now will cancel the event to prevent normal block breakage when none should happen. +At this point, the new auto manager appears to be working really well. + + * **Changed the location usage with block event placeholders, which now uses the location that is tied to the targetBlock instead of the mined block.** The mined block may be null so it's not stable. diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockBreakEvent.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockBreakEvent.java index 89671224f..06bf3fb70 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockBreakEvent.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockBreakEvent.java @@ -77,7 +77,12 @@ public class PrisonMinesBlockBreakEvent private BlockEventType blockEventType; private String triggered; + + // If this is set during the validation process, and the validation fails, then this it will + // force the canceling of the original block event. private boolean cancelOriginalEvent = false; + + private boolean monitor = false; private boolean blockEventsOnly = false; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index 6bd1b5ab7..283a264f8 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -373,6 +373,8 @@ else if ( pmEvent.getMine() != null || pmEvent.getMine() == null && finalizeBreakTheBlocks( pmEvent ); + doBlockEvents( pmEvent ); + } else { @@ -398,6 +400,34 @@ else if ( pmEvent.getMine() != null || pmEvent.getMine() == null && } + /** + *

This processes the block finalizations, which are counting the block breakage, + * and also processes the blockEvents. It's important to process the block events + * after the blocks are broken (set to AIR) to ensure that when the blockEvents are + * ran, then the block would already be set to AIR if it is being broke inline. + *

+ * + * @param pmEvent + */ + private void doBlockEvents( PrisonMinesBlockBreakEvent pmEvent ) + { + + if ( pmEvent.getMine() != null ) { + // Record the block break: + + // apply to ALL blocks including exploded: + applyBlockFinalizations( pmEvent, pmEvent.getTargetBlock() ); + + + for ( MineTargetPrisonBlock teBlock : pmEvent.getTargetExplodedBlocks() ) { + + applyBlockFinalizations( pmEvent, teBlock ); + } + + checkZeroBlockReset( pmEvent.getMine() ); + } + } + private void finalizeBreakTheBlocks( PrisonMinesBlockBreakEvent pmEvent ) { List blocks = finalizeBreakTheBlocksCollectEm( pmEvent ); @@ -419,17 +449,35 @@ private List finalizeBreakTheBlocksCollectEm( PrisonMinesBlockBreak List blocks = new ArrayList<>(); if ( pmEvent.getTargetBlock() != null && pmEvent.getTargetBlock().getMinedBlock() != null ) { - blocks.add( ((SpigotBlock) pmEvent.getTargetBlock().getMinedBlock()) ); - pmEvent.getTargetBlock().setAirBroke( true ); - pmEvent.getTargetBlock().setMinedBlock( null ); + + SpigotBlock minedBlock = ((SpigotBlock) pmEvent.getTargetBlock().getMinedBlock()); + + // Only add the minedBlock to the blocks list if it matches the expected targetBlock name, which + // indicates it has not been replaced by something else, such as the result of a block event. + if ( pmEvent.getTargetBlock().getPrisonBlock().getBlockName().equalsIgnoreCase( minedBlock.getBlockName() )) { + + blocks.add( minedBlock ); + pmEvent.getTargetBlock().setAirBroke( true ); +// pmEvent.getTargetBlock().setMinedBlock( null ); + } + } for ( MineTargetPrisonBlock targetBlock : pmEvent.getTargetExplodedBlocks() ) { if ( targetBlock != null && targetBlock.getMinedBlock() != null ) { - blocks.add( ((SpigotBlock) targetBlock.getMinedBlock()) ); - targetBlock.setAirBroke( true ); - targetBlock.setMinedBlock( null ); + + SpigotBlock minedBlock = ((SpigotBlock) targetBlock.getMinedBlock()); + + // Only add the minedBlock to the blocks list if it matches the expected targetBlock name, which + // indicates it has not been replaced by something else, such as the result of a block event. + if ( targetBlock.getPrisonBlock().getBlockName().equalsIgnoreCase( minedBlock.getBlockName() )) { + + blocks.add( minedBlock ); + targetBlock.setAirBroke( true ); +// targetBlock.setMinedBlock( null ); + } + } } @@ -522,11 +570,18 @@ private boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent, StringBuilder targetBlock.setMined( true ); } + // A mine bomb will be "set" above a valid mine block, so it would generally be air and + // it probably was already mined if it's not on top of the top layer of the mine. if ( !pmEvent.isForceIfAirBlock() ) { + // This block has already been mined and is not a mine bomb, so fail the validation + // and cancel the event since if it's not an air block, it may be another effect that + // is placing a block within the mine, such as a prison util's decay function. debugInfo.append( "VALIDATION_FAILED_BLOCK_ALREADY_MINED " ); results = false; + + pmEvent.setCancelOriginalEvent( true ); } } @@ -905,6 +960,9 @@ else if ( isTEExplosiveEnabled && } finalizeBreakTheBlocks( pmEvent ); + + doBlockEvents( pmEvent ); + } else { @@ -1108,6 +1166,9 @@ else if ( isCEBlockExplodeEnabled && } finalizeBreakTheBlocks( pmEvent ); + + doBlockEvents( pmEvent ); + } else { @@ -1240,6 +1301,9 @@ else if ( isPEExplosiveEnabled && } finalizeBreakTheBlocks( pmEvent ); + + doBlockEvents( pmEvent ); + } else { @@ -1346,6 +1410,9 @@ else if ( isPPrisonExplosiveBlockBreakEnabled && } finalizeBreakTheBlocks( pmEvent ); + + doBlockEvents( pmEvent ); + } else { @@ -1657,20 +1724,20 @@ public void processBlockBreakage( PrisonMinesBlockBreakEvent pmEvent, StringBuil } - if ( pmEvent.getMine() != null ) { - // Record the block break: - - // apply to ALL blocks including exploded: - applyBlockFinalizations( pmEvent, pmEvent.getTargetBlock() ); - - - for ( MineTargetPrisonBlock teBlock : pmEvent.getTargetExplodedBlocks() ) { - - applyBlockFinalizations( pmEvent, teBlock ); - } - - checkZeroBlockReset( pmEvent.getMine() ); - } +// if ( pmEvent.getMine() != null ) { +// // Record the block break: +// +// // apply to ALL blocks including exploded: +// applyBlockFinalizations( pmEvent, pmEvent.getTargetBlock() ); +// +// +// for ( MineTargetPrisonBlock teBlock : pmEvent.getTargetExplodedBlocks() ) { +// +// applyBlockFinalizations( pmEvent, teBlock ); +// } +// +// checkZeroBlockReset( pmEvent.getMine() ); +// } } } @@ -1731,8 +1798,9 @@ private void applyBlockFinalizations( PrisonMinesBlockBreakEvent pmEvent, MineTa SpigotBlock sBlock = (SpigotBlock) targetBlock.getMinedBlock(); + PrisonBlock pBlock = sBlock == null ? null : sBlock.getPrisonBlock(); - pmEvent.getMine().processBlockBreakEventCommands( sBlock.getPrisonBlock(), + pmEvent.getMine().processBlockBreakEventCommands( pBlock, targetBlock, pmEvent.getSpigotPlayer(), pmEvent.getBlockEventType(), pmEvent.getTriggered() ); From 15d9dce224c291f63c46ffaf39b6815f7eb8f3fc Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Mon, 1 Nov 2021 10:00:34 -0400 Subject: [PATCH 104/283] Changes to improve the way the upcoming mine bombs. They are currently non-functional. --- docs/changelog_v3.3.x.md | 6 +- .../mcprison/prison/bombs/MineBombData.java | 15 +++ .../mcprison/prison/spigot/SpigotUtil.java | 12 +- .../spigot/api/ExplosiveBlockBreakEvent.java | 27 ++++ .../api/PrisonMinesBlockBreakEvent.java | 13 ++ .../spigot/block/OnBlockBreakEventCore.java | 15 ++- .../spigot/utils/PrisonBombListener.java | 2 +- .../spigot/utils/PrisonUtilsMineBombs.java | 120 ++++++++++++++---- 8 files changed, 179 insertions(+), 31 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 1dfc3d6aa..064e489b1 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,11 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.3 2021-10-30 +# 3.2.11-alpha.3 2021-11-01 + + +* **Changes to improve the way the upcoming mine bombs.** +They are currently non-functional. * **Adjustments to get block events, such as decays, to work correctly with the new auto feature block event handlers.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java index 71d4557a9..8ffefd269 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java @@ -44,6 +44,9 @@ public class MineBombData { private String explosionShape; + private String toolInHand; + + private String description; @@ -76,6 +79,8 @@ public MineBombData( String name, String itemType, String explosionShape, } } + this.toolInHand = null; + } @@ -84,6 +89,9 @@ public MineBombData clone() { getRadius() ); cloned.setDescription( getDescription() ); + + cloned.setToolInHand( getToolInHand() ); + cloned.setGlowing( isGlowing() ); cloned.setActivated( isActivated() ); @@ -143,6 +151,13 @@ public void setDescription( String description ) { this.description = description; } + public String getToolInHand() { + return toolInHand; + } + public void setToolInHand( String toolInHand ) { + this.toolInHand = toolInHand; + } + public boolean isGlowing() { return glowing; } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotUtil.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotUtil.java index 4f1822830..f98c3868c 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotUtil.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotUtil.java @@ -19,6 +19,7 @@ package tech.mcprison.prison.spigot; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -1011,8 +1012,15 @@ public static ItemStack prisonItemStackToBukkit( public static List getDrops(SpigotBlock block, SpigotItemStack tool) { List ret = new ArrayList<>(); - block.getWrapper().getDrops( tool.getBukkitStack() ) - .forEach(itemStack -> ret.add(SpigotUtil.bukkitItemStackToPrison(itemStack))); + Collection drops = block.getWrapper().getDrops( tool.getBukkitStack() ); + + for ( ItemStack drop : drops ) + { + ret.add( SpigotUtil.bukkitItemStackToPrison(drop) ); + } + +// block.getWrapper().getDrops( tool.getBukkitStack() ) +// .forEach(itemStack -> ret.add(SpigotUtil.bukkitItemStackToPrison(itemStack))); return ret; } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/ExplosiveBlockBreakEvent.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/ExplosiveBlockBreakEvent.java index 66d6a2dcc..6147bebaa 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/ExplosiveBlockBreakEvent.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/ExplosiveBlockBreakEvent.java @@ -10,6 +10,7 @@ import org.bukkit.event.block.BlockBreakEvent; import tech.mcprison.prison.bombs.MineBombData; +import tech.mcprison.prison.internal.ItemStack; /** *

This is an example of an explosive event that should be used for @@ -54,8 +55,20 @@ public class ExplosiveBlockBreakEvent private MineBombData mineBomb; + /** + * ToolInHand is optional. It should only be used if the player did not directly initiate + * the explosion event with a tool. For example, if they set off a mine bomb, and when the + * explosion event is processed, they won't be holding a tool, but an item instead, or even + * AIR. + */ + private ItemStack toolInHand; + private boolean forceIfAirBlock = false; + private boolean calculateDurability = true; + +// private boolean processedSuccessfully = false; + public ExplosiveBlockBreakEvent( Block theBlock, Player player, List explodedBlocks, String triggeredBy ) { @@ -117,6 +130,13 @@ public void setMineBomb( MineBombData mineBomb ) { this.mineBomb = mineBomb; } + public ItemStack getToolInHand() { + return toolInHand; + } + public void setToolInHand( ItemStack toolInHand ) { + this.toolInHand = toolInHand; + } + public boolean isForceIfAirBlock() { return forceIfAirBlock; } @@ -124,6 +144,13 @@ public void setForceIfAirBlock( boolean forceIfAirBlock ) { this.forceIfAirBlock = forceIfAirBlock; } + public boolean isCalculateDurability() { + return calculateDurability; + } + public void setCalculateDurability( boolean calculateDurability ) { + this.calculateDurability = calculateDurability; + } + @Override public HandlerList getHandlers(){ return handlers; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockBreakEvent.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockBreakEvent.java index 06bf3fb70..506c354c0 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockBreakEvent.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockBreakEvent.java @@ -83,6 +83,12 @@ public class PrisonMinesBlockBreakEvent private boolean cancelOriginalEvent = false; + // This will control if durability is calculated, but only if in the auto features configs + // has the AutoFeatures.isCalculateDurabilityEnabled set to true. If it is set to false + // then this setting will do nothing. + private boolean calculateDurability = true; + + private boolean monitor = false; private boolean blockEventsOnly = false; @@ -282,6 +288,13 @@ public void setCancelOriginalEvent( boolean cancelOriginalEvent ) { this.cancelOriginalEvent = cancelOriginalEvent; } + public boolean isCalculateDurability() { + return calculateDurability; + } + public void setCalculateDurability( boolean calculateDurability ) { + this.calculateDurability = calculateDurability; + } + public boolean isMonitor() { return monitor; } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index 283a264f8..62beabe3b 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -1369,6 +1369,15 @@ protected void genericExplosiveEvent( ExplosiveBlockBreakEvent e, boolean monito pmEvent.setUnprocessedRawBlocks( e.getExplodedBlocks() ); pmEvent.setForceIfAirBlock( e.isForceIfAirBlock() ); + // Warning: toolInHand really needs to be defined in the event if the source is a + // Mine Bomb, otherwise auto features will detect the player is holding + // a mine bomb which is not a pickaxe so the drops will be ZERO. If they + // used their last mine bomb, then auto features will detect only AIR + // in their hand. + if ( e.getToolInHand() != null ) { + pmEvent.setItemInHand( (SpigotItemStack) e.getToolInHand() ); + } + if ( !validateEvent( pmEvent, debugInfo ) ) { // The event has not passed validation. All logging and Errors have been recorded @@ -1702,7 +1711,8 @@ public void processBlockBreakage( PrisonMinesBlockBreakEvent pmEvent, StringBuil // calculate durability impact: Include item durability resistance. - if ( isBoolean( AutoFeatures.isCalculateDurabilityEnabled ) ) { + if ( isBoolean( AutoFeatures.isCalculateDurabilityEnabled ) && + pmEvent.isCalculateDurability() ) { // value of 0 = normal durability. Value 100 = never calculate durability. int durabilityResistance = 0; @@ -2208,7 +2218,8 @@ else if ( durabilityResistance > 0 ) { String message = String.format( "(calcDurability: %s: maxDurability= %d " + "durability: %d damage: %d durResistance: %d toolDurabilityLvl: %d %s) ", - itemInHand.getName(), maxDurability, durability, totalDamage, + (itemInHand == null ? "(empty hand)" : itemInHand.getName() ), + maxDurability, durability, totalDamage, durabilityResistance, durabilityLevel, (toolBreak ? "[Broke]" : "") ); debugInfo.append( message ); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java index 7327c0e6f..5f0e2e435 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java @@ -52,7 +52,7 @@ public void onInteract( PlayerInteractEvent event ) { // The item was a bomb and it was activated. // Cancel the event so the item will not be placed or processed farther. - Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent 03 Bomb activated " ); + Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent 03 Bomb detected - May not have been set. " ); event.setCancelled( true ); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java index 03218096d..dca81f10f 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java @@ -14,14 +14,14 @@ import com.cryptomorin.xseries.XMaterial; -import tech.mcprison.prison.autofeatures.AutoFeaturesWrapper; import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; +import tech.mcprison.prison.autofeatures.AutoFeaturesWrapper; import tech.mcprison.prison.bombs.MineBombData; import tech.mcprison.prison.bombs.MineBombs; import tech.mcprison.prison.commands.Arg; import tech.mcprison.prison.commands.Command; import tech.mcprison.prison.internal.CommandSender; -import tech.mcprison.prison.internal.block.BlockFace; +import tech.mcprison.prison.internal.ItemStack; import tech.mcprison.prison.output.LogLevel; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.SpigotPrison; @@ -39,7 +39,7 @@ public class PrisonUtilsMineBombs { public static final String MINE_BOMBS_LORE_1 = "&4Prison Mine Bomb:"; public static final String MINE_BOMBS_LORE_2_PREFIX = " &7"; - public static final int MINE_BOMBS_COOLDOWN_TICKS = 15 * 20; // 15 seconds + public static final int MINE_BOMBS_COOLDOWN_TICKS = 5 * 20; // 5 seconds // 15 seconds private boolean enableMineBombs = false; @@ -146,6 +146,8 @@ public void utilsMineBombs( CommandSender sender, targetBlock.getWrapper(), player.getWrapper(), blocks ); explodeEvent.setTriggeredBy( "minebombs" ); + explodeEvent.setForceIfAirBlock( true ); + Bukkit.getServer().getPluginManager().callEvent( explodeEvent ); } @@ -454,13 +456,22 @@ public static boolean setBombInHand( Player player, SpigotBlock sBlock ) { AutoFeatures.ProcessPrisons_ExplosiveBlockBreakEventsPriority ); if ( bomb != null && "DISABLED".equalsIgnoreCase( prisonExplosiveHandlerPriority ) ) { + isABomb = true; + Output.get().logWarn( "A Prison Mine Bomb was attempted to be used, but the " + "handling of its explosion is DISABLED. Edit the 'autoFeaturesConfig.yml' " + "file and set 'ProcessPrisons_ExplosiveBlockBreakEventsPriority: NORMAL'." ); } else if ( bomb != null ) { - + isABomb = true; + + // if the toolInHand has not been set, use a diamond pickaxe: + if ( bomb.getToolInHand() == null ) { + XMaterial xMat = XMaterial.DIAMOND_PICKAXE; + bomb.setToolInHand( xMat.name() ); + } + SpigotPlayer sPlayer = new SpigotPlayer( player ); String playerUUID = player.getUniqueId().toString(); @@ -468,15 +479,6 @@ else if ( bomb != null ) { if ( cooldownTicks == 0 ) { - isABomb = true; - - // Setting activated to true indicates the bomb is live and it has - // been removed from the player's inventory: - bomb.setActivated( true ); - itemInHand.setAmount( itemInHand.getAmount() - 1 ); - - // Remove from inventory: - SpigotCompatibility.getInstance().setItemInMainHand( player, itemInHand.getBukkitStack() ); // Set cooldown: PrisonUtilsMineBombs.addPlayerCooldown( playerUUID ); @@ -485,25 +487,61 @@ else if ( bomb != null ) { if ( bombs != null ) { - Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent 05 " ); + // Setting activated to true indicates the bomb is live and it has + // been removed from the player's inventory: + bomb.setActivated( true ); + + // Remove from inventory: + itemInHand.setAmount( itemInHand.getAmount() - 1 ); + + // Not sure if the following is needed? + SpigotCompatibility.getInstance().setItemInMainHand( player, itemInHand.getBukkitStack() ); + + + //Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent 05 " ); // SpigotBlock sBlock = new SpigotBlock( event.getClickedBlock() ); - Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent dropping block " ); + //Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent dropping block " ); + + SpigotBlock bombBlock = sBlock != null ? sBlock : (SpigotBlock) player.getLocation().getBlock(); + + - int throwSpeed = 2; + // For mine bombs, take the block below where the bomb's item was dropped. The floating + // item is not the block that needs to be the target block for the explosion. Also, the block + // if it is on top of the mine, would be identified as being outside of the mine. + int count = 0; + while ( (count++ == 0 || bombBlock.isEmpty()) && bombBlock.getLocation().getBlockY() > 1 ) { + Location bbLocation = bombBlock.getLocation(); + bbLocation.setY( bbLocation.getBlockY() - 1 ); + + bombBlock = (SpigotBlock) bbLocation.getBlockAt(); + +// Output.get().logInfo( +// "#### PrisonUtilsMineBombs: bomb y loc: " + bombBlock.getWrapper().getLocation().getBlockY() + +// " " + bombBlock.getLocation().getBlockY() + " count= " + count ); + } + +// Output.get().logInfo( +// "#### PrisonUtilsMineBombs: bomb loc: " + bombBlock.getLocation().toWorldCoordinates() ); + + //int throwSpeed = 2; // This places the item so it will float: - final Item dropped = player.getWorld().dropItem(player.getLocation(), bombs.getBukkitStack() ); + final Item dropped = player.getWorld().dropItem( + bombBlock.getWrapper().getLocation(), bombs.getBukkitStack() ); + dropped.setPickupDelay( Integer.MAX_VALUE ); dropped.setCustomName( bomb.getName() ); - dropped.setVelocity(player.getLocation().getDirection().multiply( throwSpeed ).normalize() ); + //dropped.setVelocity(player.getLocation().getDirection().multiply( throwSpeed ).normalize() ); int delayInTicks = 5 * 20; // 5 secs // Get the block that is y - 1 lower than the original block: - SpigotBlock bombBlock = (SpigotBlock) sBlock.getRelative( BlockFace.DOWN ); +// SpigotBlock bombBlock = (SpigotBlock) sBlock.getRelative( BlockFace.DOWN ); + // Submit the bomb's task to go off: PrisonUtilsMineBombs.setoffBombDelayed( sPlayer, bomb, dropped, bombBlock, delayInTicks ); @@ -528,7 +566,7 @@ else if ( bomb != null ) { else { - float cooldownSeconds = cooldownTicks / 2.0f; + float cooldownSeconds = cooldownTicks / 20.0f; DecimalFormat dFmt = new DecimalFormat( "0.0" ); String message = @@ -602,7 +640,7 @@ public static int checkPlayerCooldown( String playerUUID ) { } public static boolean setoffBombDelayed( SpigotPlayer sPlayer, MineBombData bomb, Item droppedBomb, - SpigotBlock sBlock, int delayTicks ) { + SpigotBlock targetBlock, int delayTicks ) { boolean results = false; new BukkitRunnable() { @@ -613,20 +651,21 @@ public void run() { // Remove the item that the player threw: droppedBomb.remove(); - Location location = sBlock.getLocation(); + Location location = targetBlock.getLocation(); if ( location == null ) { location = sPlayer.getLocation(); } - SpigotWorld world = (SpigotWorld) location.getWorld(); MineBombs mBombs = MineBombs.getInstance(); // Calculate all the locations that are included in the explosion: List blockLocations = mBombs.calculateSphere( location, bomb.getRadius(), false ); + + SpigotWorld world = (SpigotWorld) location.getWorld(); // Convert to spigot blocks: List blocks = new ArrayList<>(); @@ -639,7 +678,7 @@ public void run() { } - SpigotBlock targetBlock = (SpigotBlock) world.getBlockAt( location ); +// SpigotBlock targetBlock = (SpigotBlock) world.getBlockAt( location ); ExplosiveBlockBreakEvent explodeEvent = new ExplosiveBlockBreakEvent( @@ -647,6 +686,26 @@ public void run() { explodeEvent.setTriggeredBy( bomb.getName() ); explodeEvent.setMineBomb( bomb ); + // Set the toolInHand that needs to be used for the bomb: + // Default to a diamond pickaxe if not specified. + // The bomb must define a tool, otherwise auto features will + // use the mine bombs that the player is holding, or if it was their + // last one, it would be just AIR: + String toolInHandName = bomb.getToolInHand(); + if ( toolInHandName == null || toolInHandName.trim().isEmpty() ) { + XMaterial xMat = XMaterial.DIAMOND_PICKAXE; + toolInHandName = xMat.name(); + } + XMaterial xMatTool = XMaterial.matchXMaterial( toolInHandName ).orElseGet( null ); + ItemStack toolInHand = new SpigotItemStack( xMatTool == null ? + XMaterial.DIAMOND_PICKAXE.parseItem() : + xMatTool.parseItem() ); + explodeEvent.setToolInHand( toolInHand ); + + + // Mine bombs should not calculate durability: + explodeEvent.setCalculateDurability( false ); + // Normally the explosion will ONLY work if the center target block was non-AIR. // This setting allows the explosion to be processed even if it is air. @@ -654,8 +713,19 @@ public void run() { Bukkit.getServer().getPluginManager().callEvent( explodeEvent ); - if ( !explodeEvent.isCancelled() ) { + if ( explodeEvent.isCancelled() ) { + + if ( Output.get().isDebug() ) { + Output.get().logDebug( "Mine Bomb's ExplosiveBlockBreakEvent has been canceled. " + + "It may have been processed successfully." ); + } + } + else { // If it wasn't canceled, then it may not have been handled + + if ( Output.get().isDebug() ) { + Output.get().logDebug( "Mine Bomb's ExplosiveBlockBreakEvent has NOT been canceled." ); + } } From 1ab04834c7b1788ffc88e31bf4e990a5a228bad5 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Mon, 1 Nov 2021 13:25:23 -0400 Subject: [PATCH 105/283] Released v3.2.11-alpha.4 --- docs/changelog_v3.3.x.md | 8 +++++++- gradle.properties | 2 +- .../tech/mcprison/prison/tasks/PrisonCommandTask.java | 2 ++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 064e489b1..34f4a07f3 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,13 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.3 2021-11-01 +# 3.2.11-alpha.4 2021-11-01 + + + + +**3.2.11-alpha.4 2021-11-01** + Released alpha.4. * **Changes to improve the way the upcoming mine bombs.** diff --git a/gradle.properties b/gradle.properties index d31a44bd3..58bae8e7e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ ## # This is actually the "correct" place to define the version for the project. ## # Used within build.gradle with ${project.version}. ## # Can be overridden on the command line: gradle -Pversion=3.2.1-alpha.3 -version=3.2.11-alpha.3 +version=3.2.11-alpha.4 #version=3.2.8.2 #version=3.3.0-alpha.6 diff --git a/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonCommandTask.java b/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonCommandTask.java index 4644767d5..6ee599555 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonCommandTask.java +++ b/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonCommandTask.java @@ -66,6 +66,8 @@ public enum CustomPlaceholders { msg(CommandEnvironment.all_commands), broadcast(CommandEnvironment.all_commands), + title(CommandEnvironment.all_commands), + actionBar(CommandEnvironment.all_commands), inline(CommandEnvironment.all_commands), inlinePlayer(CommandEnvironment.all_commands), From 27f80aab7a98008461e0ec59b096a3c34ca3235a Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Mon, 1 Nov 2021 13:45:55 -0400 Subject: [PATCH 106/283] The use of a command placeholders for `{actionBar}` and `{title}` were added to the placeholder enumeration so they are included in the placeholders listings. The support for these two commands were added a while ago, but because they were not added to the enum, they were not being listed in the help. Note these changes were accidentally submitted with the alpha.4 release, of which they are not actually included. --- docs/changelog_v3.3.x.md | 2 ++ .../java/tech/mcprison/prison/tasks/PrisonCommandTask.java | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 34f4a07f3..02f65e32b 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,8 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.4 2021-11-01 +* **The use of a command placeholders for `{actionBar}` and `{title}` were added to the placeholder enumeration so they are included in the placeholders listings.** +The support for these two commands were added a while ago, but because they were not added to the enum, they were not being listed in the help. **3.2.11-alpha.4 2021-11-01** diff --git a/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonCommandTask.java b/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonCommandTask.java index 6ee599555..ab454d52c 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonCommandTask.java +++ b/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonCommandTask.java @@ -66,8 +66,8 @@ public enum CustomPlaceholders { msg(CommandEnvironment.all_commands), broadcast(CommandEnvironment.all_commands), - title(CommandEnvironment.all_commands), - actionBar(CommandEnvironment.all_commands), + title(CommandEnvironment.all_commands ), + actionBar(CommandEnvironment.all_commands ), inline(CommandEnvironment.all_commands), inlinePlayer(CommandEnvironment.all_commands), From 6f306a6362f00bacf0fc3499403a9ea8d2af80d6 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sat, 6 Nov 2021 22:35:26 -0400 Subject: [PATCH 107/283] Fixes a concurrent modification exception when the PlayerCacheCheckTimersTask is running. This happens rarely when a player is logging off while "trying" to process their entries; they have been removed. So when this happens, the process retries to start over a total of 2 more times and it skips processing players that have already been processed. Any update that was skipped would be covered in the next pass with no real loss. --- docs/changelog_v3.3.x.md | 7 ++- .../cache/PlayerCacheCheckTimersTask.java | 59 ++++++++++++++++--- 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 02f65e32b..6e35c346b 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,12 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.4 2021-11-01 +# 3.2.11-alpha.4 2021-11-06 + + +* **Fixes a concurrent modification exception when the PlayerCacheCheckTimersTask is running.** +This happens rarely when a player is logging off while "trying" to process their entries; they have been removed. +So when this happens, the process retries to start over a total of 2 more times and it skips processing players that have already been processed. Any update that was skipped would be covered in the next pass with no real loss. * **The use of a command placeholders for `{actionBar}` and `{title}` were added to the placeholder enumeration so they are included in the placeholders listings.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheCheckTimersTask.java b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheCheckTimersTask.java index c1efb2f4a..aa23b4667 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheCheckTimersTask.java +++ b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheCheckTimersTask.java @@ -1,5 +1,10 @@ package tech.mcprison.prison.cache; +import java.util.ArrayList; +import java.util.ConcurrentModificationException; +import java.util.HashSet; +import java.util.List; + /** *

This periodically ran task will go through all cached players and update * their status with the timers and earnings. This is a light weight task @@ -34,27 +39,67 @@ public class PlayerCacheCheckTimersTask extends PlayerCacheRunnable { + private HashSet processedKeys; + private int attempts = 0; + + public PlayerCacheCheckTimersTask() { + super(); + + this.processedKeys = new HashSet<>(); + } + @Override public void run() { + // Everytime this runs, clear the processed keys set: + processedKeys.clear(); + attempts = 0; + + processCache(); + + } + private void processCache() { PlayerCache pCache = PlayerCache.getInstance(); if ( pCache.getPlayers() != null && pCache.getPlayers().keySet().size() > 0 ) { - for ( String key : pCache.getPlayers().keySet() ) + try { - PlayerCachePlayerData playerData = pCache.getPlayers().get( key ); + List keys = new ArrayList<>( pCache.getPlayers().keySet() ); - if ( playerData != null ) { + for ( String key : keys ) + { + if ( processedKeys.contains( key ) ) { + // Already processed this key so skip it: + break; + } + processedKeys.add( key ); + + + PlayerCachePlayerData playerData = pCache.getPlayers().get( key ); - playerData.checkTimers(); + if ( playerData != null ) { + + playerData.checkTimers(); + + // By adding a zero earnings, this will force the earnings "cache" to + // progress, even if the player stopped mining. + playerData.addEarnings( 0 ); + } - // By adding a zero earnings, this will force the earnings "cache" to - // progress, even if the player stopped mining. - playerData.addEarnings( 0 ); } + } + catch ( ConcurrentModificationException e ) + { + // We can ignore this overall. It is a very rare occurrence which happens when + // a player is added or removed from an external process. Since this is a maintenance + // thread, it takes on a secondary priority. + // Try to process the list three times then give up: + if ( attempts++ < 3 ) { + processCache(); + } } } From e588a4e56cbf465d216d8a7b3513f4e27c682101 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Mon, 15 Nov 2021 18:36:58 -0500 Subject: [PATCH 108/283] Bug fix. If a null message is sent to this function, it would cause a NPE. This now prevents a few failures from causing potential problems. --- docs/changelog_v3.3.x.md | 6 +++++- .../src/main/java/tech/mcprison/prison/output/Output.java | 8 +++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 6e35c346b..32ba36e82 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,11 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.4 2021-11-06 +# 3.2.11-alpha.4 2021-11-15 + + +* **Bug fix. If a null message is sent to this function, it would cause a NPE.** +This now prevents a few failures from causing potential problems. * **Fixes a concurrent modification exception when the PlayerCacheCheckTimersTask is running.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/output/Output.java b/prison-core/src/main/java/tech/mcprison/prison/output/Output.java index 179a083ec..7dff57afb 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/output/Output.java +++ b/prison-core/src/main/java/tech/mcprison/prison/output/Output.java @@ -377,7 +377,13 @@ public void setActiveDebugTargets( Set activeDebugTargets ) { * Send a message to a {@link CommandSender} */ public void sendMessage(CommandSender sender, String message, LogLevel level, Object... args) { - sender.sendMessage(getLogPrefix(level) + String.format(message, args)); + + if ( sender != null && message != null && message.length() > 0 ) { + if ( level == null ) { + level = LogLevel.PLAIN; + } + sender.sendMessage(getLogPrefix(level) + String.format(message, args)); + } } public void send(CommandSender sender, String message, Object... args) { From cc17d0f07219922070fde508efdfe3a8311cbcb5 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Mon, 15 Nov 2021 18:44:28 -0500 Subject: [PATCH 109/283] Bug fix: The command "/prison support submit ranks" was passing a null sender, which is valid when generated by this support tool. The fixes now works well, and treats the null basically the same as an OP'd player, or the command being ran from the console. --- docs/changelog_v3.3.x.md | 4 ++++ .../mcprison/prison/ranks/commands/RanksCommands.java | 8 ++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 32ba36e82..0cd7348b2 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.4 2021-11-15 +* **Bug fix: The command "/prison support submit ranks" was passing a null sender, which is valid when generated by this support tool.** +The fixes now works well, and treats the null basically the same as an OP'd player, or the command being ran from the console. + + * **Bug fix. If a null message is sent to this function, it would cause a NPE.** This now prevents a few failures from causing potential problems. diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java index 05cf02d20..173d30d08 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java @@ -1119,8 +1119,8 @@ private ChatDisplay rankInfoDetails( CommandSender sender, Rank rank, String opt { ChatDisplay display = new ChatDisplay( ranksInfoHeaderMsg( rank.getTag() )); - boolean isOp = sender.isOp(); - boolean isConsole = !sender.isPlayer(); + boolean isOp = sender != null && sender.isOp(); + boolean isConsole = sender == null || !sender.isPlayer(); display.addText( ranksInfoNameMsg( rank.getName() )); display.addText( ranksInfoTagMsg( rank.getTag() )); @@ -1191,7 +1191,7 @@ private ChatDisplay rankInfoDetails( CommandSender sender, Rank rank, String opt int numberOfPlayersOnRank = rank.getPlayers().size(); display.addText( ranksInfoPlayersWithRankMsg( numberOfPlayersOnRank )); - if ( isOp || isConsole || sender == null || sender.hasPermission("ranks.admin")) { + if ( isOp || isConsole || sender.hasPermission("ranks.admin")) { // This is admin-exclusive content // display.addText("&8[Admin Only]"); @@ -1203,7 +1203,7 @@ private ChatDisplay rankInfoDetails( CommandSender sender, Rank rank, String opt // display.addComponent(new FancyMessageComponent(del)); } - if ( isOp && options != null && "all".equalsIgnoreCase( options )) { + if ( (isOp || isConsole) && options != null && "all".equalsIgnoreCase( options )) { if ( rank.getLadder() != null ) { From d3497c9a415ddb0fee5716d574cada2663849558 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Tue, 16 Nov 2021 00:13:00 -0500 Subject: [PATCH 110/283] Fixed an unexpected "bug" with the JumboText font for the letter Q. One section was setup to use "\Q" which is an escape character for a regex block quote. This was causing problems since it was forcing large sections of text to be ignored when translating minecraft color codes. By changing it to "\q", a lower case Q, this eliminated the translation from making the mistake. --- docs/changelog_v3.3.x.md | 4 ++++ .../main/java/tech/mcprison/prison/util/JumboTextFont.java | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 0cd7348b2..d7a0f2c9d 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.4 2021-11-15 +* **Fixed an unexpected "bug" with the JumboText font for the letter Q.** +One section was setup to use "\Q" which is an escape character for a regex block quote. This was causing problems since it was forcing large sections of text to be ignored when translating minecraft color codes. By changing it to "\q", a lower case Q, this eliminated the translation from making the mistake. + + * **Bug fix: The command "/prison support submit ranks" was passing a null sender, which is valid when generated by this support tool.** The fixes now works well, and treats the null basically the same as an OP'd player, or the command being ran from the console. diff --git a/prison-core/src/main/java/tech/mcprison/prison/util/JumboTextFont.java b/prison-core/src/main/java/tech/mcprison/prison/util/JumboTextFont.java index de6346734..976b1a99b 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/util/JumboTextFont.java +++ b/prison-core/src/main/java/tech/mcprison/prison/util/JumboTextFont.java @@ -22,7 +22,10 @@ public enum JumboTextFont { N("N", 5, "N N", "NN N", "N N N", "N NN", "N N" ), O("O", 5, " OOO ", "O O", "O O", "O O", " OOO " ), P("P", 5, "PPPP ", "P P", "PPPP ", "P ", "P "), - Q("Q", 5, " QQQ ", "Q Q", "Q \\ Q", "Q \\Q", " QQ \\" ), + + // Warning: Note that \Q is an escape code for regex block quote. + // So use lowercase q so it does not match. + Q("Q", 5, " QQQ ", "Q Q", "Q \\ Q", "Q \\q", " QQ \\" ), R("R", 5, "RRRR ", "R R", "RRRR ", "R R ", "R R" ), S("S", 5, " SSS ", "S ", " SSS ", " S", " SSS " ), T("T", 5, "TTTTT", " T ", " T ", " T ", " T " ), From 826a839c12302890149642f7e3775e5fa289063c Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Tue, 16 Nov 2021 00:45:10 -0500 Subject: [PATCH 111/283] Fixed a bug with how the regex handles block quotes. Not only was it not working correctly for multiple block quotes, but it was incorrectly handling the tail end of the processed text and was basically doubling the text. It now works correctly, even with multiple block quotes. --- docs/changelog_v3.3.x.md | 4 +++ .../java/tech/mcprison/prison/util/Text.java | 9 ++++--- .../tech/mcprison/prison/util/TextTest.java | 25 +++++++++++++++++++ 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index d7a0f2c9d..1d1cffdf5 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.4 2021-11-15 +* **Fixed a bug with how the regex handles block quotes.** +Not only was it not working correctly for multiple block quotes, but it was incorrectly handling the tail end of the processed text and was basically doubling the text. It now works correctly, even with multiple block quotes. + + * **Fixed an unexpected "bug" with the JumboText font for the letter Q.** One section was setup to use "\Q" which is an escape character for a regex block quote. This was causing problems since it was forcing large sections of text to be ignored when translating minecraft color codes. By changing it to "\q", a lower case Q, this eliminated the translation from making the mistake. diff --git a/prison-core/src/main/java/tech/mcprison/prison/util/Text.java b/prison-core/src/main/java/tech/mcprison/prison/util/Text.java index f0ec6f69c..0795db551 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/util/Text.java +++ b/prison-core/src/main/java/tech/mcprison/prison/util/Text.java @@ -349,7 +349,8 @@ public static String translateHexColorCodes( String text, char targetColorCode ) } else { while ( idxStart >= 0 ) { - sb.append( translateHexColorCodesCore( text.substring( idxEnd + 1, idxStart ), targetColorCode) ); + sb.append( translateHexColorCodesCore( + text.substring( idxEnd + (idxEnd == -1 ? 1 : 0), idxStart ), targetColorCode) ); idxEnd = text.indexOf( "\\E", idxStart ); @@ -358,13 +359,13 @@ public static String translateHexColorCodes( String text, char targetColorCode ) idxStart = -1; } else { - sb.append( text.substring( idxStart, idxEnd + 1 ) ); + sb.append( text.substring( idxStart, idxEnd ) ); idxStart = text.indexOf( "\\Q", idxEnd ); } } - if ( idxEnd < text.length() ) { - sb.append( text.substring( idxEnd + 1 ) ); + if ( idxStart == -1 && idxEnd >= 0 && (idxEnd) < text.length() ) { + sb.append( text.substring( idxEnd ) ); } } } diff --git a/prison-core/src/test/java/tech/mcprison/prison/util/TextTest.java b/prison-core/src/test/java/tech/mcprison/prison/util/TextTest.java index 8dcea75b5..9c038a37d 100644 --- a/prison-core/src/test/java/tech/mcprison/prison/util/TextTest.java +++ b/prison-core/src/test/java/tech/mcprison/prison/util/TextTest.java @@ -69,6 +69,11 @@ public void testTranslateColorCodesQuotedText() { assertEquals("This x7is xra &1t&2e&3s&4t", replaceColorCodeWithx( translateColorCodes("This &7is &Ra \\Q&1t&2e&3s&4t\\E", '&'))); + // Test with 2 quotes: + String results1 = replaceColorCodeWithx( + translateColorCodes("This &7is &Ra \\Q&1t&2e&3s&4t\\E &7and \\Q&1m&2o&3r&4e\\E", '&') ); + assertEquals("This x7is xra &1t&2e&3s&4t x7and &1m&2o&3r&4e", results1 ); + } /** @@ -131,4 +136,24 @@ public void testHexColors() { translateColorCodes("This &7is #a3b4c5 &Ra test \\Q#123456 test\\E test2 \\Q#778899 test\\E", '&'), '^' )); } + + + @Test + public void testBadRegexBlockQuote() { + + + // Test with quotes just to show it works: + String results1 = replaceColorCodeWithx( + translateColorCodes("This &7is \\Q&1t&2e\\E", '&')); + assertEquals("This x7is &1t&2e", results1 ); + assertEquals( 16, results1.length() ); + + // Test with no ending quotes: + String results2= replaceColorCodeWithx( + translateColorCodes("A&7b \\Q&1c&2d", '&')); + assertEquals("Ax7b &1c&2d", results2); + assertEquals( 11, results2.length() ); + + + } } From 772eeb44a70627d6843c38be28f295081eadcd47 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Wed, 17 Nov 2021 02:33:46 -0500 Subject: [PATCH 112/283] Prison Bombs: enabled the right clicking of AIR to set the bombs. If clicking air blocks, then the block tied to the event will be null (at least for spigot 1.13.x) in that case, will use the block location of the player, and then adding the player's vector to it times three. --- docs/changelog_v3.3.x.md | 7 +++- .../tech/mcprison/prison/util/Location.java | 38 ++++++++++++++++++ .../prison/spigot/block/SpigotBlock.java | 2 +- .../spigot/utils/PrisonBombListener.java | 22 ++++++++++- .../spigot/utils/PrisonUtilsMineBombs.java | 39 ++++++++++++++++--- 5 files changed, 100 insertions(+), 8 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 1d1cffdf5..cd817bd17 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,12 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.4 2021-11-15 +# 3.2.11-alpha.4 2021-11-17 + + +* **Prison Bombs: enabled the right clicking of AIR to set the bombs.** +If clicking air blocks, then the block tied to the event will be null (at least for spigot 1.13.x) in that case, will use the block location of the player, and then adding the player's vector to it times three. + * **Fixed a bug with how the regex handles block quotes.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/util/Location.java b/prison-core/src/main/java/tech/mcprison/prison/util/Location.java index e098c825e..0db64010d 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/util/Location.java +++ b/prison-core/src/main/java/tech/mcprison/prison/util/Location.java @@ -223,5 +223,43 @@ public Location add( Vector direction ) return results; } + + /** + *

This function will clone the current location object and then add/subtract the amount of + * x, y, and/or z to that location. To keep the same value for one or more of these coordinates + * then use a value of zero. + *

+ * + * @param x + * @param y + * @param z + * @return + */ + public Location getLocationAtDelta( int x, int y, int z ) + { + Location results = new Location( this ); + + results.setX( results.getX() + x ); + results.setY( results.getY() + y ); + results.setZ( results.getZ() + z ); + + return results; + } + + /** + *

Returns the block that is at the location of this object, offset by x, y, and/or z deltas. + *

+ * + * @param x + * @param y + * @param z + * @return + */ + public Block getBlockAtDelta( int x, int y, int z ) + { + Location results = getLocationAtDelta( x, y, z ); + + return getWorld().getBlockAt( results ); + } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java index 7beef49c5..92b898e59 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java @@ -66,7 +66,7 @@ public String toString() { StringBuilder sb = new StringBuilder(); sb.append( getPrisonBlock().getBlockName() ).append( " " ) - .append( getLocation().toCoordinates() ); + .append( getLocation().toWorldCoordinates() ); return sb.toString(); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java index 5f0e2e435..ae6a06cad 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java @@ -13,6 +13,8 @@ import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.block.SpigotBlock; +import tech.mcprison.prison.spigot.game.SpigotPlayer; +import tech.mcprison.prison.util.Location; /** *

This listener class handles the player's interaction with using a bomb. @@ -44,7 +46,25 @@ public void onInteract( PlayerInteractEvent event ) { // ItemStack in the player's hand by 1: Player player = event.getPlayer(); - SpigotBlock sBlock = new SpigotBlock( event.getClickedBlock() ); + + SpigotBlock sBlock = null; + + + // If clicking AIR, then event.getClickedBlock() will be null... + // so if null, then use the player's location for placing the bomb. + if ( event.getClickedBlock() == null ) { + SpigotPlayer sPlayer = new SpigotPlayer( event.getPlayer() ); + Location loc = sPlayer.getLocation(); + + // Get the block 3 away from the player, in the direction (vector) in which + // the player is looking. + sBlock = (SpigotBlock) loc.add( loc.getDirection().multiply( 3 ) ) .getBlockAt(); + } + else { + sBlock = new SpigotBlock( event.getClickedBlock() ); + } + + // Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent 02 " ); if ( PrisonUtilsMineBombs.setBombInHand( player, sBlock ) ) { diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java index dca81f10f..25ee0ec0c 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java @@ -22,6 +22,7 @@ import tech.mcprison.prison.commands.Command; import tech.mcprison.prison.internal.CommandSender; import tech.mcprison.prison.internal.ItemStack; +import tech.mcprison.prison.internal.block.Block; import tech.mcprison.prison.output.LogLevel; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.SpigotPrison; @@ -487,6 +488,27 @@ else if ( bomb != null ) { if ( bombs != null ) { + SpigotBlock bombBlock = sBlock != null ? sBlock : (SpigotBlock) player.getLocation().getBlock(); + +// // If the clicked on block is empty, then the player probably clicked on air. +// // Check the next lower block (y - 1) until a valid block is found, or until y < 1 +// while ( sBlock.isEmpty() && sBlock.getLocation().getBlockY() > 0 ) { +// +// Block tempBlock = sBlock.getLocation().getBlockAtDelta( 0, -1, 0 ); +// if ( tempBlock != null && tempBlock instanceof SpigotBlock ) { +// sBlock = (SpigotBlock) tempBlock; +// } +// +// // if not empty, take one block deeper below the surface: +//// if ( !sBlock.isEmpty() && sBlock.getLocation().getBlockY() > 0 ) { +//// +//// tempBlock = sBlock.getLocation().getBlockAtDelta( 0, -1, 0 ); +//// if ( tempBlock != null && tempBlock instanceof SpigotBlock ) { +//// sBlock = (SpigotBlock) tempBlock; +//// } +//// } +// } + // Setting activated to true indicates the bomb is live and it has // been removed from the player's inventory: bomb.setActivated( true ); @@ -504,7 +526,6 @@ else if ( bomb != null ) { //Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent dropping block " ); - SpigotBlock bombBlock = sBlock != null ? sBlock : (SpigotBlock) player.getLocation().getBlock(); @@ -512,11 +533,19 @@ else if ( bomb != null ) { // item is not the block that needs to be the target block for the explosion. Also, the block // if it is on top of the mine, would be identified as being outside of the mine. int count = 0; - while ( (count++ == 0 || bombBlock.isEmpty()) && bombBlock.getLocation().getBlockY() > 1 ) { - Location bbLocation = bombBlock.getLocation(); - bbLocation.setY( bbLocation.getBlockY() - 1 ); + boolean isAir = bombBlock.isEmpty(); + while ( (count++ <= ( isAir ? 1 : 0 ) || bombBlock.isEmpty()) && bombBlock.getLocation().getBlockY() > 1 ) { + + Block tempBlock = bombBlock.getLocation().getBlockAtDelta( 0, -1, 0 ); + if ( tempBlock != null && tempBlock instanceof SpigotBlock ) { + bombBlock = (SpigotBlock) tempBlock; + } + - bombBlock = (SpigotBlock) bbLocation.getBlockAt(); +// Location bbLocation = bombBlock.getLocation(); +// bbLocation.setY( bbLocation.getBlockY() - 1 ); +// +// bombBlock = (SpigotBlock) bbLocation.getBlockAt(); // Output.get().logInfo( // "#### PrisonUtilsMineBombs: bomb y loc: " + bombBlock.getWrapper().getLocation().getBlockY() + From f196dfaf07e56cee47a90d732294258cbc5e2a32 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Thu, 18 Nov 2021 01:07:08 -0500 Subject: [PATCH 113/283] Mine Bombs: More features and fixes. Added support for radiusInner (for hollow sphere explosion shapes), removalChance (chance for block inclusion), glowing, autoSell, tool material type, tool fortune level. Added a new shape which is "cube" and hooked up sphereHollow. Hooked up cube, sphereHollow, removalChance, glowing, the specified tool in hand with the custom fortune level. Did not hook up the forced autosell yet. Fixed some issues to get things to work a little better too. --- docs/changelog_v3.3.x.md | 8 +- .../mcprison/prison/bombs/MineBombData.java | 116 ++++++++- .../tech/mcprison/prison/bombs/MineBombs.java | 169 +++++++++++-- .../spigot/utils/PrisonUtilsMineBombs.java | 236 +++++++++++++++--- 4 files changed, 459 insertions(+), 70 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index cd817bd17..b63d92bf1 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,13 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.4 2021-11-17 +# 3.2.11-alpha.4 2021-11-18 + + +* **Mine Bombs: More features and fixes.** +Added support for radiusInner (for hollow sphere explosion shapes), removalChance (chance for block inclusion), glowing, autoSell, tool material type, tool fortune level. + Added a new shape which is "cube" and hooked up sphereHollow. Hooked up cube, sphereHollow, removalChance, glowing, the specified tool in hand with the custom fortune level. Did not hook up the forced autosell yet. +Fixed some issues to get things to work a little better too. * **Prison Bombs: enabled the right clicking of AIR to set the bombs.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java index 8ffefd269..8adacc2df 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java @@ -27,31 +27,78 @@ public class MineBombData { private List lore; /** - *

The radius identifies how large the blast should be. + *

The radius identifies how large the blast should be as + * expressed in a radius. Generally this applies to a sphere or + * a circle or disk, but can also apply to other shapes such as + * cubes. *

+ * + *

The radius is always based upon a center block, plus the radius. + * Therefore a radius of 1 will result in a sphere with a diameter of + * three (1 block for the center, and then 1 additional block on each + * side). The calculated diameter can never be even, and the actual + * blast size will appear to be larger than this specified radius due + * to the starting inner block. + *

+ * */ private int radius = 1; + + /** + *

Some shapes may require an inner radius, such as a hollow sphere or + * a torus. This is ignored for all other shapes. + *

+ */ + private int radiusInner = 0; + + + /** + *

Some shapes may require a height, such as a cylinder or a cone. + * Even if the shape is laying on it's side, the height will still + * apply in other planes and not just up and down. + * This is ignored for all other shapes. + *

+ */ + private int height = 0; + /** - *

The chance of complete removal. So if the radius includes + *

The chance of complete removal. So if the explosion includes * 100 blocks, but the chance is only 50%, each block will be given - * a chance if it is to be included, or excluded. + * a 50% chance to be included from the explosion block list. *

*/ - // private double chance; + private double removalChance; private String explosionShape; - private String toolInHand; + private String toolInHandName; + + private int toolInHandFortuneLevel = 0; private String description; + /** + *

On spigot versions that support it, the bomb, when placed, will glow. + * Was introduced with Minecraft 1.9. Applies only to Entities, of which + * dropped items may be considered an entity? + *

+ */ private boolean glowing = false; + + /** + *

This autosell will force the results of an explosion to autosell even when autosell + * is disabled on the server's auto features. This is almost a requirement for large + * explosions, especially if an unsafe fortune enchantment is being used. + *

+ */ + private boolean autosell = false; + private boolean activated = false; @@ -79,8 +126,12 @@ public MineBombData( String name, String itemType, String explosionShape, } } - this.toolInHand = null; + this.toolInHandName = null; + this.toolInHandFortuneLevel = 0; + this.removalChance = 100.0d; + + this.glowing = false; } @@ -90,9 +141,17 @@ public MineBombData clone() { cloned.setDescription( getDescription() ); - cloned.setToolInHand( getToolInHand() ); + cloned.setToolInHandName( getToolInHandName() ); + cloned.setToolInHandFortuneLevel( getToolInHandFortuneLevel() ); + + cloned.setRadiusInner( getRadiusInner() ); + cloned.setHeight( getHeight() ); + + cloned.setRemovalChance( getRemovalChance() ); + cloned.setGlowing( isGlowing() ); + cloned.setAutosell( isAutosell() ); cloned.setActivated( isActivated() ); for ( String l : lore ) { @@ -137,6 +196,27 @@ public void setRadius( int radius ) { this.radius = radius; } + public int getRadiusInner() { + return radiusInner; + } + public void setRadiusInner( int radiusInner ) { + this.radiusInner = radiusInner; + } + + public int getHeight() { + return height; + } + public void setHeight( int height ) { + this.height = height; + } + + public double getRemovalChance() { + return removalChance; + } + public void setRemovalChance( double removalChance ) { + this.removalChance = removalChance; + } + public String getExplosionShape() { return explosionShape; } @@ -151,11 +231,18 @@ public void setDescription( String description ) { this.description = description; } - public String getToolInHand() { - return toolInHand; + public String getToolInHandName() { + return toolInHandName; } - public void setToolInHand( String toolInHand ) { - this.toolInHand = toolInHand; + public void setToolInHandName( String toolInHandName ) { + this.toolInHandName = toolInHandName; + } + + public int getToolInHandFortuneLevel() { + return toolInHandFortuneLevel; + } + public void setToolInHandFortuneLevel( int toolInHandFortuneLevel ) { + this.toolInHandFortuneLevel = toolInHandFortuneLevel; } public boolean isGlowing() { @@ -165,6 +252,13 @@ public void setGlowing( boolean glowing ) { this.glowing = glowing; } + public boolean isAutosell() { + return autosell; + } + public void setAutosell( boolean autosell ) { + this.autosell = autosell; + } + public boolean isActivated() { return activated; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java index df38267a9..3f103012a 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java @@ -20,10 +20,28 @@ public class MineBombs public enum ExplosionShape { + + cube, + sphere, sphereHollow ; + public static ExplosionShape fromString( String shape ) { + ExplosionShape results = ExplosionShape.sphere; + + if ( shape != null ) { + for ( ExplosionShape xShape : values() ) + { + if ( xShape.name().equalsIgnoreCase( shape ) ) { + results = xShape; + break; + } + } + } + + return results; + } } private MineBombs() { @@ -109,6 +127,11 @@ public void loadConfigJson() { } public List calculateSphere( Location loc, int radius, boolean hollow ) { + + return calculateSphere( loc, radius, hollow, 0 ); + } + + public List calculateSphere( Location loc, int radius, boolean hollow, int radiusInner ) { List results = new ArrayList<>(); if ( loc != null && radius > 0 ) { @@ -117,7 +140,11 @@ public List calculateSphere( Location loc, int radius, boolean hollow int cenZ = loc.getBlockZ(); double radiusSqr = radius * radius; - double radiusHSqr = (radius - 1) * (radius - 1); + + // If the radiusInner is not specified (== 0), then subtract one from radius. + double radiusHSqr = radiusInner == 0 ? + ((radius - 1) * (radius - 1)) : + (radiusInner * radiusInner); for ( int x = cenX - radius ; x <= cenX + radius ; x++ ) { double xSqr = (cenX - x) * (cenX - x); @@ -142,35 +169,125 @@ public List calculateSphere( Location loc, int radius, boolean hollow return results; } + + public List calculateCube( Location loc, int radius ) { + List results = new ArrayList<>(); + + if ( loc != null && radius > 0 ) { + int cenX = loc.getBlockX(); + int cenY = loc.getBlockY(); + int cenZ = loc.getBlockZ(); + + for ( int x = cenX - radius ; x <= cenX + radius ; x++ ) { + for ( int y = cenY + 1; y >= 0 && y >= cenY + 1 - (radius * 2) ; y-- ) { + for ( int z = cenZ - radius ; z <= cenZ + radius ; z++ ) { + + Location l = new Location( loc.getWorld(), x, y, z ); + results.add( l ); + + } + } + } + } + return results; + } + public void setupDefaultMineBombData() { if ( getConfigData().getBombs().size() == 0 ) { - MineBombData mbDataSmall = new MineBombData( - "SmallBomb", "brewing_stand", "sphere", 2, "Small Mine Bomb" ); - mbDataSmall.setDescription("A small mine bomb made with some chemicals and a brewing stand."); - - MineBombData mbDataMedium = new MineBombData( - "MediumBomb", "firework_rocket", "sphere", 5, "Medium Mine Bomb" ); - mbDataMedium.setDescription("A medium mine bomb made from leftover fireworks, " + - "but supercharged with a strange green glowing liquid."); - - MineBombData mbDataLarge = new MineBombData( - "LargeBomb", "tnt", "sphereHollow", 12, "Large Mine Bomb" ); - mbDataLarge.setDescription("A large mine bomb made from TNT with some strange parts " + - "that maybe be " + - "described as alien technology."); - - MineBombData mbDataOof = new MineBombData( - "OofBomb", "tnt_minecart", "sphereHollow", 19, "Oof Mine Bomb" ); - mbDataOof.setDescription("An oof-ably large mine bomb made with a minecart heaping with TNT. " + - "Unlike the large mine bomb, this one obviously is built with alien technology."); - - - getConfigData().getBombs().put( mbDataSmall.getName().toLowerCase(), mbDataSmall ); - getConfigData().getBombs().put( mbDataMedium.getName().toLowerCase(), mbDataMedium ); - getConfigData().getBombs().put( mbDataLarge.getName().toLowerCase(), mbDataLarge ); - getConfigData().getBombs().put( mbDataOof.getName().toLowerCase(), mbDataOof ); +// XMaterial.WOODEN_PICKAXE; +// XMaterial.STONE_PICKAXE; +// XMaterial.IRON_PICKAXE; +// XMaterial.GOLDEN_PICKAXE; +// XMaterial.DIAMOND_PICKAXE; +// XMaterial.NETHERITE_PICKAXE; + + { + MineBombData mbd = new MineBombData( + "SmallBomb", "brewing_stand", ExplosionShape.sphere.name(), 2, "Small Mine Bomb" ); + mbd.setToolInHandName( "DIAMOND_PICKAXE" ); + mbd.setToolInHandFortuneLevel( 0 ); + mbd.setDescription("A small mine bomb made with some chemicals and a brewing stand."); + + getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); + + } + + { + MineBombData mbd = new MineBombData( + "MediumBomb", "firework_rocket", ExplosionShape.sphere.name(), 5, "Medium Mine Bomb" ); + mbd.setDescription("A medium mine bomb made from leftover fireworks, " + + "but supercharged with a strange green glowing liquid."); + mbd.setToolInHandName( "DIAMOND_PICKAXE" ); + mbd.setToolInHandFortuneLevel( 3 ); + + getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); + + } + + { + MineBombData mbd = new MineBombData( + "LargeBomb", "tnt", ExplosionShape.sphereHollow.name(), 12, "Large Mine Bomb" ); + mbd.setRadiusInner( 3 ); + mbd.setDescription("A large mine bomb made from TNT with some strange parts " + + "that maybe be described as alien technology."); + mbd.setToolInHandName( "DIAMOND_PICKAXE" ); + mbd.setToolInHandFortuneLevel( 3 ); + + getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); + } + + { + MineBombData mbd = new MineBombData( + "OofBomb", "tnt_minecart", ExplosionShape.sphereHollow.name(), 19, "Oof Mine Bomb" ); + mbd.setRadiusInner( 3 ); + mbd.setDescription("An oof-ably large mine bomb made with a minecart heaping with TNT. " + + "Unlike the large mine bomb, this one obviously is built with alien technology."); + + mbd.setToolInHandName( "GOLDEN_PICKAXE" ); + mbd.setToolInHandFortuneLevel( 13 ); + + mbd.setAutosell( true ); + mbd.setGlowing( true ); + mbd.setAutosell( true ); + + getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); + } + + { + MineBombData mbd = new MineBombData( + "WimpyBomb", "GUNPOWDER", ExplosionShape.sphere.name(), 5, + "A Wimpy Mine Bomb" ); + mbd.setRadiusInner( 2 ); + mbd.setDescription("A whimpy bomb made with gunpowder and packs the punch of a " + + "dull wooden pickaxe. For some reason, it only has a 40% chance of removing " + + "a block."); + + mbd.setToolInHandName( "WOODEN_PICKAXE" ); + mbd.setToolInHandFortuneLevel( 0 ); + mbd.setRemovalChance( 40.0d ); + + getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); + } + + + { + MineBombData mbd = new MineBombData( + "CubeBomb", "SLIME_BLOCK", ExplosionShape.cube.name(), 2, + "A Cubic Bomb" ); + mbd.setDescription("The most anti-round bomb you will ever be able to find. " + + "It's totally cubic."); + + mbd.setToolInHandName( "DIAMOND_PICKAXE" ); + mbd.setToolInHandFortuneLevel( 7 ); + mbd.setRemovalChance( 100.0d ); + + mbd.setGlowing( true ); + + getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); + } + saveConfigJson(); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java index 25ee0ec0c..d085ddbc7 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java @@ -4,10 +4,12 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Random; import java.util.Set; import java.util.TreeMap; import org.bukkit.Bukkit; +import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Item; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; @@ -18,12 +20,11 @@ import tech.mcprison.prison.autofeatures.AutoFeaturesWrapper; import tech.mcprison.prison.bombs.MineBombData; import tech.mcprison.prison.bombs.MineBombs; +import tech.mcprison.prison.bombs.MineBombs.ExplosionShape; import tech.mcprison.prison.commands.Arg; import tech.mcprison.prison.commands.Command; import tech.mcprison.prison.internal.CommandSender; -import tech.mcprison.prison.internal.ItemStack; import tech.mcprison.prison.internal.block.Block; -import tech.mcprison.prison.output.LogLevel; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.api.ExplosiveBlockBreakEvent; @@ -32,6 +33,7 @@ import tech.mcprison.prison.spigot.compat.SpigotCompatibility; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.game.SpigotWorld; +import tech.mcprison.prison.spigot.spiget.BluesSpigetSemVerComparator; import tech.mcprison.prison.util.Location; import tech.mcprison.prison.util.Text; @@ -84,8 +86,8 @@ public void utilsMineBombs( CommandSender sender, String worldCoordinates, - @Arg(name = "shape", description = "Shape of Explosion. [round]", - def = "round") String shape, + @Arg(name = "shape", description = "Shape of Explosion. [sphere]", + def = "sphere") String shape, @Arg(name = "radiusSize", description = "Size of Explosion in block radius. [1 though 20]", def = "3" ) String radiusSize @@ -173,21 +175,86 @@ public void utilsMineBombsList( CommandSender sender MineBombs mBombs = MineBombs.getInstance(); + List messages = new ArrayList<>(); + Set keys = mBombs.getConfigData().getBombs().keySet(); for ( String key : keys ) { MineBombData bomb = mBombs.getConfigData().getBombs().get( key ); String message = String.format( - "%-12s %-7s Radius= %s (%s)\n %s", - bomb.getName(), bomb.getExplosionShape(), Integer.toString(bomb.getRadius()), - bomb.getItemType(), bomb.getDescription() ); + "%-12s Autosell: %b", + bomb.getName(), + bomb.isAutosell() + ); + + messages.add( message ); + + + + ExplosionShape shape = ExplosionShape.fromString( bomb.getExplosionShape() ); + String messageShape = null; + switch ( shape ) + { + case cube: + { + int lenght = 1 + (bomb.getRadius() * 2); + messageShape = String.format( + " Shape: %s Size: %d x %d x %d Based on Radius: %d.5", + bomb.getExplosionShape(), + lenght, lenght, lenght, + bomb.getRadius() ); + break; + } + + case sphereHollow: + { + messageShape = String.format( + " Shape: %s Radius: %d.5 RadiusInner: %d.5", + bomb.getExplosionShape(), bomb.getRadius(), bomb.getRadiusInner() ); + break; + } + + case sphere: + { + messageShape = String.format( + " Shape: %s Radius: %d.5", + bomb.getExplosionShape(), bomb.getRadius() ); + break; + } + default: + { + messageShape = " (no shape defined)"; + } + } + if ( messageShape != null && !messageShape.isEmpty() ) { + + messages.add( messageShape ); + } + -// sender.sendMessage( message ); + String message2 = String.format( + " ToolInHand: %s Fortune: %d Percent Chance: %f", + bomb.getToolInHandName(), + bomb.getToolInHandFortuneLevel(), + bomb.getRemovalChance() ); + messages.add( message2 ); - Output.get().log( message, LogLevel.PLAIN ); + + String message3 = String.format( + " ItemType: %s Glowng: %b", + bomb.getItemType(), + bomb.isGlowing() ); + messages.add( message3 ); + + + messages.add( " " + bomb.getDescription() ); + + +// Output.get().log( message, LogLevel.PLAIN ); } + sender.sendMessage( messages.toArray( new String[0] ) ); } } @@ -467,10 +534,21 @@ public static boolean setBombInHand( Player player, SpigotBlock sBlock ) { else if ( bomb != null ) { isABomb = true; +// XMaterial.GUNPOWDER; +// XMaterial.BLAZE_POWDER; +// XMaterial.WOODEN_PICKAXE; +// XMaterial.STONE_PICKAXE; +// XMaterial.IRON_PICKAXE; +// XMaterial.GOLDEN_PICKAXE; +// XMaterial.DIAMOND_PICKAXE; +// XMaterial.NETHERITE_PICKAXE; + +// XMaterial.SLIME_BLOCK + // if the toolInHand has not been set, use a diamond pickaxe: - if ( bomb.getToolInHand() == null ) { + if ( bomb.getToolInHandName() == null ) { XMaterial xMat = XMaterial.DIAMOND_PICKAXE; - bomb.setToolInHand( xMat.name() ); + bomb.setToolInHandName( xMat.name() ); } SpigotPlayer sPlayer = new SpigotPlayer( player ); @@ -568,6 +646,14 @@ else if ( bomb != null ) { int delayInTicks = 5 * 20; // 5 secs + // If running MC 1.9.0 or higher, then can use the glowing feature. Ignore for 1.8.x. + if ( new BluesSpigetSemVerComparator().compareMCVersionTo( "1.9.0" ) >= 0 ) { + + dropped.setGlowing( bomb.isGlowing() ); + } + + + // Get the block that is y - 1 lower than the original block: // SpigotBlock bombBlock = (SpigotBlock) sBlock.getRelative( BlockFace.DOWN ); @@ -689,22 +775,7 @@ public void run() { MineBombs mBombs = MineBombs.getInstance(); - // Calculate all the locations that are included in the explosion: - List blockLocations = mBombs.calculateSphere( location, - bomb.getRadius(), false ); - - - SpigotWorld world = (SpigotWorld) location.getWorld(); - - // Convert to spigot blocks: - List blocks = new ArrayList<>(); - for ( Location bLocation : blockLocations ) { - SpigotBlock sBlock = (SpigotBlock) world.getBlockAt( bLocation ); - if ( !sBlock.isEmpty() ) { - - blocks.add( sBlock.getWrapper() ); - } - } + List blocks = calculatBlocksForExplosion( bomb, location, mBombs ); // SpigotBlock targetBlock = (SpigotBlock) world.getBlockAt( location ); @@ -720,15 +791,19 @@ public void run() { // The bomb must define a tool, otherwise auto features will // use the mine bombs that the player is holding, or if it was their // last one, it would be just AIR: - String toolInHandName = bomb.getToolInHand(); + String toolInHandName = bomb.getToolInHandName(); if ( toolInHandName == null || toolInHandName.trim().isEmpty() ) { XMaterial xMat = XMaterial.DIAMOND_PICKAXE; toolInHandName = xMat.name(); } - XMaterial xMatTool = XMaterial.matchXMaterial( toolInHandName ).orElseGet( null ); - ItemStack toolInHand = new SpigotItemStack( xMatTool == null ? - XMaterial.DIAMOND_PICKAXE.parseItem() : - xMatTool.parseItem() ); + + XMaterial xMatTool = XMaterial.matchXMaterial( toolInHandName ) + .orElse( XMaterial.DIAMOND_PICKAXE ); + SpigotItemStack toolInHand = new SpigotItemStack( xMatTool.parseItem() ); + + setFortune( toolInHand, bomb.getToolInHandFortuneLevel() ); + + explodeEvent.setToolInHand( toolInHand ); @@ -759,6 +834,67 @@ public void run() { } + + private List calculatBlocksForExplosion( MineBombData bomb, Location location, + MineBombs mBombs ) + { + List blocks = new ArrayList<>(); + + // Calculate all the locations that are included in the explosion: + List blockLocations = null; + + + ExplosionShape shape = ExplosionShape.fromString( bomb.getExplosionShape() ); + + switch ( shape ) + { + case cube: + { + blockLocations = mBombs.calculateCube( location, + bomb.getRadius() ); + break; + } + + case sphereHollow: + { + blockLocations = mBombs.calculateSphere( location, + bomb.getRadius(), true, bomb.getRadiusInner() ); + break; + } + + case sphere: + default: + { + blockLocations = mBombs.calculateSphere( location, + bomb.getRadius(), false ); + break; + } + } + + + SpigotWorld world = (SpigotWorld) location.getWorld(); + + + // Honor the percent chance for including the block: + double removalChance = bomb.getRemovalChance(); + Random random = new Random(); + + + // Convert to spigot blocks: + for ( Location bLocation : blockLocations ) { + double chance = random.nextDouble() * 100.0d; + + if ( chance <= removalChance ) { + + SpigotBlock sBlock = (SpigotBlock) world.getBlockAt( bLocation ); + if ( !sBlock.isEmpty() ) { + + blocks.add( sBlock.getWrapper() ); + } + } + } + return blocks; + } }.runTaskLater( SpigotPrison.getInstance(), delayTicks ); //.runTaskTimer( SpigotPrison.getInstance(), 10, 10); @@ -766,6 +902,42 @@ public void run() { return results; } + +// protected short getFortune(SpigotItemStack itemInHand){ +// short results = (short) 0; +// +// try { +// if ( itemInHand != null && +// itemInHand.getBukkitStack() != null && +// itemInHand.getBukkitStack().containsEnchantment( Enchantment.LOOT_BONUS_BLOCKS ) && +// itemInHand.getBukkitStack().getEnchantments() != null ) { +// results = (short) itemInHand.getBukkitStack().getEnchantmentLevel(Enchantment.LOOT_BONUS_BLOCKS); +// } +// } +// catch ( NullPointerException e ) { +// // Ignore. This happens when a TokeEnchanted tool is used when TE is not installed anymore. +// // It throws this exception: Caused by: java.lang.NullPointerException: null key in entry: null=5 +// } +// +// return results; +// } + + protected static void setFortune( SpigotItemStack itemInHand, int fortuneLevel ) { + + if ( itemInHand != null && + itemInHand.getBukkitStack() != null && + itemInHand.getBukkitStack().hasItemMeta() ) { + + itemInHand.getBukkitStack().addUnsafeEnchantment( Enchantment.LOOT_BONUS_BLOCKS, fortuneLevel ); + +// ItemMeta meta = itemInHand.getBukkitStack().getItemMeta(); +// meta.addEnchant( Enchantment.LOOT_BONUS_BLOCKS, fortuneLevel, true ); +// itemInHand.getBukkitStack().setItemMeta( meta ); + + } + + } + public static double getPlayerCoolDownRemaining() { From ea528c7cddcb95b0dca854cb9c3f449b0f453f1a Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Thu, 18 Nov 2021 14:43:10 -0500 Subject: [PATCH 114/283] Bug fix: refined the use of a few internal registers that are being used to control block break behavior, and also block counts and block events. A few of the settings were being changed in the wrong places, which was out of synch with when they should have been applied. A few of the side effects was failure of tracking block counts, block events, and handling some explosion events. --- docs/changelog_v3.3.x.md | 5 ++ .../mcprison/prison/mines/data/MineData.java | 25 +++++- .../mcprison/prison/mines/data/MineReset.java | 14 ++-- .../spigot/block/OnBlockBreakEventCore.java | 80 ++++++++----------- 4 files changed, 67 insertions(+), 57 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index b63d92bf1..da5b0fb24 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,11 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.4 2021-11-18 +* **Bug fix: refined the use of a few internal registers that are being used to control block break behavior, and also block counts and block events.* +A few of the settings were being changed in the wrong places, which was out of synch with when they should have been applied. +A few of the side effects was failure of tracking block counts, block events, and handling some explosion events. + + * **Mine Bombs: More features and fixes.** Added support for radiusInner (for hollow sphere explosion shapes), removalChance (chance for block inclusion), glowing, autoSell, tool material type, tool fortune level. Added a new shape which is "cube" and hooked up sphereHollow. Hooked up cube, sphereHollow, removalChance, glowing, the specified tool in hand with the custom fortune level. Did not hook up the forced autosell yet. diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java index 88f85b32b..a6ad920c9 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java @@ -669,22 +669,39 @@ public boolean hasBlock( String blockName ) { * * @param targetPrisonBlock */ - public void incrementBlockMiningCount( MineTargetPrisonBlock targetPrisonBlock ) { + public boolean incrementBlockMiningCount( MineTargetPrisonBlock targetPrisonBlock ) { + boolean results = false; // Only count the block as being broke if it was not originally air and - // and it has not been broke before: - if ( targetPrisonBlock != null && !targetPrisonBlock.isAirBroke() && !targetPrisonBlock.isCounted() ) { + // and it has not been broke before. + + // NOTE: setAirBroke() and setMined() will be set to true if the mine reset + // places an air block. That will prevent the air from being processed. + if ( targetPrisonBlock != null && !targetPrisonBlock.isCounted() ) { targetPrisonBlock.setAirBroke( true ); targetPrisonBlock.setCounted( true ); - targetPrisonBlock.setMined( true ); + + // The field isMined() is used to "reserve" a block to indicate that it is in + // the stages of being processed, since much later in the processing will the + // block be set to setAirBreak() or even setCounted(). This prevents + // high-speed or concurrent operations from multiple players from trying to + // process the same block. So set it to true here, if it has not already + // been set. + if ( !targetPrisonBlock.isMined() ) { + + targetPrisonBlock.setMined( true ); + } incrementBlockBreakCount(); incrementTotalBlocksMined(); targetPrisonBlock.getPrisonBlock().incrementMiningBlockCount(); + results = true; } + + return results; } // public void incrementBlockMiningCount( Block block ) { diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java index 6a3d2ce87..9e8d269e2 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java @@ -1314,17 +1314,16 @@ protected void runMineSweeperTask() { for ( MineTargetPrisonBlock targetBlock : getMineTargetPrisonBlocks() ) { - if ( targetBlock != null && !targetBlock.isAirBroke() ) { + if ( targetBlock != null && !targetBlock.isAirBroke() && + !targetBlock.isCounted()) { + MineTargetBlockKey key = targetBlock.getBlockKey(); Location blockLocation = new Location( world, key.getX(), key.getY(), key.getZ() ); Block block = world.getBlockAt( blockLocation ); if ( block.isEmpty() ) { - targetBlock.getPrisonBlock().incrementMiningBlockCount(); - targetBlock.setAirBroke( true ); - targetBlock.setCounted( true ); - targetBlock.setMined( true ); + incrementBlockMiningCount( targetBlock ); blocksChanged++; } @@ -1669,6 +1668,11 @@ private void constraintsApplyMin( PrisonBlockStatusData block, boolean useNewBlo // Add the new block and increment it's count: targetBlock.setPrisonBlock( block ); + + // If the reset is placing an AiR block, then mark the block as + // setAirBroke() and setMined() to ensure they are not counted or + // processed during normal mining operations, or through + // MineSweeper checks. if ( block.isAir() ) { targetBlock.setAirBroke( true ); targetBlock.setMined( true ); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index 62beabe3b..243b05bff 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -413,7 +413,6 @@ private void doBlockEvents( PrisonMinesBlockBreakEvent pmEvent ) { if ( pmEvent.getMine() != null ) { - // Record the block break: // apply to ALL blocks including exploded: applyBlockFinalizations( pmEvent, pmEvent.getTargetBlock() ); @@ -556,6 +555,12 @@ private boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent, StringBuilder if ( !targetBlock.isMined() || !targetBlock.isAirBroke() ) { + // The field isMined() is used to "reserve" a block to indicate that it is in + // the stages of being processed, since much later in the processing will the + // block be set to setAirBreak() or even setCounted(). This prevents + // high-speed or concurrent operations from multiple players from trying to + // process the same block. + // If a chain reaction on explosions, this will prevent the same block from // being processed more than once: targetBlock.setMined( true ); @@ -1457,26 +1462,18 @@ public void doActionMonitor( SpigotBlock block, Mine mine ) { // Good chance the block was already counted, but just in case it wasn't: MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( block ); - if ( targetBlock != null && !targetBlock.isCounted() ) { - targetBlock.setCounted( true ); + // Record the block break: + if ( mine.incrementBlockMiningCount( targetBlock ) ) { - // Record the block break: - mine.incrementBlockMiningCount( targetBlock ); + // submit a mine sweeper task. It will only run if it is enabled and another + // mine sweeper task has not been submitted. + mine.submitMineSweeperTask(); - if ( !targetBlock.isMined() ) { - targetBlock.setMined( true ); - } + // Checks to see if the mine ran out of blocks, and if it did, then + // it will reset the mine: + mine.checkZeroBlockReset(); } - // Never process BlockEvents in a monitor. - - // submit a mine sweeper task. It will only run if it is enabled and another - // mine sweeper task has not been submitted. - mine.submitMineSweeperTask(); - - // Checks to see if the mine ran out of blocks, and if it did, then - // it will reset the mine: - mine.checkZeroBlockReset(); } } @@ -1488,31 +1485,24 @@ public void doActionBlockEventOnly( SpigotBlock spigotBlock, Mine mine, Player p if ( targetBlock != null && targetBlock.getPrisonBlock() != null && !targetBlock.isCounted() ) { - targetBlock.setCounted( true ); -// targetBlock.setBlockEvent( true ); // String targetBlockName = mine == null ? // spigotBlock.getPrisonBlock().getBlockName() // : targetBlock.getPrisonBlock().getBlockName(); // Process mine block break events: - SpigotPlayer sPlayer = new SpigotPlayer( player ); - - mine.incrementBlockMiningCount( targetBlock ); - - PlayerCache.getInstance().addPlayerBlocks( sPlayer, mine.getName(), targetBlock.getPrisonBlock(), 1 ); - - PrisonBlock prisonBlock = spigotBlock.getPrisonBlock(); - mine.processBlockBreakEventCommands( prisonBlock, targetBlock, sPlayer, blockEventType, triggered ); - - if ( !targetBlock.isMined() ) { - targetBlock.setMined( true ); + if ( mine.incrementBlockMiningCount( targetBlock ) ) { + + SpigotPlayer sPlayer = new SpigotPlayer( player ); + PlayerCache.getInstance().addPlayerBlocks( sPlayer, mine.getName(), targetBlock.getPrisonBlock(), 1 ); + + + PrisonBlock prisonBlock = spigotBlock.getPrisonBlock(); + mine.processBlockBreakEventCommands( prisonBlock, targetBlock, sPlayer, blockEventType, triggered ); } -// if ( targetBlock.getMinedBlock() != null ) { -// targetBlock.setMinedBlock( null ); -// } + } } } @@ -1798,11 +1788,15 @@ private void applyBlockFinalizations( PrisonMinesBlockBreakEvent pmEvent, MineTa if ( targetBlock != null ) { - if ( !targetBlock.isCounted() ) { - targetBlock.setCounted( true ); + Mine mine = pmEvent.getMine(); + + // Increment the block break counts if they have not been processed before. + // Since the function return true if it can count the block, then we can + // then have the player counts be incremented. + if ( mine.incrementBlockMiningCount( targetBlock ) ) { - pmEvent.getMine().incrementBlockMiningCount( targetBlock ); - PlayerCache.getInstance().addPlayerBlocks( pmEvent.getSpigotPlayer(), pmEvent.getMine().getName(), targetBlock.getPrisonBlock(), 1 ); + PlayerCache.getInstance().addPlayerBlocks( pmEvent.getSpigotPlayer(), + mine.getName(), targetBlock.getPrisonBlock(), 1 ); } @@ -1810,19 +1804,9 @@ private void applyBlockFinalizations( PrisonMinesBlockBreakEvent pmEvent, MineTa SpigotBlock sBlock = (SpigotBlock) targetBlock.getMinedBlock(); PrisonBlock pBlock = sBlock == null ? null : sBlock.getPrisonBlock(); - pmEvent.getMine().processBlockBreakEventCommands( pBlock, + mine.processBlockBreakEventCommands( pBlock, targetBlock, pmEvent.getSpigotPlayer(), pmEvent.getBlockEventType(), pmEvent.getTriggered() ); - - // if isMined has not been set, set it: - if ( !targetBlock.isMined() ) { - targetBlock.setMined( true ); - } - -// if ( targetBlock.getMinedBlock() != null ) { -// targetBlock.setMinedBlock( null ); -// } - } } From 2158aebf63719abff97ffabf7a67a4445fcc45a4 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Thu, 18 Nov 2021 22:36:46 -0500 Subject: [PATCH 115/283] Bug fix: For TokenEnchant's explosive event processing, need to set PrisonMinesBlockBreakEvent's setForceIfAirBlock( true ) so the explosion event can be processed, even if the initial block has already been processed. This allows TE explosion events to work correctly now. --- docs/changelog_v3.3.x.md | 4 ++++ .../mcprison/prison/spigot/block/OnBlockBreakEventCore.java | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index da5b0fb24..bb557307f 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.4 2021-11-18 +* **Bug fix: For TokenEnchant's explosive event processing,** need to set PrisonMinesBlockBreakEvent's setForceIfAirBlock( true ) so the explosion event can be processed, even if the initial block has already been processed. +This allows TE explosion events to work correctly now. + + * **Bug fix: refined the use of a few internal registers that are being used to control block break behavior, and also block counts and block events.* A few of the settings were being changed in the wrong places, which was out of synch with when they should have been applied. A few of the side effects was failure of tracking block counts, block events, and handling some explosion events. diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index 243b05bff..52d9b7794 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -889,6 +889,12 @@ private void genericBlockExplodeEvent( TEBlockExplodeEvent e, boolean monitor, b PrisonMinesBlockBreakEvent pmEvent = new PrisonMinesBlockBreakEvent( e.getBlock(), e.getPlayer(), sBlock, sPlayer, monitor, blockEventsOnly, eventType, triggered ); + // NOTE: Token Enchant will pass the event's block to prison, but that block may + // have already been processed by prison. Therefore the PrisonMinesBlockBreakEvent + // must enable the feature setForceIfAirBlock( true ). That block will not be used a + // second time, but it will allow the explosion event to be processed. + pmEvent.setForceIfAirBlock( true ); + pmEvent.setUnprocessedRawBlocks( e.blockList() ); if ( !validateEvent( pmEvent, debugInfo ) ) { From 58153d178c59e2b2d6c963ee6718024ea7162ece Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 19 Nov 2021 00:03:59 -0500 Subject: [PATCH 116/283] Mine bombs: Add cooldown and fuse delay to the mine bomb settings so each bomb can be customized. Added gravity to the mine bombs too. Gravity, like glow, was added in minecraft 1.9 so older versions won't work. --- docs/changelog_v3.3.x.md | 4 + .../mcprison/prison/bombs/MineBombData.java | 89 ++++++++++++++----- .../tech/mcprison/prison/bombs/MineBombs.java | 6 ++ .../spigot/utils/PrisonUtilsMineBombs.java | 60 ++++--------- 4 files changed, 98 insertions(+), 61 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index bb557307f..ab61c981a 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.4 2021-11-18 +* **Mine bombs: Add cooldown and fuse delay to the mine bomb settings so each bomb can be customized. +Added gravity to the mine bombs too.** Gravity, like glow, was added in minecraft 1.9 so older versions won't work. + + * **Bug fix: For TokenEnchant's explosive event processing,** need to set PrisonMinesBlockBreakEvent's setForceIfAirBlock( true ) so the explosion event can be processed, even if the initial block has already been processed. This allows TE explosion events to work correctly now. diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java index 8adacc2df..d4177ecaf 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java @@ -9,6 +9,11 @@ public class MineBombData { private String name; + private String description; + + private List lore; + + /** *

The String name of an XMaterial item to use as the "bomb". @@ -23,9 +28,6 @@ public class MineBombData { */ private transient PrisonBlock item; - - private List lore; - /** *

The radius identifies how large the blast should be as * expressed in a radius. Generally this applies to a sphere or @@ -68,7 +70,7 @@ public class MineBombData { * a 50% chance to be included from the explosion block list. *

*/ - private double removalChance; + private double removalChance = 100.0d; // 100.0 % chance private String explosionShape; @@ -79,7 +81,9 @@ public class MineBombData { private int toolInHandFortuneLevel = 0; - private String description; + private int fuseDelayTicks = 5 * 20; // 5 seconds + + private int cooldownTicks = 30 * 20; // 30 seconds /** @@ -91,6 +95,14 @@ public class MineBombData { private boolean glowing = false; + /** + *

Identifies if the item is effected by gravity. + * Gravity was introduced with Minecraft 1.9. + *

+ */ + private boolean gravity = true; + + /** *

This autosell will force the results of an explosion to autosell even when autosell * is disabled on the server's auto features. This is almost a requirement for large @@ -131,7 +143,14 @@ public MineBombData( String name, String itemType, String explosionShape, this.removalChance = 100.0d; + this.fuseDelayTicks = 5 * 20; + + this.cooldownTicks = 30 * 20; + + this.glowing = false; + this.gravity = true; + } @@ -148,9 +167,13 @@ public MineBombData clone() { cloned.setHeight( getHeight() ); cloned.setRemovalChance( getRemovalChance() ); - + cloned.setFuseDelayTicks( getFuseDelayTicks() ); + cloned.setCooldownTicks( getCooldownTicks() ); cloned.setGlowing( isGlowing() ); + cloned.setGravity( isGravity() ); + + cloned.setAutosell( isAutosell() ); cloned.setActivated( isActivated() ); @@ -168,6 +191,20 @@ public void setName( String name ) { this.name = name; } + public String getDescription() { + return description; + } + public void setDescription( String description ) { + this.description = description; + } + + public List getLore() { + return lore; + } + public void setLore( List lore ) { + this.lore = lore; + } + public String getItemType() { return itemType; } @@ -182,13 +219,6 @@ public void setItem( PrisonBlock item ) { this.item = item; } - public List getLore() { - return lore; - } - public void setLore( List lore ) { - this.lore = lore; - } - public int getRadius() { return radius; } @@ -224,13 +254,6 @@ public void setExplosionShape( String explosionShape ) { this.explosionShape = explosionShape; } - public String getDescription() { - return description; - } - public void setDescription( String description ) { - this.description = description; - } - public String getToolInHandName() { return toolInHandName; } @@ -245,6 +268,20 @@ public void setToolInHandFortuneLevel( int toolInHandFortuneLevel ) { this.toolInHandFortuneLevel = toolInHandFortuneLevel; } + public int getFuseDelayTicks() { + return fuseDelayTicks; + } + public void setFuseDelayTicks( int fuseDelayTicks ) { + this.fuseDelayTicks = fuseDelayTicks; + } + + public int getCooldownTicks() { + return cooldownTicks; + } + public void setCooldownTicks( int cooldownTicks ) { + this.cooldownTicks = cooldownTicks; + } + public boolean isGlowing() { return glowing; } @@ -252,6 +289,18 @@ public void setGlowing( boolean glowing ) { this.glowing = glowing; } + public boolean isGravity() + { + return gravity; + } + + + public void setGravity( boolean gravity ) + { + this.gravity = gravity; + } + + public boolean isAutosell() { return autosell; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java index 3f103012a..164f2ae1f 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java @@ -268,6 +268,12 @@ public void setupDefaultMineBombData() mbd.setToolInHandFortuneLevel( 0 ); mbd.setRemovalChance( 40.0d ); + mbd.setCooldownTicks( 3 * 20 ); // 3 seconds + mbd.setFuseDelayTicks( 2 * 20 ); // 2 seconds + + mbd.setGlowing( true ); + mbd.setGravity( false ); + getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java index d085ddbc7..0ac51542c 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java @@ -183,9 +183,11 @@ public void utilsMineBombsList( CommandSender sender MineBombData bomb = mBombs.getConfigData().getBombs().get( key ); String message = String.format( - "%-12s Autosell: %b", + "%-12s Autosell: %b FuseDelayTicks: %d CooldownTicks: %d", bomb.getName(), - bomb.isAutosell() + bomb.isAutosell(), + bomb.getFuseDelayTicks(), + bomb.getCooldownTicks() ); messages.add( message ); @@ -242,9 +244,10 @@ public void utilsMineBombsList( CommandSender sender String message3 = String.format( - " ItemType: %s Glowng: %b", + " ItemType: %s Glowng: %b Gravity: %b", bomb.getItemType(), - bomb.isGlowing() ); + bomb.isGlowing(), + bomb.isGravity() ); messages.add( message3 ); @@ -560,7 +563,7 @@ else if ( bomb != null ) { // Set cooldown: - PrisonUtilsMineBombs.addPlayerCooldown( playerUUID ); + PrisonUtilsMineBombs.addPlayerCooldown( playerUUID, bomb.getCooldownTicks() ); SpigotItemStack bombs = PrisonUtilsMineBombs.getItemStackBomb( bomb ); @@ -598,14 +601,6 @@ else if ( bomb != null ) { SpigotCompatibility.getInstance().setItemInMainHand( player, itemInHand.getBukkitStack() ); - //Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent 05 " ); - - // SpigotBlock sBlock = new SpigotBlock( event.getClickedBlock() ); - - //Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent dropping block " ); - - - // For mine bombs, take the block below where the bomb's item was dropped. The floating // item is not the block that needs to be the target block for the explosion. Also, the block @@ -619,12 +614,6 @@ else if ( bomb != null ) { bombBlock = (SpigotBlock) tempBlock; } - -// Location bbLocation = bombBlock.getLocation(); -// bbLocation.setY( bbLocation.getBlockY() - 1 ); -// -// bombBlock = (SpigotBlock) bbLocation.getBlockAt(); - // Output.get().logInfo( // "#### PrisonUtilsMineBombs: bomb y loc: " + bombBlock.getWrapper().getLocation().getBlockY() + // " " + bombBlock.getLocation().getBlockY() + " count= " + count ); @@ -643,39 +632,28 @@ else if ( bomb != null ) { dropped.setCustomName( bomb.getName() ); //dropped.setVelocity(player.getLocation().getDirection().multiply( throwSpeed ).normalize() ); - int delayInTicks = 5 * 20; // 5 secs +// int delayInTicks = 5 * 20; // 5 secs // If running MC 1.9.0 or higher, then can use the glowing feature. Ignore for 1.8.x. if ( new BluesSpigetSemVerComparator().compareMCVersionTo( "1.9.0" ) >= 0 ) { dropped.setGlowing( bomb.isGlowing() ); + + + // setGravity is invalid for spigot 1.8.8: + dropped.setGravity( bomb.isGravity() ); } - - // Get the block that is y - 1 lower than the original block: -// SpigotBlock bombBlock = (SpigotBlock) sBlock.getRelative( BlockFace.DOWN ); - - // Submit the bomb's task to go off: - PrisonUtilsMineBombs.setoffBombDelayed( sPlayer, bomb, dropped, bombBlock, delayInTicks ); + PrisonUtilsMineBombs.setoffBombDelayed( sPlayer, bomb, dropped, bombBlock ); - - // setGlow is invalid for spigot 1.8.8: - //dropped.setGlowing( bomb.isGlowing() ); - - // setGravity is invalid for spigot 1.8.8: -// dropped.setGravity( false ); - - - // dropped.setMetadata( "prisonMineBomb", new FixedMetadataValue( SpigotPrison.getInstance(), true ) ); //dropped.setMetadata( "prisonMineName", new FixedMetadataValue( SpigotPrison.getInstance(), "mineName" ) ); - } } @@ -698,9 +676,9 @@ else if ( bomb != null ) { return isABomb; } - public static boolean addPlayerCooldown( String playerUUID ) { - return addPlayerCooldown( playerUUID, MINE_BOMBS_COOLDOWN_TICKS ); - } +// public static boolean addPlayerCooldown( String playerUUID ) { +// return addPlayerCooldown( playerUUID, MINE_BOMBS_COOLDOWN_TICKS ); +// } /** *

If a cooldown is not setup for the player, this will try to add one and @@ -755,7 +733,7 @@ public static int checkPlayerCooldown( String playerUUID ) { } public static boolean setoffBombDelayed( SpigotPlayer sPlayer, MineBombData bomb, Item droppedBomb, - SpigotBlock targetBlock, int delayTicks ) { + SpigotBlock targetBlock ) { boolean results = false; new BukkitRunnable() { @@ -895,7 +873,7 @@ private List calculatBlocksForExplosion( MineBombData bo } return blocks; } - }.runTaskLater( SpigotPrison.getInstance(), delayTicks ); + }.runTaskLater( SpigotPrison.getInstance(), bomb.getFuseDelayTicks() ); //.runTaskTimer( SpigotPrison.getInstance(), 10, 10); From f3f75458896984c2a5b4d4730627dc2ebcfaddca Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 19 Nov 2021 11:47:59 -0500 Subject: [PATCH 117/283] SellAll: Setup a sellall function that will allow the selling of one ItemStack, which is not tied to any of the player's inventories. This is used in prison's auto features when enabling the option to auto sell on a per block break event basis. This is highly optimized and a lot faster than using the normal sellall since it does not deal with any of the player's inventories or backpacks. This forces a delayed sold amount message since an explosion could includ many ItemStacks. --- docs/changelog_v3.3.x.md | 7 +- .../prison/spigot/sellall/SellAllUtil.java | 82 ++++++++++++++++++- 2 files changed, 87 insertions(+), 2 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index ab61c981a..66abf0cb4 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,12 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.4 2021-11-18 +# 3.2.11-alpha.4 2021-11-19 + + +* **SellAll: Setup a sellall function that will allow the selling of one ItemStack, which is not tied to any of the player's inventories.** +This is used in prison's auto features when enabling the option to auto sell on a per block break event basis. This is highly optimized and a lot faster than using the normal sellall since it does not deal with any of the player's inventories or backpacks. +This forces a delayed sold amount message since an explosion could includ many ItemStacks. * **Mine bombs: Add cooldown and fuse delay to the mine bomb settings so each bomb can be customized. diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java index 3a31913ee..b4936803f 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java @@ -24,6 +24,7 @@ import tech.mcprison.prison.ranks.data.RankPlayer; import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.backpacks.BackpacksUtil; +import tech.mcprison.prison.spigot.block.SpigotItemStack; import tech.mcprison.prison.spigot.compat.Compatibility; import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; @@ -377,6 +378,31 @@ public double getSellMoney(Player p){ return getSellMoney(p, getHashMapOfPlayerInventories(p)); } + + /** + *

This sells a specific item stack. Actually it returns the value of an item stack, + * its up to the calling function to dispose of the contents if the result is non-zero. + *

+ * @param p + * @param itemStack + * @return + */ + private double getSellMoney( Player p, SpigotItemStack itemStack ) + { + double results = 0d; + + HashMap xMaterialIntegerHashMap = new HashMap<>(); + + XMaterial xMat = XMaterial.matchXMaterial( itemStack.getBukkitStack() ); + + if ( xMat != null ) { + xMaterialIntegerHashMap.put( xMat, itemStack.getAmount() ); + + results = getSellMoney( p, xMaterialIntegerHashMap ); + } + + return results; + } /** * Get HashMap with all the items of a Player. @@ -1475,8 +1501,62 @@ public boolean sellAllSell(Player p, boolean isUsingSign, boolean completelySile return false; } } - + + /** + *

This function enables the selling of just one ItemStack and can be used outside of + * the player's inventory, such as processing the drops of tens of thousands of blocks + * worth of drops. This would be much faster than processing the player's inventory. + *

+ * + *

This function is used by auto features. + *

+ * + * @param p + * @param itemStack + * @param completelySilent + * @param notifyPlayerEarned + * @param notifyPlayerEarningDelay + * @return Amount of money earned from the sale of the item stack + */ + public double sellAllSell(Player p, SpigotItemStack itemStack, + boolean completelySilent, boolean notifyPlayerEarned, boolean notifyPlayerEarningDelay){ + + double money = getSellMoney(p, itemStack); + + if (money != 0){ + + SpigotPlayer sPlayer = new SpigotPlayer(p); + RankPlayer rankPlayer = PrisonRanks.getInstance().getPlayerManager().getPlayer(sPlayer.getUUID(), sPlayer.getName()); + + if (sellAllCurrency != null && sellAllCurrency.equalsIgnoreCase("default")) sellAllCurrency = null; + rankPlayer.addBalance(sellAllCurrency, money); + + + if (!completelySilent) { + + if (notifyPlayerEarningDelay // && isAutoSellEarningNotificationDelayEnabled + ){ + + if (!isPlayerWaitingAutoSellNotification(p)){ + // Force delayed notifications, even if delayed is disabled: + autoSellEarningsNotificationWaiting.put(p, 0.00); + Bukkit.getScheduler().scheduleSyncDelayedTask(SpigotPrison.getInstance(), () -> removeFromAutoSellDelayAndNotify(p), 20L * defaultAutoSellEarningNotificationDelay); + } else { + addDelayedEarningAutoSellNotification(p, money); + } + } else if (notifyPlayerEarned){ + Output.get().sendInfo(sPlayer, messages.getString(MessagesConfig.StringID.spigot_message_sellall_money_earned) + money); + } + } + } + + return money; + } + + + + /** * Sell removing items from Inventories and checking all the possible conditions that a Player must meet to sell * items, this includes method parameters like: * - Is using SellAll Sign. From 743c68894bf945ec43b2095f9d96bf3cfab8c75a Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 19 Nov 2021 11:50:22 -0500 Subject: [PATCH 118/283] PrisonDispatchCommandTask: Removed the debug logging since it can be very numerous when used with a large mine bomb and it's pointless since most of the block events being submitted runs in less that one millisecond. So this is just cleaning up a messy logging item. --- docs/changelog_v3.3.x.md | 4 ++++ .../tasks/PrisonDispatchCommandTask.java | 20 +++++++++---------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 66abf0cb4..1cdbd0bdd 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.4 2021-11-19 +* **PrisonDispatchCommandTask: Removed the debug logging since it can be very numerous when used with a large mine bomb and it's pointless since most of the block events being submitted runs in less that one millisecond.** +So this is just cleaning up a messy logging item. + + * **SellAll: Setup a sellall function that will allow the selling of one ItemStack, which is not tied to any of the player's inventories.** This is used in prison's auto features when enabling the option to auto sell on a per block break event basis. This is highly optimized and a lot faster than using the normal sellall since it does not deal with any of the player's inventories or backpacks. This forces a delayed sold amount message since an explosion could includ many ItemStacks. diff --git a/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonDispatchCommandTask.java b/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonDispatchCommandTask.java index f9f63a2f9..16ad2ba65 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonDispatchCommandTask.java +++ b/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonDispatchCommandTask.java @@ -46,24 +46,24 @@ public void run() { try { if ( playerTask && player != null ) { - double start = System.currentTimeMillis(); +// double start = System.currentTimeMillis(); PrisonAPI.dispatchCommand( player, task ); - double stop = System.currentTimeMillis(); - Output.get().logDebug( "PrisonDispatchCommandTask.run: (player) " + - (stop - start) + " ms player= " + player.getName() + - " task: " + task ); +// double stop = System.currentTimeMillis(); +// Output.get().logDebug( "PrisonDispatchCommandTask.run: (player) " + +// (stop - start) + " ms player= " + player.getName() + +// " task: " + task ); } else { - double start = System.currentTimeMillis(); +// double start = System.currentTimeMillis(); PrisonAPI.dispatchCommand( task ); - double stop = System.currentTimeMillis(); - Output.get().logDebug( "PrisonDispatchCommandTask.run: (console) " + - (stop - start) + " ms" + - " task: " + task ); +// double stop = System.currentTimeMillis(); +// Output.get().logDebug( "PrisonDispatchCommandTask.run: (console) " + +// (stop - start) + " ms" + +// " task: " + task ); } } catch ( Exception e ) { From a70947d32c4ffe0e500be51de6ff857184133c53 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 19 Nov 2021 12:32:54 -0500 Subject: [PATCH 119/283] Auto Features Forced Auto Sell Optimization Improvement: AutoSell within auto features now only uses sellall by item stack and not the player interface that accesses all of the player's inventories. Since the auto features items are not placed in the player's inventories at this time in the process of auto features, there is no reason to access the player's inventories. Selling directly reduces a lot of sellall overhead and as a result sellall is just calculating the prices. The old autosell code within autofeatures has not be removed yet, but it cannot be called anymore. --- docs/changelog_v3.3.x.md | 5 ++ .../api/PrisonMinesBlockBreakEvent.java | 14 ++++++ .../autofeatures/AutoManagerFeatures.java | 50 +++++++++++++------ 3 files changed, 53 insertions(+), 16 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 1cdbd0bdd..653d9a05d 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,11 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.4 2021-11-19 +* **Auto Features Forced Auto Sell Optimization Improvement: AutoSell within auto features now only uses sellall by item stack and not the player interface that accesses all of the player's inventories.** +Since the auto features items are not placed in the player's inventories at this time in the process of auto features, there is no reason to access the player's inventories. Selling directly reduces a lot of sellall overhead and as a result sellall is just calculating the prices. +The old autosell code within autofeatures has not be removed yet, but it cannot be called anymore. + + * **PrisonDispatchCommandTask: Removed the debug logging since it can be very numerous when used with a large mine bomb and it's pointless since most of the block events being submitted runs in less that one millisecond.** So this is just cleaning up a messy logging item. diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockBreakEvent.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockBreakEvent.java index 506c354c0..25d460c53 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockBreakEvent.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockBreakEvent.java @@ -89,6 +89,13 @@ public class PrisonMinesBlockBreakEvent private boolean calculateDurability = true; + // The use of forceAutoSell will sell the drops before they are added to the + // player's inventory. This would actually be much faster to process than + // going through the normal sellall functionality since that will have to process + // all of the player's inventory slots, including their backpacks. + private boolean forceAutoSell = false; + + private boolean monitor = false; private boolean blockEventsOnly = false; @@ -295,6 +302,13 @@ public void setCalculateDurability( boolean calculateDurability ) { this.calculateDurability = calculateDurability; } + public boolean isForceAutoSell() { + return forceAutoSell; + } + public void setForceAutoSell( boolean forceAutoSell ) { + this.forceAutoSell = forceAutoSell; + } + public boolean isMonitor() { return monitor; } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java index dc616ef75..e56f5397d 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java @@ -479,29 +479,47 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, count += itemStack.getAmount(); - HashMap extras = SpigotUtil.addItemToPlayerInventory( player, itemStack ); - - if ( extras.size() > 0 && autosellPerBlockBreak( player ) ) { + if (isBoolean(AutoFeatures.isAutoSellPerBlockBreakEnabled) || + pmEvent.isForceAutoSell() ) { - // Try to add the extras back to the player's inventory if they had autosellPerBlockBrean enabled: - for ( SpigotItemStack extraItemStack : extras.values() ) { - - HashMap extras2 = SpigotUtil.addItemToPlayerInventory( player, extraItemStack ); - - autosellPerBlockBreak( player ); + double amount = SellAllUtil.get().sellAllSell( player, itemStack, false, false, true ); - // If the remainder of the extras still as too much, then just drop them and move on: - dropExtra( extras2, player ); + debugInfo.append( "(sold: " + itemStack.getName() + " qty: " + itemStack.getAmount() + " amt: " + amount + ") "); + + // Set to zero quantity since they have all been sold. + itemStack.setAmount( 0 ); + } + else { + + HashMap extras = SpigotUtil.addItemToPlayerInventory( player, itemStack ); + + if ( extras.size() > 0 && autosellPerBlockBreak( player ) ) { + + // Try to add the extras back to the player's inventory if they had autosellPerBlockBrean enabled: + for ( SpigotItemStack extraItemStack : extras.values() ) { + + HashMap extras2 = SpigotUtil.addItemToPlayerInventory( player, extraItemStack ); + + autosellPerBlockBreak( player ); + + // If the remainder of the extras still as too much, then just drop them and move on: + dropExtra( extras2, player ); + } + extras.clear(); } - extras.clear(); + + dropExtra( extras, player ); +// dropExtra( player.getInventory().addItem(itemStack), player, block ); } - dropExtra( extras, player ); -// dropExtra( player.getInventory().addItem(itemStack), player, block ); - } + } - autosellPerBlockBreak( player ); + if ( !isBoolean(AutoFeatures.isAutoSellPerBlockBreakEnabled) && + !pmEvent.isForceAutoSell() ) { + + autosellPerBlockBreak( player ); + } // autoPickupCleanup( player, itemInHand, count ); } From 81dd01205a823bfe263a87e24f92b290c896a065 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 19 Nov 2021 12:39:34 -0500 Subject: [PATCH 120/283] Autofeatures ignore certain events to improve performance and reduce logging entries when in debug mode. Since there are multiple listeners on block break events, which monitor the same event, these changes are able to mark a specific block within the MineTargetPrisonBlock objects that will be able to pass along an "ignore" event status to the other listeners to short-circuit their processing. This is highly beneficial when using large mine bombs and the mine has blockEvents setup to perform explosions... which will help reduce a ton of "dead" events. --- docs/changelog_v3.3.x.md | 4 + .../internal/block/MineTargetPrisonBlock.java | 8 + .../spigot/block/OnBlockBreakEventCore.java | 306 ++++++++++++++---- 3 files changed, 263 insertions(+), 55 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 653d9a05d..d328ef743 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.4 2021-11-19 +* **Autofeatures ignore certain events to improve performance and reduce logging entries when in debug mode.** +Since there are multiple listeners on block break events, which monitor the same event, these changes are able to mark a specific block within the MineTargetPrisonBlock objects that will be able to pass along an "ignore" event status to the other listeners to short-circuit their processing. This is highly beneficial when using large mine bombs and the mine has blockEvents setup to perform explosions... which will help reduce a ton of "dead" events. + + * **Auto Features Forced Auto Sell Optimization Improvement: AutoSell within auto features now only uses sellall by item stack and not the player interface that accesses all of the player's inventories.** Since the auto features items are not placed in the player's inventories at this time in the process of auto features, there is no reason to access the player's inventories. Selling directly reduces a lot of sellall overhead and as a result sellall is just calculating the prices. The old autosell code within autofeatures has not be removed yet, but it cannot be called anymore. diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetPrisonBlock.java b/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetPrisonBlock.java index 667885713..b3a7c3d5c 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetPrisonBlock.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetPrisonBlock.java @@ -20,6 +20,7 @@ public class MineTargetPrisonBlock // private boolean blockEvent = false; private boolean counted = false; + private boolean ignoreAllBlockEvents = false; protected MineTargetPrisonBlock( World world, int x, int y, int z, boolean isEdge ) { @@ -155,6 +156,13 @@ public void setMinedBlock( Block minedBlock ) { this.minedBlock = minedBlock; } + public boolean isIgnoreAllBlockEvents() { + return ignoreAllBlockEvents; + } + public void setIgnoreAllBlockEvents( boolean ignoreAllBlockEvents ) { + this.ignoreAllBlockEvents = ignoreAllBlockEvents; + } + @Override public int compareTo( MineTargetPrisonBlock block ) { return block.getBlockKey().compareTo( block.getBlockKey() ); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index 52d9b7794..5c4e4f165 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -296,6 +296,22 @@ protected void genericBlockEvent( BlockBreakEvent e, boolean monitor, boolean bl long start = System.nanoTime(); + if ( e.isCancelled() && !monitor ) { + // Check to see if the event should be ignored. + + SpigotBlock sBlock = new SpigotBlock( e.getBlock() ); + + Mine mine = findMine( e.getPlayer(), sBlock, null, null ); + + MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); + + // If ignore all block events, then exit this function without logging anything: + if ( targetBlock.isIgnoreAllBlockEvents() ) { + return; + } + + } + // Register all external events such as mcMMO and EZBlocks: OnBlockBreakExternalEvents.getInstance().registerAllExternalEvents(); @@ -393,10 +409,13 @@ else if ( pmEvent.getMine() != null || pmEvent.getMine() == null && } - long stop = System.nanoTime(); - debugInfo.append( " [" ).append( (stop - start) / 1000000d ).append( " ms]" ); - - Output.get().logDebug( DebugTarget.blockBreak, debugInfo.toString() ); + if ( debugInfo.length() > 0 ) { + + long stop = System.nanoTime(); + debugInfo.append( " [" ).append( (stop - start) / 1000000d ).append( " ms]" ); + + Output.get().logDebug( DebugTarget.blockBreak, debugInfo.toString() ); + } } @@ -483,48 +502,35 @@ private List finalizeBreakTheBlocksCollectEm( PrisonMinesBlockBreak return blocks; } - - /** - *

This function an attempt to provide a uniform procedure to validate if the event should - * be processed. This will eliminate a lot of duplicate code, and will make supporting other - * plugin events easier to implement. - *

- * - *

This is using the PrisonMinesBlockBreakEvent object to act as the vehicle for carrying - * all of the possible parameters that are needed for appropriate processing. - *

- * - * @param pmEvent - * @param debugInfo - * @return - */ - private boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent, StringBuilder debugInfo ) - { - boolean results = true; + private Mine findMine( Player player, SpigotBlock sBlock, + List altBlocksSource, PrisonMinesBlockBreakEvent pmEvent ) { - - Long playerUUIDLSB = Long.valueOf( pmEvent.getPlayer().getUniqueId().getLeastSignificantBits() ); + Long playerUUIDLSB = Long.valueOf( player.getUniqueId().getLeastSignificantBits() ); // Get the cached mine, if it exists: Mine mine = getPlayerCache().get( playerUUIDLSB ); if ( mine == null || - pmEvent.getSpigotBlock() != null && !mine.isInMineExact( pmEvent.getSpigotBlock().getLocation() ) ) { + sBlock != null && !mine.isInMineExact( sBlock.getLocation() ) ) { // Look for the correct mine to use. // Set mine to null so if cannot find the right one it will return a null: - mine = findMineLocation( pmEvent.getSpigotBlock() ); + mine = findMineLocation( sBlock ); // Thanks to CrazyEnchant, where they do not identify the block the player breaks, we // have to go through all of the unprecessedRawBlocks to see if any are within a mine. // If we find a block that's in a mine, then use that block as the primary block. - if ( mine == null ) { + if ( mine == null && altBlocksSource != null ) { - for ( Block bBlock : pmEvent.getUnprocessedRawBlocks() ) + for ( Block bBlock : altBlocksSource ) { - SpigotBlock sBlock = new SpigotBlock( bBlock ); - mine = findMineLocation( sBlock ); + SpigotBlock sBlockAltBlock = new SpigotBlock( bBlock ); + mine = findMineLocation( sBlockAltBlock ); if ( mine != null ) { - pmEvent.setSpigotBlock( sBlock ); + + if ( pmEvent != null ) { + pmEvent.setSpigotBlock( sBlockAltBlock ); + } + break; } } @@ -535,6 +541,66 @@ private boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent, StringBuilder getPlayerCache().put( playerUUIDLSB, mine ); } } + + + return mine; + } + + + /** + *

This function an attempt to provide a uniform procedure to validate if the event should + * be processed. This will eliminate a lot of duplicate code, and will make supporting other + * plugin events easier to implement. + *

+ * + *

This is using the PrisonMinesBlockBreakEvent object to act as the vehicle for carrying + * all of the possible parameters that are needed for appropriate processing. + *

+ * + * @param pmEvent + * @param debugInfo + * @return + */ + private boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent, StringBuilder debugInfo ) + { + boolean results = true; + + + Mine mine = findMine( pmEvent.getPlayer(), pmEvent.getSpigotBlock(), + pmEvent.getUnprocessedRawBlocks(), pmEvent ); + +// Long playerUUIDLSB = Long.valueOf( pmEvent.getPlayer().getUniqueId().getLeastSignificantBits() ); +// +// // Get the cached mine, if it exists: +// Mine mine = getPlayerCache().get( playerUUIDLSB ); +// +// if ( mine == null || +// pmEvent.getSpigotBlock() != null && !mine.isInMineExact( pmEvent.getSpigotBlock().getLocation() ) ) { +// // Look for the correct mine to use. +// // Set mine to null so if cannot find the right one it will return a null: +// mine = findMineLocation( pmEvent.getSpigotBlock() ); +// +// // Thanks to CrazyEnchant, where they do not identify the block the player breaks, we +// // have to go through all of the unprecessedRawBlocks to see if any are within a mine. +// // If we find a block that's in a mine, then use that block as the primary block. +// if ( mine == null ) { +// +// for ( Block bBlock : pmEvent.getUnprocessedRawBlocks() ) +// { +// SpigotBlock sBlock = new SpigotBlock( bBlock ); +// mine = findMineLocation( sBlock ); +// if ( mine != null ) { +// pmEvent.setSpigotBlock( sBlock ); +// break; +// } +// } +// } +// +// // Store the mine in the player cache if not null: +// if ( mine != null ) { +// getPlayerCache().put( playerUUIDLSB, mine ); +// } +// } pmEvent.setMine( mine ); debugInfo.append( "mine=" + (mine == null ? "none" : mine.getName()) + " " ); @@ -547,8 +613,22 @@ private boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent, StringBuilder int alreadyMined = 0; int noTargetBlock = 0; + boolean targetBlockAlreadyMined = false; + // Get the mine's targetBlock: MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( pmEvent.getSpigotBlock() ); + pmEvent.setTargetBlock( targetBlock ); + + // If ignore all block evnts has been set on this target block, then shutdown + if ( targetBlock.isIgnoreAllBlockEvents() ) { + debugInfo.setLength( 0 ); + + pmEvent.setForceIfAirBlock( false ); + + pmEvent.setCancelOriginalEvent( true ); + + return false; + } // NOTE: for the primary block pmEvent.getSpigotBlock() the unbreakable will be checked later: if ( targetBlock != null && targetBlock.getPrisonBlock() != null ) { @@ -566,10 +646,10 @@ private boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent, StringBuilder targetBlock.setMined( true ); targetBlock.setMinedBlock( pmEvent.getSpigotBlock() ); - pmEvent.setTargetBlock( targetBlock ); } else { alreadyMined++; + targetBlockAlreadyMined = true; if ( !targetBlock.isMined() ) { targetBlock.setMined( true ); @@ -677,6 +757,31 @@ else if ( results ) { debugInfo.append( "NO_TARGET_BLOCKS (" + noTargetBlock + " ) " ); } + + + // If target block aready was mined and there are no exploded blocks, then this whole event + // needs to be canceled since it sounds like a blockevent fired a prison util explosion that + // has zero blocks tied to it. + if ( targetBlockAlreadyMined && pmEvent.isForceIfAirBlock() && pmEvent.getExplodedBlocks().size() == 0 ) { + + // Since this was a dud event, we must set the flag to ignore all + // future block events that include this block as the primary block. + // This code block cancels the current event, but we must ensure that + // the monitor event is also canceled. + pmEvent.getTargetBlock().setIgnoreAllBlockEvents( true ); + + pmEvent.setForceIfAirBlock( false ); + + results = false; + + pmEvent.setCancelOriginalEvent( true ); + + // Ignore event and clear debugInfo: + debugInfo.setLength( 0 ); + + return results; + } + } @@ -858,6 +963,22 @@ private void genericBlockExplodeEvent( TEBlockExplodeEvent e, boolean monitor, b boolean autoManager ) { long start = System.nanoTime(); + + if ( e.isCancelled() && !monitor ) { + // Check to see if the event should be ignored. + + SpigotBlock sBlock = new SpigotBlock( e.getBlock() ); + + Mine mine = findMine( e.getPlayer(), sBlock, e.blockList(), null ); + + MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); + + // If ignore all block events, then exit this function without logging anything: + if ( targetBlock.isIgnoreAllBlockEvents() ) { + return; + } + + } // Register all external events such as mcMMO and EZBlocks: OnBlockBreakExternalEvents.getInstance().registerAllExternalEvents(); @@ -1006,10 +1127,13 @@ else if ( isTEExplosiveEnabled && } - long stop = System.nanoTime(); - debugInfo.append( " [" ).append( (stop - start) / 1000000d ).append( " ms]" ); - - Output.get().logDebug( DebugTarget.blockBreak, debugInfo.toString() ); + if ( debugInfo.length() > 0 ) { + + long stop = System.nanoTime(); + debugInfo.append( " [" ).append( (stop - start) / 1000000d ).append( " ms]" ); + + Output.get().logDebug( DebugTarget.blockBreak, debugInfo.toString() ); + } } @@ -1062,7 +1186,23 @@ protected void genericBlastUseEvent( BlastUseEvent e, boolean monitor, boolean b boolean autoManager ) { long start = System.nanoTime(); - + + if ( e.isCancelled() && !monitor ) { + // Check to see if the event should be ignored. + + SpigotBlock sBlock = new SpigotBlock( e.getBlockList().get( 0 ) ); + + Mine mine = findMine( e.getPlayer(), sBlock, e.getBlockList(), null ); + + MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); + + // If ignore all block events, then exit this function without logging anything: + if ( targetBlock.isIgnoreAllBlockEvents() ) { + return; + } + + } + // Register all external events such as mcMMO and EZBlocks: OnBlockBreakExternalEvents.getInstance().registerAllExternalEvents(); @@ -1211,11 +1351,13 @@ else if ( isCEBlockExplodeEnabled && } - long stop = System.nanoTime(); - debugInfo.append( " [" ).append( (stop - start) / 1000000d ).append( " ms]" ); - - Output.get().logDebug( DebugTarget.blockBreak, debugInfo.toString() ); - + if ( debugInfo.length() > 0 ) { + + long stop = System.nanoTime(); + debugInfo.append( " [" ).append( (stop - start) / 1000000d ).append( " ms]" ); + + Output.get().logDebug( DebugTarget.blockBreak, debugInfo.toString() ); + } } @@ -1236,6 +1378,22 @@ protected void genericExplosiveEvent( PEExplosionEvent e, boolean monitor, boole boolean autoManager ) { long start = System.nanoTime(); + + if ( e.isCancelled() && !monitor ) { + // Check to see if the event should be ignored. + + SpigotBlock sBlock = new SpigotBlock( e.getBlockBroken() ); + + Mine mine = findMine( e.getPlayer(), sBlock, e.getExplodedBlocks(), null ); + + MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); + + // If ignore all block events, then exit this function without logging anything: + if ( targetBlock.isIgnoreAllBlockEvents() ) { + return; + } + + } // Register all external events such as mcMMO and EZBlocks: OnBlockBreakExternalEvents.getInstance().registerAllExternalEvents(); @@ -1335,10 +1493,13 @@ else if ( isPEExplosiveEnabled && } - long stop = System.nanoTime(); - debugInfo.append( " [" ).append( (stop - start) / 1000000d ).append( " ms]" ); - - Output.get().logDebug( DebugTarget.blockBreak, debugInfo.toString() ); + if ( debugInfo.length() > 0 ) { + + long stop = System.nanoTime(); + debugInfo.append( " [" ).append( (stop - start) / 1000000d ).append( " ms]" ); + + Output.get().logDebug( DebugTarget.blockBreak, debugInfo.toString() ); + } } @@ -1347,6 +1508,22 @@ protected void genericExplosiveEvent( ExplosiveBlockBreakEvent e, boolean monito long start = System.nanoTime(); + if ( e.isCancelled() && !monitor ) { + // Check to see if the event should be ignored. + + SpigotBlock sBlock = new SpigotBlock( e.getBlock() ); + + Mine mine = findMine( e.getPlayer(), sBlock, e.getExplodedBlocks(), null ); + + MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); + + // If ignore all block events, then exit this function without logging anything: + if ( targetBlock.isIgnoreAllBlockEvents() ) { + return; + } + + } + // Register all external events such as mcMMO and EZBlocks: OnBlockBreakExternalEvents.getInstance().registerAllExternalEvents(); @@ -1357,8 +1534,6 @@ protected void genericExplosiveEvent( ExplosiveBlockBreakEvent e, boolean monito (e.isCancelled() ? "CANCELED " : ""), (monitor ? "MONITOR " : ""), (blockEventsOnly ? "BlockEventsOnly" : "" )) ); - - // NOTE that check for auto manager has happened prior to accessing this function. if ( !monitor && !e.isCancelled() || monitor ) { @@ -1376,9 +1551,17 @@ protected void genericExplosiveEvent( ExplosiveBlockBreakEvent e, boolean monito PrisonMinesBlockBreakEvent pmEvent = new PrisonMinesBlockBreakEvent( e.getBlock(), e.getPlayer(), sBlock, sPlayer, monitor, blockEventsOnly, eventType, triggered ); + + + // If this event is fired, but yet there are no exploded blocks, then do not set + // forceIfAirBlock to true so this event is skipped. + if ( e.getExplodedBlocks() != null && e.getExplodedBlocks().size() > 0 ) { + + pmEvent.setUnprocessedRawBlocks( e.getExplodedBlocks() ); + pmEvent.setForceIfAirBlock( e.isForceIfAirBlock() ); + } + - pmEvent.setUnprocessedRawBlocks( e.getExplodedBlocks() ); - pmEvent.setForceIfAirBlock( e.isForceIfAirBlock() ); // Warning: toolInHand really needs to be defined in the event if the source is a // Mine Bomb, otherwise auto features will detect the player is holding @@ -1404,7 +1587,9 @@ protected void genericExplosiveEvent( ExplosiveBlockBreakEvent e, boolean monito // now process all blocks (non-monitor): else if ( isPPrisonExplosiveBlockBreakEnabled && - ( pmEvent.getMine() != null || pmEvent.getMine() == null && !isBoolean( AutoFeatures.pickupLimitToMines )) ) { + ( pmEvent.getMine() != null || pmEvent.getMine() == null && + !isBoolean( AutoFeatures.pickupLimitToMines )) ) { + if ( pmEvent.getExplodedBlocks().size() > 0 ) { // String triggered = null; @@ -1453,10 +1638,13 @@ else if ( isPPrisonExplosiveBlockBreakEnabled && } - long stop = System.nanoTime(); - debugInfo.append( " [" ).append( (stop - start) / 1000000d ).append( " ms]" ); - - Output.get().logDebug( DebugTarget.blockBreak, debugInfo.toString() ); + if ( debugInfo.length() > 0 ) { + + long stop = System.nanoTime(); + debugInfo.append( " [" ).append( (stop - start) / 1000000d ).append( " ms]" ); + + Output.get().logDebug( DebugTarget.blockBreak, debugInfo.toString() ); + } } @@ -1753,6 +1941,14 @@ public void processBlockBreakage( PrisonMinesBlockBreakEvent pmEvent, StringBuil public boolean autosellPerBlockBreak( Player player ) { boolean enabled = false; + +// if (isBoolean(AutoFeatures.isAutoSellPerBlockBreakEnabled) || +// pmEvent.isForceAutoSell() ) { +// +// SellAllUtil.get().sellAllSell( player, itemStack, true, false, false ); +// } + + // This won't try to sell on every item stack, but assuming that sellall will hit on very block // break, then the odds of inventory being overflowed on one explosion would be more rare than anything if ( isBoolean( AutoFeatures.isAutoSellPerBlockBreakEnabled ) ) { From 114e7fc1c9aa105e83ae7ddf186072c894eb6000 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 19 Nov 2021 13:41:54 -0500 Subject: [PATCH 121/283] Bug fix with SellAll: bug in original logic where the delayed notification when initialized is losing the first amount. It now always adds the amount to the delayed queue. --- docs/changelog_v3.3.x.md | 4 ++++ .../prison/spigot/sellall/SellAllUtil.java | 20 ++++++++++--------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index d328ef743..8ce14c5d3 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.4 2021-11-19 +* **Bug fix with SellAll: bug in original logic where the delayed notification when initialized is losing the first amount.** +It now always adds the amount to the delayed queue. + + * **Autofeatures ignore certain events to improve performance and reduce logging entries when in debug mode.** Since there are multiple listeners on block break events, which monitor the same event, these changes are able to mark a specific block within the MineTargetPrisonBlock objects that will be able to pass along an "ignore" event status to the other listeners to short-circuit their processing. This is highly beneficial when using large mine bombs and the mine has blockEvents setup to perform explosions... which will help reduce a ton of "dead" events. diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java index b4936803f..3d7cec949 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java @@ -1483,9 +1483,9 @@ public boolean sellAllSell(Player p, boolean isUsingSign, boolean completelySile if (notifyPlayerEarningDelay && isAutoSellEarningNotificationDelayEnabled){ if (!isPlayerWaitingAutoSellNotification(p)){ addToAutoSellNotificationDelay(p); - } else { - addDelayedEarningAutoSellNotification(p, money); - } + } + + addDelayedEarningAutoSellNotification(p, money); } else if (notifyPlayerEarned){ Output.get().sendInfo(sPlayer, messages.getString(MessagesConfig.StringID.spigot_message_sellall_money_earned) + money); } @@ -1524,7 +1524,7 @@ public double sellAllSell(Player p, SpigotItemStack itemStack, double money = getSellMoney(p, itemStack); - if (money != 0){ + if (money != 0) { SpigotPlayer sPlayer = new SpigotPlayer(p); RankPlayer rankPlayer = PrisonRanks.getInstance().getPlayerManager().getPlayer(sPlayer.getUUID(), sPlayer.getName()); @@ -1539,13 +1539,15 @@ public double sellAllSell(Player p, SpigotItemStack itemStack, ){ if (!isPlayerWaitingAutoSellNotification(p)){ - // Force delayed notifications, even if delayed is disabled: + // Initialize && Force delayed notifications, even if delayed is disabled: autoSellEarningsNotificationWaiting.put(p, 0.00); Bukkit.getScheduler().scheduleSyncDelayedTask(SpigotPrison.getInstance(), () -> removeFromAutoSellDelayAndNotify(p), 20L * defaultAutoSellEarningNotificationDelay); - } else { - addDelayedEarningAutoSellNotification(p, money); - } - } else if (notifyPlayerEarned){ + + } + + addDelayedEarningAutoSellNotification(p, money); + } + else if (notifyPlayerEarned){ Output.get().sendInfo(sPlayer, messages.getString(MessagesConfig.StringID.spigot_message_sellall_money_earned) + money); } } From f605fb02a0b87e3aa354d09fd3e6040c86487ebb Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 19 Nov 2021 14:31:44 -0500 Subject: [PATCH 122/283] Remove the now obsolete auto features setting isAutoSellPerBlockBreaknliedEnabled. It is no longer needed since the auto features autosell per block break is now optimized and has no impact anymore. Improve the autosell integration in to the auto features for both the auto pickup and also the normal drops. Improved the debug logging to include a list of all blocks being sold, or dropped, and their quantity and value. Also the toal counts too. --- docs/changelog_v3.3.x.md | 5 + .../autofeatures/AutoFeaturesFileConfig.java | 2 +- .../autofeatures/AutoManagerFeatures.java | 107 ++++++++++++++---- .../spigot/block/OnBlockBreakEventCore.java | 70 ++++++------ 4 files changed, 128 insertions(+), 56 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 8ce14c5d3..9014d9dad 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,11 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.4 2021-11-19 +* **Remove the now obsolete auto features setting isAutoSellPerBlockBreaknliedEnabled.** +It is no longer needed since the auto features autosell per block break is now optimized and has no impact anymore. +Improve the autosell integration in to the auto features for both the auto pickup and also the normal drops. Improved the debug logging to include a list of all blocks being sold, or dropped, and their quantity and value. Also the total counts too. + + * **Bug fix with SellAll: bug in original logic where the delayed notification when initialized is losing the first amount.** It now always adds the amount to the delayed queue. diff --git a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java index 78257ff5b..b59ac68be 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java +++ b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java @@ -93,7 +93,7 @@ public enum AutoFeatures { hologramIfInventoryIsFull(general, false), isAutoSellPerBlockBreakEnabled(general, false), - isAutoSellPerBlockBreakInlinedEnabled(general, false), +// isAutoSellPerBlockBreakInlinedEnabled(general, false), permissions(options), diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java index e56f5397d..b50b8b66e 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java @@ -434,6 +434,8 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, if (drops != null && drops.size() > 0 ) { + debugInfo.append( "[autoPickupDrops]" ); + // Need better drop calculation that is not using the getDrops function. calculateSilkTouch( itemInHand, drops ); @@ -475,6 +477,8 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, } + double autosellTotal = 0; + for ( SpigotItemStack itemStack : drops ) { count += itemStack.getAmount(); @@ -483,31 +487,46 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, pmEvent.isForceAutoSell() ) { double amount = SellAllUtil.get().sellAllSell( player, itemStack, false, false, true ); - - debugInfo.append( "(sold: " + itemStack.getName() + " qty: " + itemStack.getAmount() + " amt: " + amount + ") "); + autosellTotal += amount; + + debugInfo.append( "(sold: " + itemStack.getName() + " qty: " + itemStack.getAmount() + " value: " + amount + ") "); // Set to zero quantity since they have all been sold. itemStack.setAmount( 0 ); } else { - HashMap extras = SpigotUtil.addItemToPlayerInventory( player, itemStack ); - - if ( extras.size() > 0 && autosellPerBlockBreak( player ) ) { + if ( Output.get().isDebug() ) { - // Try to add the extras back to the player's inventory if they had autosellPerBlockBrean enabled: - for ( SpigotItemStack extraItemStack : extras.values() ) { - - HashMap extras2 = SpigotUtil.addItemToPlayerInventory( player, extraItemStack ); - - autosellPerBlockBreak( player ); - - // If the remainder of the extras still as too much, then just drop them and move on: - dropExtra( extras2, player ); - } - extras.clear(); + // Just get the calculated value for the drops... do not sell: + double amount = SellAllUtil.get().sellAllSell( player, itemStack, true, false, false ); + autosellTotal += amount; + + debugInfo.append( "(adding: " + itemStack.getName() + " qty: " + itemStack.getAmount() + " value: " + amount + ") "); } + HashMap extras = SpigotUtil.addItemToPlayerInventory( player, itemStack ); + + + // Warning: The following is now obsolete since there is now a sellall function that will sell on a + // per SpigotItemStack so it eliminates a ton of overhead. It also supports thousands of + // items per stack. + +// if ( extras.size() > 0 && autosellPerBlockBreak( player ) ) { +// +// // Try to add the extras back to the player's inventory if they had autosellPerBlockBrean enabled: +// for ( SpigotItemStack extraItemStack : extras.values() ) { +// +// HashMap extras2 = SpigotUtil.addItemToPlayerInventory( player, extraItemStack ); +// +// autosellPerBlockBreak( player ); +// +// // If the remainder of the extras still as too much, then just drop them and move on: +// dropExtra( extras2, player ); +// } +// extras.clear(); +// } + dropExtra( extras, player ); // dropExtra( player.getInventory().addItem(itemStack), player, block ); } @@ -515,12 +534,18 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, } - if ( !isBoolean(AutoFeatures.isAutoSellPerBlockBreakEnabled) && - !pmEvent.isForceAutoSell() ) { + if ( count > 0 || autosellTotal > 0 ) { + + debugInfo.append( "[autoPickupDrops total: qty: " + count + " value: " + autosellTotal + ") "); - autosellPerBlockBreak( player ); } +// if ( !isBoolean(AutoFeatures.isAutoSellPerBlockBreakEnabled) && +// !pmEvent.isForceAutoSell() ) { +// +// autosellPerBlockBreak( player ); +// } + // autoPickupCleanup( player, itemInHand, count ); } return count; @@ -531,7 +556,7 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, - public int calculateNormalDrop( PrisonMinesBlockBreakEvent pmEvent ) { + public int calculateNormalDrop( PrisonMinesBlockBreakEvent pmEvent, StringBuilder debugInfo ) { // Count should be the total number of items that are to be "dropped". // So effectively it will be the sum of all bukkitDrops counts. @@ -552,6 +577,8 @@ public int calculateNormalDrop( PrisonMinesBlockBreakEvent pmEvent ) { if (drops != null && drops.size() > 0 ) { + + debugInfo.append( "[normalDrops]" ); // Need better drop calculation that is not using the getDrops function. short fortuneLevel = getFortune( pmEvent.getItemInHand() ); @@ -589,15 +616,53 @@ public int calculateNormalDrop( PrisonMinesBlockBreakEvent pmEvent ) { } + double autosellTotal = 0; + // Drop the items where the original block was located: for ( SpigotItemStack itemStack : drops ) { count += itemStack.getAmount(); - dropAtBlock( itemStack, pmEvent.getSpigotBlock() ); + if (isBoolean(AutoFeatures.isAutoSellPerBlockBreakEnabled) || + pmEvent.isForceAutoSell() ) { + + Player player = pmEvent.getPlayer(); + + double amount = SellAllUtil.get().sellAllSell( player, itemStack, false, false, true ); + autosellTotal += amount; + + debugInfo.append( "(sold: " + itemStack.getName() + " qty: " + itemStack.getAmount() + " value: " + amount + ") "); + + // Set to zero quantity since they have all been sold. + itemStack.setAmount( 0 ); + } + else { + + if ( Output.get().isDebug() ) { + + // Just get the calculated value for the drops... do not sell: + Player player = pmEvent.getPlayer(); + + double amount = SellAllUtil.get().sellAllSell( player, itemStack, true, false, false ); + autosellTotal += amount; + + debugInfo.append( "(adding: " + itemStack.getName() + " qty: " + itemStack.getAmount() + " value: " + amount + ") "); + } + + dropAtBlock( itemStack, pmEvent.getSpigotBlock() ); + } + + } + if ( count > 0 || autosellTotal > 0 ) { + + debugInfo.append( "[normalDrops total: qty: " + count + " value: " + autosellTotal + ") "); + + } + + // // Break the block and change it to air: // if ( !pmEvent.getSpigotBlock().isEmpty() ) { // diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index 5c4e4f165..9417c7d86 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -38,7 +38,6 @@ import tech.mcprison.prison.spigot.api.PrisonMinesBlockBreakEvent; import tech.mcprison.prison.spigot.autofeatures.AutoManagerBreakBlockTask; import tech.mcprison.prison.spigot.autofeatures.AutoManagerFeatures; -import tech.mcprison.prison.spigot.commands.PrisonSpigotSellAllCommands; import tech.mcprison.prison.spigot.compat.Compatibility; import tech.mcprison.prison.spigot.compat.SpigotCompatibility; import tech.mcprison.prison.spigot.game.SpigotPlayer; @@ -1756,7 +1755,7 @@ public void doActionBlockEventOnly( SpigotBlock spigotBlock, Mine mine, Player p public boolean doAction( PrisonMinesBlockBreakEvent pmEvent, StringBuilder debugInfo ) { AutoManagerFeatures aMan = SpigotPrison.getInstance().getAutoFeatures(); - int totalDrops = aMan.calculateNormalDrop( pmEvent ); + int totalDrops = aMan.calculateNormalDrop( pmEvent, debugInfo ); debugInfo.append( "(normalDrops totalDrops: " + totalDrops + ") "); @@ -1776,7 +1775,7 @@ public boolean applyDropsBlockBreakage( PrisonMinesBlockBreakEvent pmEvent, int processBlockBreakage( pmEvent, debugInfo ); - autosellPerBlockBreak( pmEvent.getPlayer() ); +// autosellPerBlockBreak( pmEvent.getPlayer() ); // if ( pmEvent.getMine() != null ) { // checkZeroBlockReset( pmEvent.getMine() ); @@ -1938,39 +1937,42 @@ public void processBlockBreakage( PrisonMinesBlockBreakEvent pmEvent, StringBuil - public boolean autosellPerBlockBreak( Player player ) { - boolean enabled = false; - - -// if (isBoolean(AutoFeatures.isAutoSellPerBlockBreakEnabled) || -// pmEvent.isForceAutoSell() ) { + // Warning: The following is now obsolete since there is now a sellall function that will sell on a + // per SpigotItemStack so it eliminates a ton of overhead. It also supports thousands of + // items per stack. +// public boolean autosellPerBlockBreak( Player player ) { +// boolean enabled = false; +// +// +//// if (isBoolean(AutoFeatures.isAutoSellPerBlockBreakEnabled) || +//// pmEvent.isForceAutoSell() ) { +//// +//// SellAllUtil.get().sellAllSell( player, itemStack, true, false, false ); +//// } +// +// +// // This won't try to sell on every item stack, but assuming that sellall will hit on very block +// // break, then the odds of inventory being overflowed on one explosion would be more rare than anything +// if ( isBoolean( AutoFeatures.isAutoSellPerBlockBreakEnabled ) ) { // -// SellAllUtil.get().sellAllSell( player, itemStack, true, false, false ); +// enabled = true; +// +// // Run sell all +// if ( isBoolean( AutoFeatures.isAutoSellPerBlockBreakInlinedEnabled ) ) { +// // run sellall inline with the block break event: +// if (PrisonSpigotSellAllCommands.get() != null) { +// PrisonSpigotSellAllCommands.get().sellAllSellWithDelayCommand(new SpigotPlayer(player)); +// } +// } +// else { +// // Submit sellall to run in the future (0 ticks in the future): +// String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "sellall sell silent" ); +// Bukkit.dispatchCommand(player, registeredCmd); +// } // } - - - // This won't try to sell on every item stack, but assuming that sellall will hit on very block - // break, then the odds of inventory being overflowed on one explosion would be more rare than anything - if ( isBoolean( AutoFeatures.isAutoSellPerBlockBreakEnabled ) ) { - - enabled = true; - - // Run sell all - if ( isBoolean( AutoFeatures.isAutoSellPerBlockBreakInlinedEnabled ) ) { - // run sellall inline with the block break event: - if (PrisonSpigotSellAllCommands.get() != null) { - PrisonSpigotSellAllCommands.get().sellAllSellWithDelayCommand(new SpigotPlayer(player)); - } - } - else { - // Submit sellall to run in the future (0 ticks in the future): - String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "sellall sell silent" ); - Bukkit.dispatchCommand(player, registeredCmd); - } - } - - return enabled; - } +// +// return enabled; +// } public void checkZeroBlockReset( Mine mine ) { From b4c8d616562f3973f6dafee90087d32cf2889c36 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 19 Nov 2021 17:44:09 -0500 Subject: [PATCH 123/283] Relased the v3.2.11-alpha.5 --- docs/changelog_v3.3.x.md | 7 ++++++- gradle.properties | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 9014d9dad..1330e7a21 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,12 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.4 2021-11-19 +# 3.2.11-alpha.5 2021-11-19 + + +* **3.2.11-alpha.5 2021-11-19** + +Post the alpha.5 release. * **Remove the now obsolete auto features setting isAutoSellPerBlockBreaknliedEnabled.** diff --git a/gradle.properties b/gradle.properties index 58bae8e7e..02950d282 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ ## # This is actually the "correct" place to define the version for the project. ## # Used within build.gradle with ${project.version}. ## # Can be overridden on the command line: gradle -Pversion=3.2.1-alpha.3 -version=3.2.11-alpha.4 +version=3.2.11-alpha.5 #version=3.2.8.2 #version=3.3.0-alpha.6 From 975dee79140aa0b5d3febb6312c0750fb12d0522 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 19 Nov 2021 17:47:58 -0500 Subject: [PATCH 124/283] Changes to how the event listeners are setup. Used to be that all three would be set if autopickup was enabled, but now only two will be set... monitor, and then either autopickup or manual drops. This should improve performance since prison will be processing 1/3 less events. --- docs/changelog_v3.3.x.md | 6 +++ .../events/AutoManagerBlockBreakEvents.java | 33 +++++++++-------- .../events/AutoManagerCrazyEnchants.java | 16 ++++---- .../events/AutoManagerPrisonEnchants.java | 27 ++++++++------ ...nagerPrisonsExplosiveBlockBreakEvents.java | 27 ++++++++------ .../events/AutoManagerTokenEnchant.java | 27 ++++++++------ .../events/AutoManagerZenchantments.java | 37 ++++++++++--------- 7 files changed, 98 insertions(+), 75 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 1330e7a21..7d1aa09f2 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,12 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.5 2021-11-19 + +* **Changes to how the event listeners are setup: reduced by 1/3rd.** +Used to be that all three would be set if autopickup was enabled, but now only two will be set... monitor, and then either autopickup or manual drops. +This should improve performance since prison will be processing 1/3 less events. + + * **3.2.11-alpha.5 2021-11-19** Post the alpha.5 release. diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerBlockBreakEvents.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerBlockBreakEvents.java index 6cfe0e235..15f1b2f5f 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerBlockBreakEvents.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerBlockBreakEvents.java @@ -130,22 +130,25 @@ public void execute(Listener l, Event e) { prison); prison.getRegisteredBlockListeners().add( autoManagerlListener ); } - - OnBlockBreakEventListenerNormal normalListener = - new OnBlockBreakEventListenerNormal(); - - pm.registerEvent(BlockBreakEvent.class, normalListener, ePriority, - new EventExecutor() { - public void execute(Listener l, Event e) { - if ( l instanceof OnBlockBreakEventListenerNormal && - e instanceof BlockBreakEvent ) { - ((OnBlockBreakEventListenerNormal)l) - .onBlockBreak((BlockBreakEvent)e); + else if ( isBoolean( AutoFeatures.normalDrop ) ) { + + OnBlockBreakEventListenerNormal normalListener = + new OnBlockBreakEventListenerNormal(); + + pm.registerEvent(BlockBreakEvent.class, normalListener, ePriority, + new EventExecutor() { + public void execute(Listener l, Event e) { + if ( l instanceof OnBlockBreakEventListenerNormal && + e instanceof BlockBreakEvent ) { + ((OnBlockBreakEventListenerNormal)l) + .onBlockBreak((BlockBreakEvent)e); + } } - } - }, - prison); - prison.getRegisteredBlockListeners().add( normalListener ); + }, + prison); + prison.getRegisteredBlockListeners().add( normalListener ); + } + } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerCrazyEnchants.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerCrazyEnchants.java index fdf09e653..edad5bf36 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerCrazyEnchants.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerCrazyEnchants.java @@ -129,16 +129,18 @@ public void execute(Listener l, Event e) { prison); prison.getRegisteredBlockListeners().add( normalListener ); } - - pm.registerEvent(BlastUseEvent.class, normalListenerMonitor, EventPriority.MONITOR, - new EventExecutor() { + else if ( isBoolean( AutoFeatures.normalDrop ) ) { + + pm.registerEvent(BlastUseEvent.class, normalListenerMonitor, EventPriority.MONITOR, + new EventExecutor() { public void execute(Listener l, Event e) { ((OnBlockBreakBlastUseEventListenerMonitor)l) .onCrazyEnchantsBlockExplode((BlastUseEvent)e); - } - }, - prison); - prison.getRegisteredBlockListeners().add( normalListenerMonitor ); + } + }, + prison); + prison.getRegisteredBlockListeners().add( normalListenerMonitor ); + } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonEnchants.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonEnchants.java index cee4721d2..386127dbd 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonEnchants.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonEnchants.java @@ -120,19 +120,22 @@ public void execute(Listener l, Event e) { prison); prison.getRegisteredBlockListeners().add( autoManagerlListener ); } + else if ( isBoolean( AutoFeatures.normalDrop ) ) { + + OnBlockBreakPEExplosiveEventListener normalListener = + new OnBlockBreakPEExplosiveEventListener(); + + pm.registerEvent(PEExplosionEvent.class, normalListener, ePriority, + new EventExecutor() { + public void execute(Listener l, Event e) { + ((OnBlockBreakPEExplosiveEventListener)l) + .onPrisonEnchantsExplosiveEvent((PEExplosionEvent)e); + } + }, + prison); + prison.getRegisteredBlockListeners().add( normalListener ); + } - OnBlockBreakPEExplosiveEventListener normalListener = - new OnBlockBreakPEExplosiveEventListener(); - - pm.registerEvent(PEExplosionEvent.class, normalListener, ePriority, - new EventExecutor() { - public void execute(Listener l, Event e) { - ((OnBlockBreakPEExplosiveEventListener)l) - .onPrisonEnchantsExplosiveEvent((PEExplosionEvent)e); - } - }, - prison); - prison.getRegisteredBlockListeners().add( normalListener ); } pm.registerEvent(PEExplosionEvent.class, normalListenerMonitor, EventPriority.MONITOR, diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonsExplosiveBlockBreakEvents.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonsExplosiveBlockBreakEvents.java index a612ee66d..25ef43e4e 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonsExplosiveBlockBreakEvents.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerPrisonsExplosiveBlockBreakEvents.java @@ -116,19 +116,22 @@ public void execute(Listener l, Event e) { prison); prison.getRegisteredBlockListeners().add( autoManagerlListener ); } + else if ( isBoolean( AutoFeatures.normalDrop ) ) { + + OnBlockBreakExplosiveBlockBreakEventListener normalListener = + new OnBlockBreakExplosiveBlockBreakEventListener(); + + pm.registerEvent(ExplosiveBlockBreakEvent.class, normalListener, ePriority, + new EventExecutor() { + public void execute(Listener l, Event e) { + ((OnBlockBreakExplosiveBlockBreakEventListener)l) + .onPrisonExplosiveBlockBreakEvent((ExplosiveBlockBreakEvent)e); + } + }, + prison); + prison.getRegisteredBlockListeners().add( normalListener ); + } - OnBlockBreakExplosiveBlockBreakEventListener normalListener = - new OnBlockBreakExplosiveBlockBreakEventListener(); - - pm.registerEvent(ExplosiveBlockBreakEvent.class, normalListener, ePriority, - new EventExecutor() { - public void execute(Listener l, Event e) { - ((OnBlockBreakExplosiveBlockBreakEventListener)l) - .onPrisonExplosiveBlockBreakEvent((ExplosiveBlockBreakEvent)e); - } - }, - prison); - prison.getRegisteredBlockListeners().add( normalListener ); } pm.registerEvent(ExplosiveBlockBreakEvent.class, normalListenerMonitor, EventPriority.MONITOR, diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerTokenEnchant.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerTokenEnchant.java index 566ed6785..fbc311445 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerTokenEnchant.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerTokenEnchant.java @@ -117,19 +117,22 @@ public void execute(Listener l, Event e) { prison); prison.getRegisteredBlockListeners().add( autoManagerlListener ); } + else if ( isBoolean( AutoFeatures.normalDrop ) ) { + + OnBlockBreakEventTokenEnchantEventListener normalListener = + new OnBlockBreakEventTokenEnchantEventListener(); + + pm.registerEvent(TEBlockExplodeEvent.class, normalListener, ePriority, + new EventExecutor() { + public void execute(Listener l, Event e) { + ((OnBlockBreakEventTokenEnchantEventListener)l) + .onTEBlockExplode((TEBlockExplodeEvent)e); + } + }, + prison); + prison.getRegisteredBlockListeners().add( normalListener ); + } - OnBlockBreakEventTokenEnchantEventListener normalListener = - new OnBlockBreakEventTokenEnchantEventListener(); - - pm.registerEvent(TEBlockExplodeEvent.class, normalListener, ePriority, - new EventExecutor() { - public void execute(Listener l, Event e) { - ((OnBlockBreakEventTokenEnchantEventListener)l) - .onTEBlockExplode((TEBlockExplodeEvent)e); - } - }, - prison); - prison.getRegisteredBlockListeners().add( normalListener ); } pm.registerEvent(TEBlockExplodeEvent.class, normalListenerMonitor, EventPriority.MONITOR, diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerZenchantments.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerZenchantments.java index 9301fb23d..d85005097 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerZenchantments.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerZenchantments.java @@ -122,24 +122,27 @@ public void execute(Listener l, Event e) { prison); prison.getRegisteredBlockListeners().add( autoManagerlListener ); } - - OnBlockBreakBlockShredEventListener normalListener = - new OnBlockBreakBlockShredEventListener(); - - pm.registerEvent(BlockShredEvent.class, normalListener, ePriority, - new EventExecutor() { - public void execute(Listener l, Event e) { - if ( l instanceof OnBlockBreakBlockShredEventListenerMonitor && - e instanceof BlockShredEvent ) { - OnBlockBreakBlockShredEventListenerMonitor lmon = - (OnBlockBreakBlockShredEventListenerMonitor) l; - BlockShredEvent event = (BlockShredEvent) e; - lmon.onBlockShredBreakMonitor( event ); + else if ( isBoolean( AutoFeatures.normalDrop ) ) { + + OnBlockBreakBlockShredEventListener normalListener = + new OnBlockBreakBlockShredEventListener(); + + pm.registerEvent(BlockShredEvent.class, normalListener, ePriority, + new EventExecutor() { + public void execute(Listener l, Event e) { + if ( l instanceof OnBlockBreakBlockShredEventListenerMonitor && + e instanceof BlockShredEvent ) { + OnBlockBreakBlockShredEventListenerMonitor lmon = + (OnBlockBreakBlockShredEventListenerMonitor) l; + BlockShredEvent event = (BlockShredEvent) e; + lmon.onBlockShredBreakMonitor( event ); + } } - } - }, - prison); - prison.getRegisteredBlockListeners().add( normalListener ); + }, + prison); + prison.getRegisteredBlockListeners().add( normalListener ); + } + } pm.registerEvent(BlockShredEvent.class, normalListenerMonitor, EventPriority.MONITOR, From fe1766055f2689d493077b80deb6ada65a777468 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 21 Nov 2021 14:11:03 -0500 Subject: [PATCH 125/283] Update on how prison manages the tracking of block breaks and earnings when auto features has autosell enabled. --- docs/changelog_v3.3.x.md | 6 +++- .../mcprison/prison/cache/PlayerCache.java | 20 ++++++++---- .../cache/PlayerCacheCheckTimersTask.java | 2 +- .../prison/cache/PlayerCachePlayerData.java | 13 ++++++-- .../internal/block/MineTargetPrisonBlock.java | 11 +++---- .../mcprison/prison/mines/data/MineData.java | 5 ++- .../api/PrisonMinesBlockBreakEvent.java | 19 ++++++++++++ .../autofeatures/AutoManagerFeatures.java | 31 +++++++++++++++++++ .../spigot/block/OnBlockBreakEventCore.java | 5 +-- 9 files changed, 91 insertions(+), 21 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 7d1aa09f2..5d79e7a76 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,10 +13,14 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.5 2021-11-19 +# 3.2.11-alpha.5 2021-11-21 + +* **Update on how prison manages the tracking of block breaks and earnings when auto features has autosell enabled.** + + * **Changes to how the event listeners are setup: reduced by 1/3rd.** Used to be that all three would be set if autopickup was enabled, but now only two will be set... monitor, and then either autopickup or manual drops. This should improve performance since prison will be processing 1/3 less events. diff --git a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCache.java b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCache.java index 67af85a63..61a9369e2 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCache.java +++ b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCache.java @@ -9,7 +9,6 @@ import java.util.TreeSet; import tech.mcprison.prison.internal.Player; -import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.internal.block.PrisonBlockStatusData; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.tasks.PrisonTaskSubmitter; @@ -353,20 +352,23 @@ public PlayerCacheRunnable submitCacheUpdatePlayerStats() { public void addPlayerBlocks( Player player, String mine, PrisonBlockStatusData block, int quantity ) { - addPlayerBlocks( player, mine, (PrisonBlock) block, quantity ); + addPlayerBlocks( player, mine, block.getBlockName(), quantity ); } - public void addPlayerBlocks( Player player, String mine, PrisonBlock block, int quantity ) { +// public void addPlayerBlocks( Player player, String mine, PrisonBlock block, int quantity ) { +// addPlayerBlocks( player, mine, block.getBlockName(), quantity ); +// } + public void addPlayerBlocks( Player player, String mine, String blockName, int quantity ) { PlayerCachePlayerData playerData = getPlayer( player ); // Output.get().logInfo( "### addPlayerBlock: mine= " + (mine == null ? "null" : mine) + // " block= " + (block == null ? "null" : block.getBlockName()) + " qty= " + quantity + " playerData= " + // (playerData == null ? "null" : playerData.toString() )); - + // if ( playerData != null && playerData.getBlocksTotal() % 20 == 0 ) { // Output.get().logInfo( "#### PlayerCache: " + playerData.toString() ); // } - playerData.addBlock( mine, block.getBlockName(), quantity ); + playerData.addBlock( mine, blockName, quantity ); } /** @@ -379,7 +381,13 @@ public void addPlayerBlocks( Player player, String mine, PrisonBlock block, int public void addPlayerEarnings( Player player, double earnings ) { PlayerCachePlayerData playerData = getPlayer( player ); - playerData.addEarnings( earnings ); + String mineName = null; + playerData.addEarnings( earnings, mineName ); + } + public void addPlayerEarnings( Player player, double earnings, String mineName ) { + PlayerCachePlayerData playerData = getPlayer( player ); + + playerData.addEarnings( earnings, mineName ); } public double getPlayerEarningsPerMinute( Player player ) { double earningsPerMinute = 0; diff --git a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheCheckTimersTask.java b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheCheckTimersTask.java index aa23b4667..7ace3b302 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheCheckTimersTask.java +++ b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheCheckTimersTask.java @@ -85,7 +85,7 @@ private void processCache() { // By adding a zero earnings, this will force the earnings "cache" to // progress, even if the player stopped mining. - playerData.addEarnings( 0 ); + playerData.addEarnings( 0, null ); } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java index 8297da749..761c19b64 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java @@ -348,7 +348,7 @@ private void addTimeToMine( String mine, long miningDuration ) * * @param earnings */ - public void addEarnings( double earnings ) { + public void addEarnings( double earnings, String mineName ) { SimpleDateFormat dateFmt = new SimpleDateFormat("yyyy-MM-dd_hh:mm"); String key = dateFmt.format( new Date() ); @@ -363,13 +363,20 @@ public void addEarnings( double earnings ) { earningsPerMinute.firstEntry().getKey() ); } + if ( mineName != null && sessionType != SessionType.mining ) { + sessionType = SessionType.mining; + } + if ( mineName == null && getLastMine() != null ) { + mineName = getLastMine(); + } // If earnings are within the session timeout for mining, then add the // earnings to the moneyByMine: - if ( sessionType == SessionType.mining && getLastMine() != null ) { + if ( sessionType == SessionType.mining && mineName != null ) { long duration = System.currentTimeMillis() - sessionTimingLastCheck; if ( duration < SESSION_TIMEOUT_MINING_MS ) { - addEarningsByMine( getLastMine(), earnings ); + + addEarningsByMine( mineName, earnings ); } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetPrisonBlock.java b/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetPrisonBlock.java index b3a7c3d5c..06f301489 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetPrisonBlock.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetPrisonBlock.java @@ -23,14 +23,11 @@ public class MineTargetPrisonBlock private boolean ignoreAllBlockEvents = false; - protected MineTargetPrisonBlock( World world, int x, int y, int z, boolean isEdge ) { - - this.blockKey = new MineTargetBlockKey( world, x, y, z ); - } - - public MineTargetPrisonBlock( PrisonBlockStatusData prisonBlock, World world, + public MineTargetPrisonBlock( + PrisonBlockStatusData prisonBlock, + World world, int x, int y, int z, boolean isEdge ) { - this( world, x, y, z, isEdge ); + this.blockKey = new MineTargetBlockKey( world, x, y, z ); this.prisonBlock = prisonBlock; diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java index a6ad920c9..dc8a77cc1 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java @@ -696,7 +696,10 @@ public boolean incrementBlockMiningCount( MineTargetPrisonBlock targetPrisonBloc incrementBlockBreakCount(); incrementTotalBlocksMined(); - targetPrisonBlock.getPrisonBlock().incrementMiningBlockCount(); + if ( targetPrisonBlock.getPrisonBlock() != null ) { + + targetPrisonBlock.getPrisonBlock().incrementMiningBlockCount(); + } results = true; } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockBreakEvent.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockBreakEvent.java index 25d460c53..d04ff38d0 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockBreakEvent.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockBreakEvent.java @@ -2,6 +2,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.TreeMap; import org.bukkit.block.Block; import org.bukkit.entity.Player; @@ -211,6 +212,24 @@ public MineTargetPrisonBlock getOriginalTargetBlock( Block bukkitBlock ) { return getOriginalTargetBlock( spigotBlock ); } + + public TreeMap getTargetBlockCounts() { + TreeMap results = new TreeMap<>(); + + if ( getTargetBlock() != null ) { + results.put( getTargetBlock().getPrisonBlock().getBlockName(), 1 ); + } + + for ( MineTargetPrisonBlock targetBlock : getTargetExplodedBlocks() ) + { + String blockName = targetBlock.getPrisonBlock().getBlockName(); + int count = 1 + ( results.containsKey( blockName ) ? results.get( blockName ) : 0) ; + results.put( blockName, count ); + } + + return results; + } + public Mine getMine() { return mine; } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java index b50b8b66e..767fe23c3 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java @@ -4,6 +4,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map.Entry; import java.util.Random; import java.util.Set; import java.util.TreeMap; @@ -22,6 +23,7 @@ import com.cryptomorin.xseries.XMaterial; import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; +import tech.mcprison.prison.cache.PlayerCache; import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.output.Output; @@ -476,6 +478,18 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, normalDropBlock( drops ); } + String mineName = pmEvent.getMine() == null ? null : pmEvent.getMine().getName(); + + // PlayerCache log block breaks: + TreeMap targetBlockCounts = pmEvent.getTargetBlockCounts(); + for ( Entry targetBlockCount : targetBlockCounts.entrySet() ) + { + + PlayerCache.getInstance().addPlayerBlocks( pmEvent.getSpigotPlayer(), mineName, + targetBlockCount.getKey(), targetBlockCount.getValue().intValue() ); + } + + double autosellTotal = 0; @@ -483,12 +497,16 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, count += itemStack.getAmount(); + if (isBoolean(AutoFeatures.isAutoSellPerBlockBreakEnabled) || pmEvent.isForceAutoSell() ) { double amount = SellAllUtil.get().sellAllSell( player, itemStack, false, false, true ); autosellTotal += amount; + PlayerCache.getInstance().addPlayerEarnings( pmEvent.getSpigotPlayer(), + amount, mineName ); + debugInfo.append( "(sold: " + itemStack.getName() + " qty: " + itemStack.getAmount() + " value: " + amount + ") "); // Set to zero quantity since they have all been sold. @@ -616,6 +634,19 @@ public int calculateNormalDrop( PrisonMinesBlockBreakEvent pmEvent, StringBuilde } + String mineName = pmEvent.getMine() == null ? null : pmEvent.getMine().getName(); + + // PlayerCache log block breaks: + TreeMap targetBlockCounts = pmEvent.getTargetBlockCounts(); + for ( Entry targetBlockCount : targetBlockCounts.entrySet() ) + { + + PlayerCache.getInstance().addPlayerBlocks( pmEvent.getSpigotPlayer(), mineName, + targetBlockCount.getKey(), targetBlockCount.getValue().intValue() ); + } + + + double autosellTotal = 0; // Drop the items where the original block was located: diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index 9417c7d86..063e709e5 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -1999,8 +1999,9 @@ private void applyBlockFinalizations( PrisonMinesBlockBreakEvent pmEvent, MineTa // then have the player counts be incremented. if ( mine.incrementBlockMiningCount( targetBlock ) ) { - PlayerCache.getInstance().addPlayerBlocks( pmEvent.getSpigotPlayer(), - mine.getName(), targetBlock.getPrisonBlock(), 1 ); + // Now in AutoManagerFeatures.autoPickup and calculateNormalDrop: +// PlayerCache.getInstance().addPlayerBlocks( pmEvent.getSpigotPlayer(), +// mine.getName(), targetBlock.getPrisonBlock(), 1 ); } From 59413fd69a259b0302f5c0f8e4a29d0554b900bb Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 21 Nov 2021 14:15:50 -0500 Subject: [PATCH 126/283] Capture an error within prison's Output class when trying to log content that has an UnknownFormatConversionException error. This happens when there is a problem with text formatting characters that conflict with Java's formating class. This tries to log the error with better details so it can be fixed and resolved where the error is happening. --- docs/changelog_v3.3.x.md | 2 ++ .../tech/mcprison/prison/output/Output.java | 30 ++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 5d79e7a76..32995ede6 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,8 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.5 2021-11-21 +* **Capture an error within prison's Output class when trying to log content that has an UnknownFormatConversionException error.** +This happens when there is a problem with text formatting characters that conflict with Java's formating class. This tries to log the error with better details so it can be fixed and resolved where the error is happening. This does not "fix" the problem, but just better reports it so it can be identified and fixed. * **Update on how prison manages the tracking of block breaks and earnings when auto features has autosell enabled.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/output/Output.java b/prison-core/src/main/java/tech/mcprison/prison/output/Output.java index 7dff57afb..7a6a79c9b 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/output/Output.java +++ b/prison-core/src/main/java/tech/mcprison/prison/output/Output.java @@ -23,6 +23,7 @@ import java.util.MissingFormatArgumentException; import java.util.Set; import java.util.TreeSet; +import java.util.UnknownFormatConversionException; import tech.mcprison.prison.Prison; import tech.mcprison.prison.internal.CommandSender; @@ -205,7 +206,14 @@ public void log(String message, LogLevel level, Object... args) { // can be identified along with the reasons. errorMessage = "Prison: (Sending to System.err due to Output.log Logger failure):"; } - System.err.println( errorMessage + " " + message ); + + StringBuilder sb = new StringBuilder(); + for ( Object arg : args ) { + sb.append( "[" ).append( arg ).append( "] " ); + } + + System.err.println( errorMessage + " message: [" + message + + "] params: " + sb.toString() ); } else { try { Prison.get().getPlatform().log( @@ -229,6 +237,26 @@ public void log(String message, LogLevel level, Object... args) { getLogColorCode(LogLevel.ERROR) + errorMessage ); } + catch ( UnknownFormatConversionException e) + { + StringBuilder sb = new StringBuilder(); + + for ( Object arg : args ) { + sb.append( "[" ).append( arg ).append( "] " ); + } + + String errorMessage = "Error with Java conversion format (eg %s): " + + " LogLevel: " + level.name() + + " message: [" + message + "] params: " + sb.toString() + + " error: " + e.getMessage(); + + Prison.get().getPlatform().logCore( + prefixTemplatePrison + " " + + getLogColorCode(LogLevel.ERROR) + + errorMessage ); + + e.printStackTrace(); + } } } From 65202119eaca7a9bd93eddf8b239ad3f73da56f3 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 21 Nov 2021 14:20:18 -0500 Subject: [PATCH 127/283] New feature which lists all of the Player Cache stats in the command `/ranks player`. This includes stats for block breaks, time spent in mines, and earnings per mine. --- docs/changelog_v3.3.x.md | 3 + .../prison/ranks/commands/RanksCommands.java | 265 +++++++++++++++++- 2 files changed, 259 insertions(+), 9 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 32995ede6..c7ad18d82 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.5 2021-11-21 +* **New feature which lists all of the Player Cache stats in the command `/ranks player`. This includes stats for block breaks, time spent in mines, and earnings per mine.** + + * **Capture an error within prison's Output class when trying to log content that has an UnknownFormatConversionException error.** This happens when there is a problem with text formatting characters that conflict with Java's formating class. This tries to log the error with better details so it can be fixed and resolved where the error is happening. This does not "fix" the problem, but just better reports it so it can be identified and fixed. diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java index 173d30d08..345c179ca 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java @@ -1,18 +1,23 @@ package tech.mcprison.prison.ranks.commands; import java.text.DecimalFormat; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; +import java.util.Date; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.TreeMap; import tech.mcprison.prison.Prison; import tech.mcprison.prison.PrisonAPI; import tech.mcprison.prison.PrisonCommand; import tech.mcprison.prison.autofeatures.AutoFeaturesWrapper; +import tech.mcprison.prison.cache.PlayerCache; +import tech.mcprison.prison.cache.PlayerCachePlayerData; import tech.mcprison.prison.chat.FancyMessage; import tech.mcprison.prison.commands.Arg; import tech.mcprison.prison.commands.Command; @@ -29,8 +34,10 @@ import tech.mcprison.prison.output.BulletedListComponent; import tech.mcprison.prison.output.ChatDisplay; import tech.mcprison.prison.output.FancyMessageComponent; +import tech.mcprison.prison.output.LogLevel; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.output.RowComponent; +import tech.mcprison.prison.placeholders.PlaceholdersUtil; import tech.mcprison.prison.ranks.PrisonRanks; import tech.mcprison.prison.ranks.data.PlayerRank; import tech.mcprison.prison.ranks.data.PlayerRankRefreshTask; @@ -1417,21 +1424,29 @@ public void rankPlayer(CommandSender sender, return; } + List msgs = new ArrayList<>(); + + PlayerManager pm = PrisonRanks.getInstance().getPlayerManager(); RankPlayer rankPlayer = pm.getPlayer(player.getUUID(), player.getName()); - String msg1 = String.format( "&c%s:", rankPlayer.getName() ); - sendToPlayerAndConsole( sender, msg1 ); + String msg1 = String.format( "&7Player Stats for&8: &c%s: ", rankPlayer.getName() ); + msgs.add( msg1 ); +// sendToPlayerAndConsole( sender, msg1 ); DecimalFormat fFmt = new DecimalFormat("0.0000"); String msg2 = String.format( " &7Rank Cost Multiplier: &f", fFmt.format( rankPlayer.getSellAllMultiplier() )); - sendToPlayerAndConsole( sender, msg2 ); + msgs.add( msg2 ); +// sendToPlayerAndConsole( sender, msg2 ); if ( rankPlayer != null ) { DecimalFormat dFmt = new DecimalFormat("#,##0.00"); + DecimalFormat iFmt = new DecimalFormat("#,##0"); + + SimpleDateFormat sdFmt = new SimpleDateFormat( "HH:mm:ss" ); // Collect all currencies in the default ladder: Set currencies = new LinkedHashSet<>(); @@ -1475,7 +1490,8 @@ public void rankPlayer(CommandSender sender, } } - sendToPlayerAndConsole( sender, messageRank ); + msgs.add( messageRank ); +// sendToPlayerAndConsole( sender, messageRank ); } // Print out the player's balances: @@ -1483,13 +1499,16 @@ public void rankPlayer(CommandSender sender, // The default currency first: double balance = rankPlayer.getBalance(); String message = ranksPlayerBalanceDefaultMsg( player.getName(), dFmt.format( balance ) ); - sendToPlayerAndConsole( sender, message ); + msgs.add( message ); +// sendToPlayerAndConsole( sender, message ); + for ( String currency : currencies ) { double balanceCurrency = rankPlayer.getBalance( currency ); String messageCurrency = ranksPlayerBalanceOthersMsg( player.getName(), dFmt.format( balanceCurrency ), currency ); - sendToPlayerAndConsole( sender, messageCurrency ); + msgs.add( messageCurrency ); +// sendToPlayerAndConsole( sender, messageCurrency ); } @@ -1502,7 +1521,8 @@ public void rankPlayer(CommandSender sender, if ( !isOnline ) { String msgOffline = ranksPlayerPermsOfflineMsg(); - sendToPlayerAndConsole( sender, msgOffline ); + msgs.add( msgOffline ); +// sendToPlayerAndConsole( sender, msgOffline ); } double sellallMultiplier = player.getSellAllMultiplier(); @@ -1511,10 +1531,92 @@ public void rankPlayer(CommandSender sender, String messageSellallMultiplier = ranksPlayerSellallMultiplierMsg( pFmt.format( sellallMultiplier ), (!isOnline ? " " + messageNotAccurrate : "") ); - sendToPlayerAndConsole( sender, messageSellallMultiplier ); + msgs.add( messageSellallMultiplier ); +// sendToPlayerAndConsole( sender, messageSellallMultiplier ); + msgs.add( "" ); + + // Get the cachedPlayer: + PlayerCachePlayerData cPlayer = PlayerCache.getInstance().getOnlinePlayer( rankPlayer ); + + if ( cPlayer != null ) { + + msgs.add( "PlayerCache Information:" ); + + // Print all earnings for all mines: + msgs.add( String.format( + " Earnings By Mine: &2Avg Earnings per min: &3%s", + dFmt.format( cPlayer.getAverageEarningsPerMinute() )) ); + + formatTreeMapStats(cPlayer.getEarningsByMine(), msgs, dFmt, iFmt, 5 ); + + msgs.add( String.format( + " &7Timings By Mine&8: &2Online&8: &3%s &2Mining&8: &3%s", + formatTimeMs( cPlayer.getOnlineTimeTotal() ), + formatTimeMs( cPlayer.getOnlineMiningTimeTotal()) ) + ); + + formatTreeMapStats(cPlayer.getTimeByMine(), msgs, dFmt, iFmt, 5 ); + + + // Print all earnings for all mines: + String totalBlocks = PlaceholdersUtil.formattedKmbtSISize( + cPlayer.getBlocksTotal(), dFmt, " &9" ); + msgs.add( String.format( + " &7Blocks By Mine&8: &2Blocks Total&8: &3%s", + totalBlocks) ); + formatTreeMapStats(cPlayer.getBlocksByMine(), msgs, dFmt, iFmt, 5 ); + + + msgs.add( " &7Blocks By Type&8:" ); + formatTreeMapStats(cPlayer.getBlocksByType(), msgs, dFmt, iFmt, 3 ); + + +// Set keysEarnings = cPlayer.getEarningsByMine().keySet(); +// +// int count = 0; +// StringBuilder sbErn = new StringBuilder(); +// for ( String earningKey : keysEarnings ) +// { +// Double mineEarnings = cPlayer.getEarningsByMine().get( earningKey ); +// +// String earnings = PlaceholdersUtil.formattedKmbtSISize( mineEarnings, dFmt, " " ); +// +// sbErn.append( String.format( "%s %s ", earningKey, earnings ) ); +// +// if ( count++ % 5 == 0 ) { +// msgs.add( String.format( +// " " + sbErn.toString() ) ); +// sbErn.setLength( 0 ); +// +// } +// } +// +// if ( sbErn.length() > 0 ) { +// +// msgs.add( String.format( +// " " + sbErn.toString() ) ); +// } + + + +// msgs.add( String.format( +// " " ) ); +// +// cPlayer.getEarningsByMine() + + } + + + + + + sendToPlayerAndConsole( sender, msgs ); + + + if ( sender.hasPermission("ranks.admin") ) { // This is admin-exclusive content @@ -1595,7 +1697,135 @@ public void rankPlayer(CommandSender sender, // ranksPlayerNoRanksFoundMsg( sender, player.getDisplayName() ); // } } + + private String formatTimeMs( long timeMs ) { + + DecimalFormat iFmt = new DecimalFormat("#,##0"); + DecimalFormat tFmt = new DecimalFormat("00"); +// SimpleDateFormat sdFmt = new SimpleDateFormat( "HH:mm:ss" ); + + long _sec = 1000; + long _min = _sec * 60; + long _hour = _min * 60; + long _day = _hour * 24; + + long ms = timeMs; + long days = _day < ms ? ms / _day : 0; + + ms -= (days * _day); + long hours = _hour < ms ? ms / _hour : 0; + + ms -= (hours * _hour); + long mins = _min < ms ? ms / _min : 0; + + ms -= (mins * _min); + long secs = _sec < ms ? ms / _sec : 0; + + + String results = + (days == 0 ? "" : iFmt.format( days ) + "d ") + + tFmt.format( hours ) + ":" + + tFmt.format( mins ) + ":" + + tFmt.format( secs ) + ; + + return results; + } + + private void formatTreeMapStats( TreeMap statMap, List msgs, + DecimalFormat dFmt, DecimalFormat iFmt, + int columns ) { + + Set keysEarnings = statMap.keySet(); + + + List values = new ArrayList<>(); + List valueMaxLen = new ArrayList<>(); + + + int count = 0; + StringBuilder sb = new StringBuilder(); + for ( String earningKey : keysEarnings ) + { + String value = null; + Object valueObj = statMap.get( earningKey ); + + if ( valueObj instanceof Double ) { + + value = PlaceholdersUtil.formattedKmbtSISize( (Double) valueObj, dFmt, " &9" ); + } + else if ( valueObj instanceof Integer ) { + int intVal = (Integer) valueObj; + value = PlaceholdersUtil.formattedKmbtSISize( intVal, + ( intVal < 1000 ? iFmt : dFmt ), " &9" ); + } + else if ( valueObj instanceof Long ) { + + value = formatTimeMs( (Long) valueObj ); + } + + String msg = String.format( "&3%s&8: &b%s", earningKey, value ).trim(); + + String msgNoColor = Text.stripColor( msg ); + int lenMNC = msgNoColor.length(); + + + int col = values.size() % columns; + values.add( msg ); + + if ( col >= valueMaxLen.size() || lenMNC > valueMaxLen.get( col ) ) { + + if ( col > valueMaxLen.size() - 1 ) { + valueMaxLen.add( lenMNC ); + } + else { + + valueMaxLen.set( col, lenMNC ); + } + } + } + + + for ( int j = 0; j < values.size(); j++ ) + { + String msg = values.get( j ); + + int col = j % columns; + + int maxColumnWidth = col > valueMaxLen.size() - 1 ? + msg.length() : + valueMaxLen.get( col ); + + sb.append( msg ); + + // Pad the right of all content with spaces to align columns, up to a + // given maxLength: + String msgNoColor = Text.stripColor( msg ); + int lenMNC = msgNoColor.length(); + for( int i = lenMNC; i < maxColumnWidth; i++ ) { + sb.append( " " ); + } + // The spacer: + sb.append( " " ); + + if ( ++count % columns == 0 ) { + msgs.add( String.format( + " " + sb.toString() ) ); + sb.setLength( 0 ); + + } + } + + if ( sb.length() > 0 ) { + + msgs.add( String.format( + " " + sb.toString() ) ); + } + + + } + //// @Command(identifier = "ranks playerInventory", permissions = "mines.set", //// description = "For listing what's in a player's inventory by dumping it to console.", @@ -1646,6 +1876,23 @@ private void listPermissions( CommandSender sender, String prefix, List } } + private void sendToPlayerAndConsole( CommandSender sender, List messages ) + { + + // If not a console user then send the message to the sender, other wise if a console + // user then they will see duplicate messages: + if ( sender.getName() != null && !sender.getName().equalsIgnoreCase( "console" ) ) { + sender.sendMessage( messages.toArray( new String[0] ) ); + } + + for ( String message : messages ) + { + // log the rank. There was one issue with the ranks suddenly being changed so this + // will help document what ranks were. + Output.get().log( message, LogLevel.PLAIN ); + } + } + private void sendToPlayerAndConsole( CommandSender sender, String messageRank ) { // If not a console user then send the message to the sender, other wise if a console @@ -1656,7 +1903,7 @@ private void sendToPlayerAndConsole( CommandSender sender, String messageRank ) // log the rank. There was one issue with the ranks suddenly being changed so this // will help document what ranks were. - Output.get().logInfo( messageRank ); + Output.get().log( messageRank, LogLevel.PLAIN ); } From d619eeda2b194514702bbef94a82af4006afea96 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 21 Nov 2021 14:22:32 -0500 Subject: [PATCH 128/283] Bug fix: If player is mining outside of a mine, then don't process anything. May want to allow prison to manage block breaks outside of mines in the future, but for now, prison is only managing mines. --- docs/changelog_v3.3.x.md | 4 ++++ .../spigot/block/OnBlockBreakEventCore.java | 20 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index c7ad18d82..8d30620da 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.5 2021-11-21 +* **Bug fix: If player is mining outside of a mine, then don't process anything.** +May want to allow prison to manage block breaks outside of mines in the future, but for now, prison is only managing mines. + + * **New feature which lists all of the Player Cache stats in the command `/ranks player`. This includes stats for block breaks, time spent in mines, and earnings per mine.** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index 063e709e5..c944f0e9d 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -302,6 +302,10 @@ protected void genericBlockEvent( BlockBreakEvent e, boolean monitor, boolean bl Mine mine = findMine( e.getPlayer(), sBlock, null, null ); + if ( mine == null ) { + // Prison is unable to process blocks outside of mines right now, so exit: + return; + } MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); // If ignore all block events, then exit this function without logging anything: @@ -970,6 +974,10 @@ private void genericBlockExplodeEvent( TEBlockExplodeEvent e, boolean monitor, b Mine mine = findMine( e.getPlayer(), sBlock, e.blockList(), null ); + if ( mine == null ) { + // Prison is unable to process blocks outside of mines right now, so exit: + return; + } MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); // If ignore all block events, then exit this function without logging anything: @@ -1193,6 +1201,10 @@ protected void genericBlastUseEvent( BlastUseEvent e, boolean monitor, boolean b Mine mine = findMine( e.getPlayer(), sBlock, e.getBlockList(), null ); + if ( mine == null ) { + // Prison is unable to process blocks outside of mines right now, so exit: + return; + } MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); // If ignore all block events, then exit this function without logging anything: @@ -1385,6 +1397,10 @@ protected void genericExplosiveEvent( PEExplosionEvent e, boolean monitor, boole Mine mine = findMine( e.getPlayer(), sBlock, e.getExplodedBlocks(), null ); + if ( mine == null ) { + // Prison is unable to process blocks outside of mines right now, so exit: + return; + } MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); // If ignore all block events, then exit this function without logging anything: @@ -1514,6 +1530,10 @@ protected void genericExplosiveEvent( ExplosiveBlockBreakEvent e, boolean monito Mine mine = findMine( e.getPlayer(), sBlock, e.getExplodedBlocks(), null ); + if ( mine == null ) { + // Prison is unable to process blocks outside of mines right now, so exit: + return; + } MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); // If ignore all block events, then exit this function without logging anything: From f2ed013f69be382b946d56da6102feda8afe732b Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 21 Nov 2021 19:52:40 -0500 Subject: [PATCH 129/283] Release v3.2.11-alpha.6 --- docs/changelog_v3.3.x.md | 3 +++ gradle.properties | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 8d30620da..0242f43ba 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -20,6 +20,9 @@ These build logs represent the work that has been going on within prison. May want to allow prison to manage block breaks outside of mines in the future, but for now, prison is only managing mines. +* **3.2.11-alpha.6 2021-11-21** + + * **New feature which lists all of the Player Cache stats in the command `/ranks player`. This includes stats for block breaks, time spent in mines, and earnings per mine.** diff --git a/gradle.properties b/gradle.properties index 02950d282..8bb24c096 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ ## # This is actually the "correct" place to define the version for the project. ## # Used within build.gradle with ${project.version}. ## # Can be overridden on the command line: gradle -Pversion=3.2.1-alpha.3 -version=3.2.11-alpha.5 +version=3.2.11-alpha.6 #version=3.2.8.2 #version=3.3.0-alpha.6 From d757a50ca9f0a36f2b2703b7c34bbf6095f7c16b Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 21 Nov 2021 19:54:45 -0500 Subject: [PATCH 130/283] Moved the multi-column formatting of data to the class Text so it can be used in other parts of the project. It was originally created for use in /ranks player but is now extended to be usd to list the plugins within the /prison version command. --- docs/changelog_v3.3.x.md | 5 + .../tech/mcprison/prison/PrisonCommand.java | 44 ++- .../java/tech/mcprison/prison/util/Text.java | 215 ++++++++++++++ .../prison/mines/commands/MinesCommands.java | 7 +- .../tech/mcprison/prison/mines/data/Mine.java | 7 +- .../prison/ranks/commands/RanksCommands.java | 277 +++++++++--------- 6 files changed, 399 insertions(+), 156 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 0242f43ba..d218e2ec0 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,11 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.5 2021-11-21 + +* **Moved the multi-column formatting of data to the class Text so it can be used in other parts of the project.** +It was originally created for use in /ranks player but is now extended to be usd to list the plugins within the /prison version command. + + * **Bug fix: If player is mining outside of a mine, then don't process anything.** May want to allow prison to manage block breaks outside of mines in the future, but for now, prison is only managing mines. diff --git a/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java b/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java index 8ebb5bab0..4f373c678 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java +++ b/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java @@ -25,6 +25,7 @@ import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Optional; @@ -55,6 +56,7 @@ import tech.mcprison.prison.troubleshoot.Troubleshooter; import tech.mcprison.prison.util.JumboTextFont; import tech.mcprison.prison.util.PrisonJarReporter; +import tech.mcprison.prison.util.Text; /** * Root commands for managing the platform as a whole, in-game. @@ -345,21 +347,31 @@ else if ( !isBasic ) { if ( getRegisteredPlugins().size() > 0 ) { display.addText(""); display.addText( "&7Registered Plugins: " ); - StringBuilder sb = new StringBuilder(); - for ( String plugin : getRegisteredPlugins() ) { - if ( sb.length() == 0) { - sb.append( ". " ); - sb.append( plugin ); - } else { - sb.append( ", " ); - sb.append( plugin ); - display.addText( sb.toString() ); - sb.setLength( 0 ); - } - } - if ( sb.length() > 0 ) { - display.addText( sb.toString()); - } + + List plugins = getRegisteredPlugins(); + Collections.sort( plugins ); + List plugins2Cols = Text.formatColumnsFromList( plugins, 2 ); + + for ( String rp : plugins2Cols ) { + + display.addText( rp ); + } + +// StringBuilder sb = new StringBuilder(); +// for ( String plugin : getRegisteredPlugins() ) { +// if ( sb.length() == 0) { +// sb.append( ". " ); +// sb.append( plugin ); +// } else { +// sb.append( ", " ); +// sb.append( plugin ); +// display.addText( sb.toString() ); +// sb.setLength( 0 ); +// } +// } +// if ( sb.length() > 0 ) { +// display.addText( sb.toString()); +// } } // This version of plugins does not have all the registered commands: @@ -1262,7 +1274,7 @@ public void supportSubmitMines(CommandSender sender List files = listFiles( "data_storage/mines/mines/", ".json" ); - + Collections.sort( files ); StringBuilder text = new StringBuilder(); diff --git a/prison-core/src/main/java/tech/mcprison/prison/util/Text.java b/prison-core/src/main/java/tech/mcprison/prison/util/Text.java index 0795db551..880a44ed9 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/util/Text.java +++ b/prison-core/src/main/java/tech/mcprison/prison/util/Text.java @@ -18,16 +18,20 @@ package tech.mcprison.prison.util; +import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Set; +import java.util.TreeMap; import java.util.regex.Matcher; import java.util.regex.Pattern; import tech.mcprison.prison.Prison; +import tech.mcprison.prison.placeholders.PlaceholdersUtil; /** * Provides utilities for manipulating text. @@ -67,6 +71,11 @@ public class Text { //#([A-Fa-f0-9]){6} + private static DecimalFormat dFmt = new DecimalFormat("#,##0.00"); + private static DecimalFormat iFmt = new DecimalFormat("#,##0"); + + + protected Text() { super(); @@ -530,5 +539,211 @@ public static String pluralize(String baseNoun, int quantity) { } } + + public static String formatTimeDaysHhMmSs( long timeMs ) { + + DecimalFormat iFmt = new DecimalFormat("#,##0"); + DecimalFormat tFmt = new DecimalFormat("00"); +// SimpleDateFormat sdFmt = new SimpleDateFormat( "HH:mm:ss" ); + +// long _sec = 1000; +// long _min = _sec * 60; +// long _hour = _min * 60; +// long _day = _hour * 24; + + long ms = timeMs; + long days = millisPerDay < ms ? ms / millisPerDay : 0; + + ms -= (days * millisPerDay); + long hours = millisPerHour < ms ? ms / millisPerHour : 0; + + ms -= (hours * millisPerHour); + long mins = millisPerMinute < ms ? ms / millisPerMinute : 0; + + ms -= (mins * millisPerMinute); + long secs = millisPerSecond < ms ? ms / millisPerSecond : 0; + + + String results = + (days == 0 ? "" : iFmt.format( days ) + "d ") + + tFmt.format( hours ) + ":" + + tFmt.format( mins ) + ":" + + tFmt.format( secs ) + ; + + return results; + } + + + public static List formatTreeMapStats( TreeMap statMap, + int columns ) { + + List msgs = new ArrayList<>(); + + Set keys = statMap.keySet(); + + + List values = new ArrayList<>(); +// List valueMaxLen = new ArrayList<>(); + +// StringBuilder sb = new StringBuilder(); +// int count = 0; + + for ( String earningKey : keys ) + { + String value = null; + Object valueObj = statMap.get( earningKey ); + + if ( valueObj instanceof Double ) { + + value = PlaceholdersUtil.formattedKmbtSISize( (Double) valueObj, dFmt, " &9" ); + } + else if ( valueObj instanceof Integer ) { + int intVal = (Integer) valueObj; + value = PlaceholdersUtil.formattedKmbtSISize( intVal, + ( intVal < 1000 ? iFmt : dFmt ), " &9" ); + } + else if ( valueObj instanceof Long ) { + + value = Text.formatTimeDaysHhMmSs( (Long) valueObj ); + } + + String msg = String.format( "&3%s&8: &b%s", earningKey, value ).trim(); + +// String msgNoColor = Text.stripColor( msg ); +// int lenMNC = msgNoColor.length(); +// +// +// int col = values.size() % columns; + values.add( msg ); + +// if ( col >= valueMaxLen.size() || lenMNC > valueMaxLen.get( col ) ) { +// +// if ( col > valueMaxLen.size() - 1 ) { +// valueMaxLen.add( lenMNC ); +// } +// else { +// +// valueMaxLen.set( col, lenMNC ); +// } +// } + } + + msgs = formatColumnsFromList( values, columns ); + +// for ( int j = 0; j < values.size(); j++ ) +// { +// String msg = values.get( j ); +// +// int col = j % columns; +// +// int maxColumnWidth = col > valueMaxLen.size() - 1 ? +// msg.length() : +// valueMaxLen.get( col ); +// +// sb.append( msg ); +// +// // Pad the right of all content with spaces to align columns, up to a +// // given maxLength: +// String msgNoColor = Text.stripColor( msg ); +// int lenMNC = msgNoColor.length(); +// for( int i = lenMNC; i < maxColumnWidth; i++ ) { +// sb.append( " " ); +// } +// +// // The spacer: +// sb.append( " " ); +// +// if ( ++count % columns == 0 ) { +// msgs.add( String.format( +// " " + sb.toString() ) ); +// sb.setLength( 0 ); +// +// } +// } +// +// if ( sb.length() > 0 ) { +// +// msgs.add( String.format( +// " " + sb.toString() ) ); +// } + + return msgs; + } + + + public static List formatColumnsFromList( List textItems, + int columns ) { + + List msgs = new ArrayList<>(); + + List valueMaxLen = new ArrayList<>(); + + StringBuilder sb = new StringBuilder(); + int count = 0; + + // Find the maxLenght value for each column that will be generated: + for ( int i = 0; i < textItems.size(); i++ ) + { + String msg = textItems.get( i ); + + String msgNoColor = Text.stripColor( msg ); + int lenMNC = msgNoColor.length(); + + + int col = i % columns; + + if ( col >= valueMaxLen.size() || lenMNC > valueMaxLen.get( col ) ) { + + if ( col > valueMaxLen.size() - 1 ) { + valueMaxLen.add( lenMNC ); + } + else { + + valueMaxLen.set( col, lenMNC ); + } + } + } + + + for ( int j = 0; j < textItems.size(); j++ ) + { + String msg = textItems.get( j ); + + int col = j % columns; + + int maxColumnWidth = col > valueMaxLen.size() - 1 ? + msg.length() : + valueMaxLen.get( col ); + + sb.append( msg ); + + // Pad the right of all content with spaces to align columns, up to a + // given maxLength: + String msgNoColor = Text.stripColor( msg ); + int lenMNC = msgNoColor.length(); + for( int i = lenMNC; i < maxColumnWidth; i++ ) { + sb.append( " " ); + } + + // The spacer: + sb.append( " " ); + + if ( ++count % columns == 0 ) { + msgs.add( String.format( + " " + sb.toString() ) ); + sb.setLength( 0 ); + + } + } + + if ( sb.length() > 0 ) { + + msgs.add( String.format( + " " + sb.toString() ) ); + } + + return msgs; + } } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java index 9bd8e7adb..b003feeaf 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java @@ -20,6 +20,7 @@ import java.text.DecimalFormat; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -794,7 +795,11 @@ public void allMinesInfoDetails( StringBuilder sb ) { PrisonMines pMines = PrisonMines.getInstance(); MineManager mMan = pMines.getMineManager(); - for ( Mine mine : mMan.getMines() ) { + List mines = new ArrayList<>(); + mines.addAll( mMan.getMines() ); + Collections.sort( mines ); + + for ( Mine mine : mines ) { PrisonCommand.printFooter( sb ); diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/Mine.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/Mine.java index eb1719565..aa4422b2a 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/Mine.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/Mine.java @@ -46,7 +46,7 @@ */ public class Mine extends MineScheduler - implements PrisonSortable { + implements PrisonSortable, Comparable { public enum MineType { @@ -759,4 +759,9 @@ public String getBlockListString() return sb.toString(); } + @Override + public int compareTo( Mine o ) { + return getName().toLowerCase().compareTo( o.getName().toLowerCase() ); + } + } diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java index 345c179ca..3b0b81b6f 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java @@ -1,16 +1,13 @@ package tech.mcprison.prison.ranks.commands; import java.text.DecimalFormat; -import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; -import java.util.Date; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; -import java.util.TreeMap; import tech.mcprison.prison.Prison; import tech.mcprison.prison.PrisonAPI; @@ -1444,9 +1441,9 @@ public void rankPlayer(CommandSender sender, if ( rankPlayer != null ) { DecimalFormat dFmt = new DecimalFormat("#,##0.00"); - DecimalFormat iFmt = new DecimalFormat("#,##0"); - - SimpleDateFormat sdFmt = new SimpleDateFormat( "HH:mm:ss" ); +// DecimalFormat iFmt = new DecimalFormat("#,##0"); +// +// SimpleDateFormat sdFmt = new SimpleDateFormat( "HH:mm:ss" ); // Collect all currencies in the default ladder: Set currencies = new LinkedHashSet<>(); @@ -1550,15 +1547,17 @@ public void rankPlayer(CommandSender sender, " Earnings By Mine: &2Avg Earnings per min: &3%s", dFmt.format( cPlayer.getAverageEarningsPerMinute() )) ); - formatTreeMapStats(cPlayer.getEarningsByMine(), msgs, dFmt, iFmt, 5 ); + msgs.addAll( + Text.formatTreeMapStats(cPlayer.getEarningsByMine(), 5 ) ); msgs.add( String.format( " &7Timings By Mine&8: &2Online&8: &3%s &2Mining&8: &3%s", - formatTimeMs( cPlayer.getOnlineTimeTotal() ), - formatTimeMs( cPlayer.getOnlineMiningTimeTotal()) ) + Text.formatTimeDaysHhMmSs( cPlayer.getOnlineTimeTotal() ), + Text.formatTimeDaysHhMmSs( cPlayer.getOnlineMiningTimeTotal()) ) ); - formatTreeMapStats(cPlayer.getTimeByMine(), msgs, dFmt, iFmt, 5 ); + msgs.addAll( + Text.formatTreeMapStats(cPlayer.getTimeByMine(), 5 ) ); // Print all earnings for all mines: @@ -1567,11 +1566,13 @@ public void rankPlayer(CommandSender sender, msgs.add( String.format( " &7Blocks By Mine&8: &2Blocks Total&8: &3%s", totalBlocks) ); - formatTreeMapStats(cPlayer.getBlocksByMine(), msgs, dFmt, iFmt, 5 ); + msgs.addAll( + Text.formatTreeMapStats(cPlayer.getBlocksByMine(), 5 ) ); msgs.add( " &7Blocks By Type&8:" ); - formatTreeMapStats(cPlayer.getBlocksByType(), msgs, dFmt, iFmt, 3 ); + msgs.addAll( + Text.formatTreeMapStats(cPlayer.getBlocksByType(), 3 ) ); // Set keysEarnings = cPlayer.getEarningsByMine().keySet(); @@ -1698,133 +1699,133 @@ public void rankPlayer(CommandSender sender, // } } - private String formatTimeMs( long timeMs ) { - - DecimalFormat iFmt = new DecimalFormat("#,##0"); - DecimalFormat tFmt = new DecimalFormat("00"); -// SimpleDateFormat sdFmt = new SimpleDateFormat( "HH:mm:ss" ); - - long _sec = 1000; - long _min = _sec * 60; - long _hour = _min * 60; - long _day = _hour * 24; - - long ms = timeMs; - long days = _day < ms ? ms / _day : 0; - - ms -= (days * _day); - long hours = _hour < ms ? ms / _hour : 0; - - ms -= (hours * _hour); - long mins = _min < ms ? ms / _min : 0; - - ms -= (mins * _min); - long secs = _sec < ms ? ms / _sec : 0; - - - String results = - (days == 0 ? "" : iFmt.format( days ) + "d ") + - tFmt.format( hours ) + ":" + - tFmt.format( mins ) + ":" + - tFmt.format( secs ) - ; - - return results; - } +// private String formatTimeMs( long timeMs ) { +// +// DecimalFormat iFmt = new DecimalFormat("#,##0"); +// DecimalFormat tFmt = new DecimalFormat("00"); +//// SimpleDateFormat sdFmt = new SimpleDateFormat( "HH:mm:ss" ); +// +// long _sec = 1000; +// long _min = _sec * 60; +// long _hour = _min * 60; +// long _day = _hour * 24; +// +// long ms = timeMs; +// long days = _day < ms ? ms / _day : 0; +// +// ms -= (days * _day); +// long hours = _hour < ms ? ms / _hour : 0; +// +// ms -= (hours * _hour); +// long mins = _min < ms ? ms / _min : 0; +// +// ms -= (mins * _min); +// long secs = _sec < ms ? ms / _sec : 0; +// +// +// String results = +// (days == 0 ? "" : iFmt.format( days ) + "d ") + +// tFmt.format( hours ) + ":" + +// tFmt.format( mins ) + ":" + +// tFmt.format( secs ) +// ; +// +// return results; +// } - private void formatTreeMapStats( TreeMap statMap, List msgs, - DecimalFormat dFmt, DecimalFormat iFmt, - int columns ) { - - Set keysEarnings = statMap.keySet(); - - - List values = new ArrayList<>(); - List valueMaxLen = new ArrayList<>(); - - - int count = 0; - StringBuilder sb = new StringBuilder(); - for ( String earningKey : keysEarnings ) - { - String value = null; - Object valueObj = statMap.get( earningKey ); - - if ( valueObj instanceof Double ) { - - value = PlaceholdersUtil.formattedKmbtSISize( (Double) valueObj, dFmt, " &9" ); - } - else if ( valueObj instanceof Integer ) { - int intVal = (Integer) valueObj; - value = PlaceholdersUtil.formattedKmbtSISize( intVal, - ( intVal < 1000 ? iFmt : dFmt ), " &9" ); - } - else if ( valueObj instanceof Long ) { - - value = formatTimeMs( (Long) valueObj ); - } - - String msg = String.format( "&3%s&8: &b%s", earningKey, value ).trim(); - - String msgNoColor = Text.stripColor( msg ); - int lenMNC = msgNoColor.length(); - - - int col = values.size() % columns; - values.add( msg ); - - if ( col >= valueMaxLen.size() || lenMNC > valueMaxLen.get( col ) ) { - - if ( col > valueMaxLen.size() - 1 ) { - valueMaxLen.add( lenMNC ); - } - else { - - valueMaxLen.set( col, lenMNC ); - } - } - } - - - for ( int j = 0; j < values.size(); j++ ) - { - String msg = values.get( j ); - - int col = j % columns; - - int maxColumnWidth = col > valueMaxLen.size() - 1 ? - msg.length() : - valueMaxLen.get( col ); - - sb.append( msg ); - - // Pad the right of all content with spaces to align columns, up to a - // given maxLength: - String msgNoColor = Text.stripColor( msg ); - int lenMNC = msgNoColor.length(); - for( int i = lenMNC; i < maxColumnWidth; i++ ) { - sb.append( " " ); - } - - // The spacer: - sb.append( " " ); - - if ( ++count % columns == 0 ) { - msgs.add( String.format( - " " + sb.toString() ) ); - sb.setLength( 0 ); - - } - } - - if ( sb.length() > 0 ) { - - msgs.add( String.format( - " " + sb.toString() ) ); - } - - - } +// private void formatTreeMapStats( TreeMap statMap, List msgs, +// DecimalFormat dFmt, DecimalFormat iFmt, +// int columns ) { +// +// Set keysEarnings = statMap.keySet(); +// +// +// List values = new ArrayList<>(); +// List valueMaxLen = new ArrayList<>(); +// +// +// int count = 0; +// StringBuilder sb = new StringBuilder(); +// for ( String earningKey : keysEarnings ) +// { +// String value = null; +// Object valueObj = statMap.get( earningKey ); +// +// if ( valueObj instanceof Double ) { +// +// value = PlaceholdersUtil.formattedKmbtSISize( (Double) valueObj, dFmt, " &9" ); +// } +// else if ( valueObj instanceof Integer ) { +// int intVal = (Integer) valueObj; +// value = PlaceholdersUtil.formattedKmbtSISize( intVal, +// ( intVal < 1000 ? iFmt : dFmt ), " &9" ); +// } +// else if ( valueObj instanceof Long ) { +// +// value = Text.formatTimeDaysHhMmSs( (Long) valueObj ); +// } +// +// String msg = String.format( "&3%s&8: &b%s", earningKey, value ).trim(); +// +// String msgNoColor = Text.stripColor( msg ); +// int lenMNC = msgNoColor.length(); +// +// +// int col = values.size() % columns; +// values.add( msg ); +// +// if ( col >= valueMaxLen.size() || lenMNC > valueMaxLen.get( col ) ) { +// +// if ( col > valueMaxLen.size() - 1 ) { +// valueMaxLen.add( lenMNC ); +// } +// else { +// +// valueMaxLen.set( col, lenMNC ); +// } +// } +// } +// +// +// for ( int j = 0; j < values.size(); j++ ) +// { +// String msg = values.get( j ); +// +// int col = j % columns; +// +// int maxColumnWidth = col > valueMaxLen.size() - 1 ? +// msg.length() : +// valueMaxLen.get( col ); +// +// sb.append( msg ); +// +// // Pad the right of all content with spaces to align columns, up to a +// // given maxLength: +// String msgNoColor = Text.stripColor( msg ); +// int lenMNC = msgNoColor.length(); +// for( int i = lenMNC; i < maxColumnWidth; i++ ) { +// sb.append( " " ); +// } +// +// // The spacer: +// sb.append( " " ); +// +// if ( ++count % columns == 0 ) { +// msgs.add( String.format( +// " " + sb.toString() ) ); +// sb.setLength( 0 ); +// +// } +// } +// +// if ( sb.length() > 0 ) { +// +// msgs.add( String.format( +// " " + sb.toString() ) ); +// } +// +// +// } //// @Command(identifier = "ranks playerInventory", permissions = "mines.set", From 267cc2e4edb5ff8259cad6cbcf5b714af4b24766 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Mon, 22 Nov 2021 03:30:55 -0500 Subject: [PATCH 131/283] Bug Fix: There was originally a problem with applying block constraints that resulted in being unable to select a block when trying to randomly choose one. Initially as a first quick fix was to trying to reselect a block, but if the block chances were really low, then it could still fail to select a block. Then it was attempted to select a default block, but that too failed to work, especially if there were a sizable chance for AIR, and it would fail 100% of the time if the was only one block with a very low chance. The failure was the whole mine could be filled with that one block with the very small chance. This fix completely redesigns the block selection, by first selecting only the blocks that are valid for that level of the mine. That way, when selecting blocks where blocks should be excluded from that level, those excluded blocks are never in the selected blocks to be considered. Also if AIR is a valid option, then this new process adds an AIR block to the temporary level block list with the percent chance assigned to the air. Overall, this is working really well now, and it actually simplifies a lot of code and reduces the amount of processing involved. This new process always selects a block on the first pass too so it never haves to try to reselect a block. --- docs/changelog_v3.3.x.md | 7 +- .../mines/data/MineLevelBlockListData.java | 172 +++++++++++++ .../mcprison/prison/mines/data/MineReset.java | 226 +++++++++--------- 3 files changed, 296 insertions(+), 109 deletions(-) create mode 100644 prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineLevelBlockListData.java diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index d218e2ec0..12b40ef34 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,9 +13,14 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.5 2021-11-21 +# 3.2.11-alpha.5 2021-11-22 +* **Bug Fix: There was originally a problem with applying block constraints that resulted in being unable to select a block when trying to randomly choose one.** +Initially as a first quick fix was to trying to reselect a block, but if the block chances were really low, then it could still fail to select a block. Then it was attempted to select a default block, but that too failed to work, especially if there were a sizable chance for AIR, and it would fail 100% of the time if the was only one block with a very low chance. The failure was the whole mine could be filled with that one block with the very small chance. +This fix completely redesigns the block selection, by first selecting only the blocks that are valid for that level of the mine. That way, when selecting blocks where blocks should be excluded from that level, those excluded blocks are never in the selected blocks to be considered. Also if AIR is a valid option, then this new process adds an AIR block to the temporary level block list with the percent chance assigned to the air. +Overall, this is working really well now, and it actually simplifies a lot of code and reduces the amount of processing involved. This new process always selects a block on the first pass too so it never haves to try to reselect a block. + * **Moved the multi-column formatting of data to the class Text so it can be used in other parts of the project.** It was originally created for use in /ranks player but is now extended to be usd to list the plugins within the /prison version command. diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineLevelBlockListData.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineLevelBlockListData.java new file mode 100644 index 000000000..ac7b6479c --- /dev/null +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineLevelBlockListData.java @@ -0,0 +1,172 @@ +package tech.mcprison.prison.mines.data; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import tech.mcprison.prison.internal.block.PrisonBlock; + +public class MineLevelBlockListData +{ + + private int currentMineLevel; + + private Mine mine; + + private Random random; + + private List selectedBlocks; + + private double totalChance = 0d; + + private double selectedChance = 0d; + + private double airChance = 0d; + + public MineLevelBlockListData( int currentMineLevel, Mine mine, Random random ) { + super(); + + this.currentMineLevel = currentMineLevel; + this.mine = mine; + + this.random = random; + + this.selectedBlocks = new ArrayList<>(); + + initialize(); + } + + private void initialize() { + + + + // PrisonBlocks contains the percent chance of spawning: + for ( PrisonBlock pBlock : mine.getPrisonBlocks() ) + { + // First calculate the total percent chance: + totalChance += pBlock.getChance(); + + // If the block has no constraints, or if the block is within the + // mine constraints, add it to our list: + if ( pBlock.getConstraintExcludeTopLayers() == 0 && + pBlock.getConstraintExcludeBottomLayers() == 0 || + + pBlock.getConstraintExcludeTopLayers() <= currentMineLevel && + (pBlock.getConstraintExcludeBottomLayers() == 0 || + pBlock.getConstraintExcludeBottomLayers() > currentMineLevel) ) { + + // Sum the selected blocks: + selectedChance += pBlock.getChance(); + + // Add the selected blocks to our list: + selectedBlocks.add( pBlock ); + + + // If exclude top layers is enabled, then only try to set the + // rangeBlockCountLowLimit once since we need the lowest possible + // value. The initial value for getRangeBlockCountLowLimit is -1. + if ( pBlock.getRangeBlockCountLowLimit() <= 0 && + currentMineLevel > pBlock.getConstraintExcludeTopLayers() ) { + + int targetBlockPosition = mine.getMineTargetPrisonBlocks().size(); + pBlock.setRangeBlockCountLowLimit( targetBlockPosition ); + } + + + // If exclude bottom layer is enabled, then we need to track every number + // until the currentLevel exceeds the getConstraintExcludeBottomLayers value. + // If exclude top layers, then do not record for the bottom layers until + // the top layers is cleared. + if ( (pBlock.getConstraintExcludeTopLayers() > 0 && + currentMineLevel > pBlock.getConstraintExcludeTopLayers() || + pBlock.getConstraintExcludeTopLayers() == 0) && + + pBlock.getConstraintExcludeBottomLayers() > 0 && + pBlock.getConstraintExcludeBottomLayers() < currentMineLevel + ) { + + int targetBlockPosition = mine.getMineTargetPrisonBlocks().size(); + pBlock.setRangeBlockCountHighLimit( targetBlockPosition ); + + } + + } + + } + + + // Using the total chance, need to calculate the AIR percent: + airChance = 100d - totalChance; + + // If airChance is not zero, add an AIR block to the selectedBlocks list: + if ( airChance > 0d ) { + PrisonBlock airBlock = PrisonBlock.AIR.clone(); + + airBlock.setChance( airChance ); + + selectedBlocks.add( airBlock ); + } + + + } + + + /** + *

For each block, run this to ensure all selected blocks that have a specified + * exclusion from the lower levels of the mine, that the rangeBlockCountHighLimit is + * properly set. + *

+ */ + public void checkSelectedBlockExcludeFromBottomLayers() { + + for ( PrisonBlock pBlock : selectedBlocks ) + { + // If exclude bottom layer is enabled, then we need to track every number + // until the currentLevel exceeds the getConstraintExcludeBottomLayers value. + // If exclude top layers, then do not record for the bottom layers until + // the top layers is cleared. + if ( (pBlock.getConstraintExcludeTopLayers() > 0 && + currentMineLevel > pBlock.getConstraintExcludeTopLayers() || + pBlock.getConstraintExcludeTopLayers() == 0) && + + pBlock.getConstraintExcludeBottomLayers() > 0 && + pBlock.getConstraintExcludeBottomLayers() < currentMineLevel + ) { + + int targetBlockPosition = mine.getMineTargetPrisonBlocks().size(); + pBlock.setRangeBlockCountHighLimit( targetBlockPosition ); + + } + + } + } + + public PrisonBlock randomlySelectPrisonBlock() + { + PrisonBlock selected = null; + + // Will have a value of 100% if no blocks are excluded due to block constraints: + double totalSelectedChance = selectedChance + airChance; + + double chance = random.nextDouble() * totalSelectedChance; + + for ( PrisonBlock block : selectedBlocks ) { + + if ( chance <= block.getChance() ) { + + // If this block is chosen and it was not skipped, then use this block and exit. + // Otherwise the chance will be recalculated and tried again to find a valid block, + // since the odds have been thrown off... + selected = block; + + break; + } else { + chance -= block.getChance(); + } + } + + return selected; + } + + +} diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java index 9e8d269e2..f6349ea38 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java @@ -532,8 +532,8 @@ public void generateBlockListAsync() { resetResetBlockCounts(); - // setup the monitoring of the blocks that have constraints: - List constrainedBlocks = null; +// // setup the monitoring of the blocks that have constraints: +// List constrainedBlocks = null; @@ -555,9 +555,17 @@ public void generateBlockListAsync() { // the player enter from the top, and the reset will appear to be more "instant". for (int y = yMax; y >= yMin; y--) { currentLevel++; // One based: First layer is currentLevel == 1 + + + // This is used to select the correct block list for the given mine level: + MineLevelBlockListData mineLevelBlockList = new MineLevelBlockListData( currentLevel, (Mine) this, random ); + + for (int x = xMin; x <= xMax; x++) { for (int z = zMin; z <= zMax; z++) { + // updates selected block's exclude from bottom layer max value settings: + mineLevelBlockList.checkSelectedBlockExcludeFromBottomLayers(); boolean xEdge = x == xMin || x == xMax; boolean yEdge = y == yMin || y == yMax; @@ -571,10 +579,12 @@ public void generateBlockListAsync() { if ( isUseNewBlockModel() ) { - // track the constraints: - trackConstraints( currentLevel, constrainedBlocks ); + // track the constraints: (obsolete) + //trackConstraints( currentLevel, constrainedBlocks ); - PrisonBlock prisonBlock = randomlySelectPrisonBlock( random, currentLevel ); + PrisonBlock prisonBlock = mineLevelBlockList.randomlySelectPrisonBlock(); + +// PrisonBlock prisonBlock = randomlySelectPrisonBlock( random, currentLevel ); // Increment the mine's block count. This block is one of the control blocks: incrementResetBlockCount( prisonBlock ); @@ -628,58 +638,58 @@ public void generateBlockListAsync() { } - private void trackConstraints( int currentLevel, List constrainedBlocks ) - { - - // If the constrainedBlocks list has not be configured, set it up with the - // blocks that have constraints: - if ( constrainedBlocks == null ) { - - constrainedBlocks = new ArrayList<>(); - - for (PrisonBlock block : getPrisonBlocks()) { - if ( block.getConstraintExcludeTopLayers() > 0 || - block.getConstraintExcludeBottomLayers() > 0 ) { - - constrainedBlocks.add( block ); - } - } - } - - - // If there are any constrained blocks, then need to record - for ( PrisonBlockStatusData block : constrainedBlocks ) { - - // If exclude top layers is enabled, then only try to set the - // rangeBlockCountLowLimit once since we need the lowest possible - // value. The inital value for getRangeBlockCountLowLimit is -1. - if ( block.getConstraintExcludeTopLayers() > 0 && - block.getRangeBlockCountLowLimit() <= 0 && - currentLevel > block.getConstraintExcludeTopLayers() ) { - - int targetBlockPosition = getMineTargetPrisonBlocks().size(); - block.setRangeBlockCountLowLimit( targetBlockPosition ); - } - - // If exclude bottom layer is enabled, then we need to track every number - // until the currentLevel exceeds the getConstraintExcludeBottomLayers value. - // If exclude top layers, then do not record for the bottom layers until - // the top layers is cleared. - if ( (block.getConstraintExcludeTopLayers() > 0 && - currentLevel > block.getConstraintExcludeTopLayers() || - block.getConstraintExcludeTopLayers() == 0) && - - block.getConstraintExcludeBottomLayers() > 0 && - block.getConstraintExcludeBottomLayers() < currentLevel - ) { - - int targetBlockPosition = getMineTargetPrisonBlocks().size(); - block.setRangeBlockCountHighLimit( targetBlockPosition ); - - } - } - - } +// private void trackConstraints( int currentLevel, List constrainedBlocks ) +// { +// +// // If the constrainedBlocks list has not be configured, set it up with the +// // blocks that have constraints: +// if ( constrainedBlocks == null ) { +// +// constrainedBlocks = new ArrayList<>(); +// +// for (PrisonBlock block : getPrisonBlocks()) { +// if ( block.getConstraintExcludeTopLayers() > 0 || +// block.getConstraintExcludeBottomLayers() > 0 ) { +// +// constrainedBlocks.add( block ); +// } +// } +// } +// +// +// // If there are any constrained blocks, then need to record +// for ( PrisonBlockStatusData block : constrainedBlocks ) { +// +// // If exclude top layers is enabled, then only try to set the +// // rangeBlockCountLowLimit once since we need the lowest possible +// // value. The inital value for getRangeBlockCountLowLimit is -1. +// if ( block.getConstraintExcludeTopLayers() > 0 && +// block.getRangeBlockCountLowLimit() <= 0 && +// currentLevel > block.getConstraintExcludeTopLayers() ) { +// +// int targetBlockPosition = getMineTargetPrisonBlocks().size(); +// block.setRangeBlockCountLowLimit( targetBlockPosition ); +// } +// +// // If exclude bottom layer is enabled, then we need to track every number +// // until the currentLevel exceeds the getConstraintExcludeBottomLayers value. +// // If exclude top layers, then do not record for the bottom layers until +// // the top layers is cleared. +// if ( (block.getConstraintExcludeTopLayers() > 0 && +// currentLevel > block.getConstraintExcludeTopLayers() || +// block.getConstraintExcludeTopLayers() == 0) && +// +// block.getConstraintExcludeBottomLayers() > 0 && +// block.getConstraintExcludeBottomLayers() < currentLevel +// ) { +// +// int targetBlockPosition = getMineTargetPrisonBlocks().size(); +// block.setRangeBlockCountHighLimit( targetBlockPosition ); +// +// } +// } +// +// } /** * @@ -1475,57 +1485,57 @@ else if ( getPercentRemainingBlockCount() > getSkipResetPercent() ) { - private PrisonBlock randomlySelectPrisonBlock( Random random, int currentLevel ) { - - int targetBlockPosition = getMineTargetPrisonBlocks().size(); - - PrisonBlock prisonBlock = Prison.get().getPlatform().getPrisonBlock( "AIR" ); - - - // this fallbackBlock field will provide a valid block that can be used when all other - // blocks have failed to be matched due to constraints not aligning with the random chance. - // As a result of failing to find a block, would result in an AIR block being used instead. - PrisonBlock fallbackBlock = null; - - - // If a chosen block was skipped, try to find another block, but try no more than 10 times - // to prevent a possible endless loop. Side effects of failing to find a block in 10 attempts - // would be an air block. - boolean success = false; - int attempts = 0; - while ( !success && attempts++ < 10 ) { - double chance = random.nextDouble() * 100.0d; - - for (PrisonBlock block : getPrisonBlocks()) { - boolean isBlockEnabled = block.isBlockConstraintsEnbled( currentLevel, targetBlockPosition ); - - if ( fallbackBlock == null && isBlockEnabled && !block.isAir() ) { - fallbackBlock = block; - } - - if ( chance <= block.getChance() && isBlockEnabled ) { - - // If this block is chosen and it was not skipped, then use this block and exit. - // Otherwise the chance will be recalculated and tried again to find a valid block, - // since the odds have been thrown off... - prisonBlock = block; - - // stop trying to locate a block so success will terminate the search: - success = true; - - break; - } else { - chance -= block.getChance(); - } - } - - if ( !success && fallbackBlock != null ) { - prisonBlock = fallbackBlock; - success = true; - } - } - return prisonBlock; - } +// private PrisonBlock randomlySelectPrisonBlock( Random random, int currentLevel ) { +// +// int targetBlockPosition = getMineTargetPrisonBlocks().size(); +// +// PrisonBlock prisonBlock = Prison.get().getPlatform().getPrisonBlock( "AIR" ); +// +// +// // this fallbackBlock field will provide a valid block that can be used when all other +// // blocks have failed to be matched due to constraints not aligning with the random chance. +// // As a result of failing to find a block, would result in an AIR block being used instead. +// PrisonBlock fallbackBlock = null; +// +// +// // If a chosen block was skipped, try to find another block, but try no more than 10 times +// // to prevent a possible endless loop. Side effects of failing to find a block in 10 attempts +// // would be an air block. +// boolean success = false; +// int attempts = 0; +// while ( !success && attempts++ < 10 ) { +// double chance = random.nextDouble() * 100.0d; +// +// for (PrisonBlock block : getPrisonBlocks()) { +// boolean isBlockEnabled = block.isBlockConstraintsEnbled( currentLevel, targetBlockPosition ); +// +// if ( fallbackBlock == null && isBlockEnabled && !block.isAir() ) { +// fallbackBlock = block; +// } +// +// if ( chance <= block.getChance() && isBlockEnabled ) { +// +// // If this block is chosen and it was not skipped, then use this block and exit. +// // Otherwise the chance will be recalculated and tried again to find a valid block, +// // since the odds have been thrown off... +// prisonBlock = block; +// +// // stop trying to locate a block so success will terminate the search: +// success = true; +// +// break; +// } else { +// chance -= block.getChance(); +// } +// } +// +// if ( !success && fallbackBlock != null ) { +// prisonBlock = fallbackBlock; +// success = true; +// } +// } +// return prisonBlock; +// } private BlockOld randomlySelectBlock( Random random, int currentLevel ) { From bc1cfa2d84dc42b2ebbb29ec98ab47764b5c35f3 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Mon, 22 Nov 2021 17:49:20 -0500 Subject: [PATCH 132/283] When using autosell through auto features, if a block cannot be sold, then the block is now placed in the player's inventory, or dropped if their inventory is full. If a block is unable to be sold, the amount returned for the item stack will be zero. --- docs/changelog_v3.3.x.md | 4 +++ .../autofeatures/AutoManagerFeatures.java | 29 +++++++++++++++---- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 12b40ef34..ab8f35ff4 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.5 2021-11-22 +* **When using autosell through auto features, if a block cannot be sold, then the block is now placed in the player's inventory, or dropped if their inventory is full.** +If a block is unable to be sold, the amount returned for the item stack will be zero. + + * **Bug Fix: There was originally a problem with applying block constraints that resulted in being unable to select a block when trying to randomly choose one.** Initially as a first quick fix was to trying to reselect a block, but if the block chances were really low, then it could still fail to select a block. Then it was attempted to select a default block, but that too failed to work, especially if there were a sizable chance for AIR, and it would fail 100% of the time if the was only one block with a very low chance. The failure was the whole mine could be filled with that one block with the very small chance. This fix completely redesigns the block selection, by first selecting only the blocks that are valid for that level of the mine. That way, when selecting blocks where blocks should be excluded from that level, those excluded blocks are never in the selected blocks to be considered. Also if AIR is a valid option, then this new process adds an AIR block to the temporary level block list with the percent chance assigned to the air. diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java index 767fe23c3..2a1b20064 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java @@ -492,12 +492,14 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, double autosellTotal = 0; + double autosellUnsellableCount = 0; for ( SpigotItemStack itemStack : drops ) { count += itemStack.getAmount(); + // Try to autosell if enabled: if (isBoolean(AutoFeatures.isAutoSellPerBlockBreakEnabled) || pmEvent.isForceAutoSell() ) { @@ -507,12 +509,26 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, PlayerCache.getInstance().addPlayerEarnings( pmEvent.getSpigotPlayer(), amount, mineName ); - debugInfo.append( "(sold: " + itemStack.getName() + " qty: " + itemStack.getAmount() + " value: " + amount + ") "); + if ( amount != 0 ) { + debugInfo.append( "(sold: " + itemStack.getName() + " qty: " + itemStack.getAmount() + " value: " + amount + ") "); + + // Set to zero quantity since they have all been sold. + itemStack.setAmount( 0 ); + } + else { + + // Unable to sell since amount was zero. Not configured to be sold. + debugInfo.append( "(unsellable: " + itemStack.getName() + " qty: " + itemStack.getAmount() + ") "); + autosellUnsellableCount += itemStack.getAmount(); + } - // Set to zero quantity since they have all been sold. - itemStack.setAmount( 0 ); } - else { + + + // Add blocks to player's inventory IF autosell is disabled or the item had a value of ZERO + // which indicates it cannot be sold. If it could not be sold, then amount would be non-zero since + // sold will zero out the number of drops for that item stack. + if ( !isBoolean(AutoFeatures.isAutoSellPerBlockBreakEnabled) || itemStack.getAmount() != 0 ) { if ( Output.get().isDebug() ) { @@ -520,7 +536,7 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, double amount = SellAllUtil.get().sellAllSell( player, itemStack, true, false, false ); autosellTotal += amount; - debugInfo.append( "(adding: " + itemStack.getName() + " qty: " + itemStack.getAmount() + " value: " + amount + ") "); + debugInfo.append( "(keeping: " + itemStack.getName() + " qty: " + itemStack.getAmount() + " value: " + amount + ") "); } HashMap extras = SpigotUtil.addItemToPlayerInventory( player, itemStack ); @@ -554,7 +570,8 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, if ( count > 0 || autosellTotal > 0 ) { - debugInfo.append( "[autoPickupDrops total: qty: " + count + " value: " + autosellTotal + ") "); + debugInfo.append( "[autoPickupDrops total: qty: " + count + " value: " + autosellTotal + + " unsellableCount: " + autosellUnsellableCount + " ] "); } From c1f006b651a4aca0d66ffb21a8562339b0507e21 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Tue, 23 Nov 2021 06:09:23 -0500 Subject: [PATCH 133/283] Shut down auto manager and all auto features if the setting 'autoManager.isAutoManagerEnabled' is set to 'false' in autoFeaturesConfig.yml. If anyone wants to use prison's block events, then they must use the auto manager. --- docs/changelog_v3.3.x.md | 6 +- .../tech/mcprison/prison/PrisonCommand.java | 178 +++++++++--------- .../api/PrisonMinesBlockBreakEvent.java | 6 + .../spigot/block/OnBlockBreakEventCore.java | 3 + .../block/OnBlockBreakEventListener.java | 19 +- 5 files changed, 121 insertions(+), 91 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index ab8f35ff4..d11472e36 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,11 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.5 2021-11-22 +# 3.2.11-alpha.5 2021-11-23 + + +* **Shut down auto manager and all auto features if the setting 'autoManager.isAutoManagerEnabled' is set to 'false' in autoFeaturesConfig.yml.** +If anyone wants to use prison's block events, then they must use the auto manager. * **When using autosell through auto features, if a block cannot be sold, then the block is now placed in the player's inventory, or dropped if their inventory is full.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java b/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java index 4f373c678..6db8f9709 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java +++ b/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java @@ -894,94 +894,96 @@ public void autoFeaturesInformation(CommandSender sender) { afw.isBoolean( AutoFeatures.isAutoManagerEnabled )); - - - display.addText( "&b " ); - display.addText( "&b options.blockBreakEvents.applyBlockBreaksThroughSyncTask: %s", - afw.getMessage( AutoFeatures.applyBlockBreaksThroughSyncTask ) ); - - display.addText( "&b options.blockBreakEvents.cancelAllBlockBreakEvents: %s", - afw.getMessage( AutoFeatures.cancelAllBlockBreakEvents ) ); - - display.addText( "&b options.blockBreakEvents.cancelAllBlockEventBlockDrops: %s", - afw.getMessage( AutoFeatures.cancelAllBlockEventBlockDrops ) ); - - - display.addText( "&b options.blockBreakEvents.TokenEnchantBlockExplodeEventPriority: %s", - afw.getMessage( AutoFeatures.TokenEnchantBlockExplodeEventPriority ) ); - - display.addText( "&b options.blockBreakEvents.CrazyEnchantsBlastUseEventPriority: %s", - afw.getMessage( AutoFeatures.CrazyEnchantsBlastUseEventPriority ) ); - - display.addText( "&b options.blockBreakEvents.ZenchantmentsBlockShredEventPriority: %s", - afw.getMessage( AutoFeatures.ZenchantmentsBlockShredEventPriority ) ); - - display.addText( "&b options.blockBreakEvents.PrisonEnchantsExplosiveEventPriority: %s", - afw.getMessage( AutoFeatures.PrisonEnchantsExplosiveEventPriority ) ); - - display.addText( "&b options.blockBreakEvents.ProcessPrisons_ExplosiveBlockBreakEventsPriority: %s", - afw.getMessage( AutoFeatures.ProcessPrisons_ExplosiveBlockBreakEventsPriority ) ); - - - - display.addText( "&b " ); - display.addText( "&b Normal Drops (if auto pickup is off):" ); - display.addText( "&b options.normalDrop.isProcessNormalDropsEvents: %s", - afw.isBoolean( AutoFeatures.handleNormalDropsEvents ) ); - - display.addText( "&b " ); - display.addText( "&7 NOTE: If this is enabled, then lore and perms will override the settings for " ); - display.addText( "&7 pickup, smelt, and block when they are turned off." ); - - - display.addText( "&b " ); - - - display.addText( "&b options.autoPickup.autoPickupEnabled %s", - afw.isBoolean( AutoFeatures.autoPickupEnabled )); - - display.addText( "&b options.autoSmelt.autoSmeltEnabled %s", - afw.isBoolean( AutoFeatures.autoSmeltEnabled )); - display.addText( "&b options.autoBlock.autoBlockEnabled %s", - afw.isBoolean( AutoFeatures.autoBlockEnabled )); - - - - display.addText( "&b " ); - display.addText( "&b options.general.isCalculateDurabilityEnabled %s", - afw.isBoolean( AutoFeatures.isCalculateDurabilityEnabled )); - display.addText( "&b options.general.isCalculateFortuneEnabled %s", - afw.isBoolean( AutoFeatures.isCalculateFortuneEnabled )); - display.addText( "&b options.general.isCalculateAltFortuneOnAllBlocksEnabled %s", - afw.isBoolean( AutoFeatures.isCalculateAltFortuneOnAllBlocksEnabled )); - display.addText( "&b options.general.isCalculateXPEnabled %s", - afw.isBoolean( AutoFeatures.isCalculateXPEnabled )); - display.addText( "&b options.general.givePlayerXPAsOrbDrops %s", - afw.isBoolean( AutoFeatures.givePlayerXPAsOrbDrops )); - display.addText( "&b options.general.fortuneMultiplierMax %s", - afw.getMessage( AutoFeatures.fortuneMultiplierMax )); - - display.addText( "&b " ); - display.addText( "&b options.isProcessMcMMOBlockBreakEvents %s", - afw.isBoolean( AutoFeatures.isProcessMcMMOBlockBreakEvents )); - display.addText( "&b " ); - - - display.addText( "&b " ); - display.addText( "&b options.lore.isLoreEnabled %s", - afw.isBoolean( AutoFeatures.isLoreEnabled )); - display.addText( "&b options.lore.loreTrackBlockBreakCount %s", - afw.isBoolean( AutoFeatures.loreTrackBlockBreakCount )); - display.addText( "&b options.lore.loreBlockBreakCountName %s", - afw.getMessage( AutoFeatures.loreBlockBreakCountName )); - - display.addText( "&b options.lore.loreBlockExplosionCountName %s", - afw.getMessage( AutoFeatures.loreBlockExplosionCountName )); - display.addText( "&b options.lore.loreDurabiltyResistance %s", - afw.isBoolean( AutoFeatures.loreDurabiltyResistance )); - display.addText( "&b options.lore.loreDurabiltyResistanceName %s", - afw.getMessage( AutoFeatures.loreDurabiltyResistanceName )); - display.addText( "&b " ); + if ( afw.isBoolean( AutoFeatures.isAutoManagerEnabled ) ) { + + + display.addText( "&b " ); + display.addText( "&b options.blockBreakEvents.applyBlockBreaksThroughSyncTask: %s", + afw.getMessage( AutoFeatures.applyBlockBreaksThroughSyncTask ) ); + + display.addText( "&b options.blockBreakEvents.cancelAllBlockBreakEvents: %s", + afw.getMessage( AutoFeatures.cancelAllBlockBreakEvents ) ); + + display.addText( "&b options.blockBreakEvents.cancelAllBlockEventBlockDrops: %s", + afw.getMessage( AutoFeatures.cancelAllBlockEventBlockDrops ) ); + + + display.addText( "&b options.blockBreakEvents.TokenEnchantBlockExplodeEventPriority: %s", + afw.getMessage( AutoFeatures.TokenEnchantBlockExplodeEventPriority ) ); + + display.addText( "&b options.blockBreakEvents.CrazyEnchantsBlastUseEventPriority: %s", + afw.getMessage( AutoFeatures.CrazyEnchantsBlastUseEventPriority ) ); + + display.addText( "&b options.blockBreakEvents.ZenchantmentsBlockShredEventPriority: %s", + afw.getMessage( AutoFeatures.ZenchantmentsBlockShredEventPriority ) ); + + display.addText( "&b options.blockBreakEvents.PrisonEnchantsExplosiveEventPriority: %s", + afw.getMessage( AutoFeatures.PrisonEnchantsExplosiveEventPriority ) ); + + display.addText( "&b options.blockBreakEvents.ProcessPrisons_ExplosiveBlockBreakEventsPriority: %s", + afw.getMessage( AutoFeatures.ProcessPrisons_ExplosiveBlockBreakEventsPriority ) ); + + + + display.addText( "&b " ); + display.addText( "&b Normal Drops (if auto pickup is off):" ); + display.addText( "&b options.normalDrop.isProcessNormalDropsEvents: %s", + afw.isBoolean( AutoFeatures.handleNormalDropsEvents ) ); + + display.addText( "&b " ); + display.addText( "&7 NOTE: If this is enabled, then lore and perms will override the settings for " ); + display.addText( "&7 pickup, smelt, and block when they are turned off." ); + + + display.addText( "&b " ); + + + display.addText( "&b options.autoPickup.autoPickupEnabled %s", + afw.isBoolean( AutoFeatures.autoPickupEnabled )); + + display.addText( "&b options.autoSmelt.autoSmeltEnabled %s", + afw.isBoolean( AutoFeatures.autoSmeltEnabled )); + display.addText( "&b options.autoBlock.autoBlockEnabled %s", + afw.isBoolean( AutoFeatures.autoBlockEnabled )); + + + + display.addText( "&b " ); + display.addText( "&b options.general.isCalculateDurabilityEnabled %s", + afw.isBoolean( AutoFeatures.isCalculateDurabilityEnabled )); + display.addText( "&b options.general.isCalculateFortuneEnabled %s", + afw.isBoolean( AutoFeatures.isCalculateFortuneEnabled )); + display.addText( "&b options.general.isCalculateAltFortuneOnAllBlocksEnabled %s", + afw.isBoolean( AutoFeatures.isCalculateAltFortuneOnAllBlocksEnabled )); + display.addText( "&b options.general.isCalculateXPEnabled %s", + afw.isBoolean( AutoFeatures.isCalculateXPEnabled )); + display.addText( "&b options.general.givePlayerXPAsOrbDrops %s", + afw.isBoolean( AutoFeatures.givePlayerXPAsOrbDrops )); + display.addText( "&b options.general.fortuneMultiplierMax %s", + afw.getMessage( AutoFeatures.fortuneMultiplierMax )); + + display.addText( "&b " ); + display.addText( "&b options.isProcessMcMMOBlockBreakEvents %s", + afw.isBoolean( AutoFeatures.isProcessMcMMOBlockBreakEvents )); + display.addText( "&b " ); + + + display.addText( "&b " ); + display.addText( "&b options.lore.isLoreEnabled %s", + afw.isBoolean( AutoFeatures.isLoreEnabled )); + display.addText( "&b options.lore.loreTrackBlockBreakCount %s", + afw.isBoolean( AutoFeatures.loreTrackBlockBreakCount )); + display.addText( "&b options.lore.loreBlockBreakCountName %s", + afw.getMessage( AutoFeatures.loreBlockBreakCountName )); + + display.addText( "&b options.lore.loreBlockExplosionCountName %s", + afw.getMessage( AutoFeatures.loreBlockExplosionCountName )); + display.addText( "&b options.lore.loreDurabiltyResistance %s", + afw.isBoolean( AutoFeatures.loreDurabiltyResistance )); + display.addText( "&b options.lore.loreDurabiltyResistanceName %s", + afw.getMessage( AutoFeatures.loreDurabiltyResistanceName )); + display.addText( "&b " ); + } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockBreakEvent.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockBreakEvent.java index d04ff38d0..627317d97 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockBreakEvent.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockBreakEvent.java @@ -98,6 +98,12 @@ public class PrisonMinesBlockBreakEvent private boolean monitor = false; + + + // blockEventsOnly was intended to be able to run the block events when + // the the AutoManager is disabled. But now, as of 2021-11-23, if + // AutoManager is disabled, then nothing related to auto features, + // including block events will be active. private boolean blockEventsOnly = false; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index c944f0e9d..85cea405f 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -826,6 +826,9 @@ else if ( results ) { if ( results && pmEvent.isBlockEventsOnly() ) { + // NOTE: This "should" never be activated since blockEventsOnly used to be enabled + // when AutoManager is disabled. As of 2021-11-23 if AutoManager is disabled, + // then everything related to auto manager is disabled. String triggered = null; doActionBlockEventOnly( pmEvent.getSpigotBlock(), mine, pmEvent.getPlayer(), diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventListener.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventListener.java index f481196cc..527e4ec89 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventListener.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventListener.java @@ -1,5 +1,6 @@ package tech.mcprison.prison.spigot.block; +import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerBlockBreakEvents; @@ -124,9 +125,23 @@ public void registerAllBlockBreakEvents(SpigotPrison spigotPrison ) { // Only register these event listeners if these are enabled. // In order to be enabled, the prison mines module must be enabled. + if ( !isBoolean(AutoFeatures.isAutoManagerEnabled) ) { + + Output.get().logWarn( "AutoMager: AutoFeatures is dsabled. " + + "No block break listeners are registered. " + + "The setting 'autoManager.isAutoManagerEnabled' is set to 'false' " + + "in autoFeaturesConfig.yml." ); + + return; + } + if ( isEnabled() ) { + Output.get().logInfo( "AutoManager: AutoFeatures and the Mine module are enabled. Prison " + + "will register the selected block break listeners." ); + + // This will register all events that should be enabled, for both // auto manager and the normal events too. new AutoManagerBlockBreakEvents().registerEvents(); @@ -135,8 +150,8 @@ public void registerAllBlockBreakEvents(SpigotPrison spigotPrison ) { } else { - Output.get().logWarn( "BlockBreak event listeners cannot be registered " + - "since the mine module is disabled." ); + Output.get().logWarn( "AutoManager: AutoFeaturs are enabled, but the Mines module is disabled." + + "Prison will not register any block break listeners." ); } } From 20dfc8742c143637889ddb50e802f64473fef75d Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Tue, 23 Nov 2021 06:15:26 -0500 Subject: [PATCH 134/283] Setup a mutex for locking the mine resets, which prevents active block break attempts, including explosions, from trying to break blocks while a mine is actively being reset. --- docs/changelog_v3.3.x.md | 4 + .../mcprison/prison/mines/data/MineData.java | 11 +++ .../mines/tasks/MinePagedResetAsyncTask.java | 15 ++++ .../AutoManagerBreakBlockTask.java | 41 +++++++-- .../spigot/block/OnBlockBreakEventCore.java | 89 +++++++++++++++++-- .../spigot/utils/PrisonBombListener.java | 2 +- 6 files changed, 150 insertions(+), 12 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index d11472e36..d4a7c5313 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.5 2021-11-23 +* **Setup a mutex for locking the mine resets, which prevents active block break attempts, including explosions, from trying to break blocks while a mine is actively being reset.** +This helps to reduce the chance of hitting a concurrent modification exception. + + * **Shut down auto manager and all auto features if the setting 'autoManager.isAutoManagerEnabled' is set to 'false' in autoFeaturesConfig.yml.** If anyone wants to use prison's block events, then they must use the auto manager. diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java index dc8a77cc1..dda88e9a0 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java @@ -44,6 +44,11 @@ public abstract class MineData private boolean enabled = false; private boolean virtual = false; + + // Controls if a mine is able to be used during a mine reset: + private MineStateMutex mineStateMutex; + + private MineType mineType; private MineGroup mineGroup; @@ -185,6 +190,9 @@ public static MineNotificationMode fromString(String mode, MineNotificationMode } public MineData() { + + this.mineStateMutex = new MineStateMutex(); + this.elementType = ModuleElementType.MINE; this.tag = null; @@ -1343,4 +1351,7 @@ public void setDeleted( boolean isDeleted ) { this.isDeleted = isDeleted; } + public MineStateMutex getMineStateMutex() { + return mineStateMutex; + } } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java index d8882b719..58a451fd5 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java @@ -175,6 +175,11 @@ public void run() { * This calls the functions to */ private boolean runSetupCancelReset() { + + // Set the MineStateMutex to a state of starting a mine reset: + mine.getMineStateMutex().setMineStateResetStart(); + + if ( resetType == MineResetType.normal || resetType == MineResetType.paged ) { mine.generateBlockListAsync(); @@ -192,7 +197,17 @@ private boolean runSetupCancelReset() { private void runShutdown() { logStats(); + + + // Set the MineStateMutex to a state of Finishing a mine reset: + // It is now safe to allow mining in the mine. + mine.getMineStateMutex().setMineStateResetFinished(); + + + // Run items such as post-mine-reset commands: mine.asynchronouslyResetFinalize(); + + } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerBreakBlockTask.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerBreakBlockTask.java index 9e5758344..cf6ef2e0c 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerBreakBlockTask.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerBreakBlockTask.java @@ -3,6 +3,8 @@ import java.util.List; import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.mines.data.Mine; +import tech.mcprison.prison.mines.data.MineStateMutex; import tech.mcprison.prison.spigot.block.SpigotBlock; import tech.mcprison.prison.tasks.PrisonRunnable; import tech.mcprison.prison.tasks.PrisonTaskSubmitter; @@ -13,30 +15,45 @@ public class AutoManagerBreakBlockTask private SpigotBlock block; private List blocks; - public AutoManagerBreakBlockTask( SpigotBlock block ) { + private Mine mine; + private MineStateMutex mineStateMutexClone; + + public AutoManagerBreakBlockTask( SpigotBlock block, Mine mine ) { super(); this.block = block; this.blocks = null; + + this.mine = mine; + + if ( mine != null ) { + this.mineStateMutexClone = mine.getMineStateMutex().clone(); + } } - public AutoManagerBreakBlockTask( List blocks ) { + public AutoManagerBreakBlockTask( List blocks, Mine mine ) { super(); this.block = null; this.blocks = blocks; + + this.mine = mine; + + if ( mine != null ) { + this.mineStateMutexClone = mine.getMineStateMutex().clone(); + } } - public static void submitTask( SpigotBlock block ) { + public static void submitTask( SpigotBlock block, Mine mine ) { - AutoManagerBreakBlockTask blockTask = new AutoManagerBreakBlockTask( block ); + AutoManagerBreakBlockTask blockTask = new AutoManagerBreakBlockTask( block, mine ); PrisonTaskSubmitter.runTaskLater( blockTask, 0 ); } - public static void submitTask( List blocks ) { + public static void submitTask( List blocks, Mine mine ) { - AutoManagerBreakBlockTask blockTask = new AutoManagerBreakBlockTask( blocks ); + AutoManagerBreakBlockTask blockTask = new AutoManagerBreakBlockTask( blocks, mine ); PrisonTaskSubmitter.runTaskLater( blockTask, 0 ); } @@ -44,14 +61,26 @@ public static void submitTask( List blocks ) { @Override public void run() { + if ( mineStateMutexClone != null && + !mine.getMineStateMutex().isValidState( mineStateMutexClone ) ) { + return; + } + // // Set the broken block to AIR and cancel the event if ( block != null && !block.isEmpty() ) { + block.setPrisonBlock( PrisonBlock.AIR ); } if ( blocks != null ) { + int count = 0; for ( SpigotBlock spigotBlock : blocks ) { + if ( count++ % 10 == 0 && mineStateMutexClone != null && + !mine.getMineStateMutex().isValidState( mineStateMutexClone ) ) { + return; + } + spigotBlock.setPrisonBlock( PrisonBlock.AIR ); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index 85cea405f..7b3ab8cab 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -299,17 +299,31 @@ protected void genericBlockEvent( BlockBreakEvent e, boolean monitor, boolean bl // Check to see if the event should be ignored. SpigotBlock sBlock = new SpigotBlock( e.getBlock() ); + if ( BlockUtils.getInstance().isUnbreakable( sBlock ) ) { + e.setCancelled( true ); + return; + } Mine mine = findMine( e.getPlayer(), sBlock, null, null ); - if ( mine == null ) { + if ( mine == null ) { // Prison is unable to process blocks outside of mines right now, so exit: return; } + + // If not minable, then display message and exit. + if ( !mine.getMineStateMutex().isMinable() ) { + + SpigotPlayer sPlayer = new SpigotPlayer( e.getPlayer() ); + sPlayer.setActionBar( "Mine " + mine.getTag() + " is being reset... please wait." ); + e.setCancelled( true ); + return; + } MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); // If ignore all block events, then exit this function without logging anything: if ( targetBlock.isIgnoreAllBlockEvents() ) { + e.setCancelled( true ); return; } @@ -455,12 +469,21 @@ private void finalizeBreakTheBlocks( PrisonMinesBlockBreakEvent pmEvent ) if ( isBoolean( AutoFeatures.applyBlockBreaksThroughSyncTask ) ) { - AutoManagerBreakBlockTask.submitTask( blocks ); + AutoManagerBreakBlockTask.submitTask( blocks, pmEvent.getMine() ); } else { + int count = 0; for ( SpigotBlock spigotBlock : blocks ) { + if ( count++ % 10 == 0 && pmEvent.getMine() != null && + !pmEvent.getMine().getMineStateMutex().isMinable() ) { + + SpigotPlayer sPlayer = pmEvent.getSpigotPlayer(); + sPlayer.setActionBar( "Mine " + pmEvent.getMine().getTag() + " is being reset... please wait." ); + break; + } + spigotBlock.setPrisonBlock( PrisonBlock.AIR ); } } @@ -974,6 +997,10 @@ private void genericBlockExplodeEvent( TEBlockExplodeEvent e, boolean monitor, b // Check to see if the event should be ignored. SpigotBlock sBlock = new SpigotBlock( e.getBlock() ); + if ( BlockUtils.getInstance().isUnbreakable( sBlock ) ) { + e.setCancelled( true ); + return; + } Mine mine = findMine( e.getPlayer(), sBlock, e.blockList(), null ); @@ -981,10 +1008,20 @@ private void genericBlockExplodeEvent( TEBlockExplodeEvent e, boolean monitor, b // Prison is unable to process blocks outside of mines right now, so exit: return; } + + // If not minable, then display message and exit. + if ( !mine.getMineStateMutex().isMinable() ) { + + SpigotPlayer sPlayer = new SpigotPlayer( e.getPlayer() ); + sPlayer.setActionBar( "Mine " + mine.getTag() + " is being reset... please wait." ); + e.setCancelled( true ); + return; + } MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); // If ignore all block events, then exit this function without logging anything: if ( targetBlock.isIgnoreAllBlockEvents() ) { + e.setCancelled( true ); return; } @@ -1201,17 +1238,31 @@ protected void genericBlastUseEvent( BlastUseEvent e, boolean monitor, boolean b // Check to see if the event should be ignored. SpigotBlock sBlock = new SpigotBlock( e.getBlockList().get( 0 ) ); - + if ( BlockUtils.getInstance().isUnbreakable( sBlock ) ) { + e.setCancelled( true ); + return; + } + Mine mine = findMine( e.getPlayer(), sBlock, e.getBlockList(), null ); if ( mine == null ) { // Prison is unable to process blocks outside of mines right now, so exit: return; } + + // If not minable, then display message and exit. + if ( !mine.getMineStateMutex().isMinable() ) { + + SpigotPlayer sPlayer = new SpigotPlayer( e.getPlayer() ); + sPlayer.setActionBar( "Mine " + mine.getTag() + " is being reset... please wait." ); + e.setCancelled( true ); + return; + } MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); // If ignore all block events, then exit this function without logging anything: if ( targetBlock.isIgnoreAllBlockEvents() ) { + e.setCancelled( true ); return; } @@ -1397,17 +1448,31 @@ protected void genericExplosiveEvent( PEExplosionEvent e, boolean monitor, boole // Check to see if the event should be ignored. SpigotBlock sBlock = new SpigotBlock( e.getBlockBroken() ); - + if ( BlockUtils.getInstance().isUnbreakable( sBlock ) ) { + e.setCancelled( true ); + return; + } + Mine mine = findMine( e.getPlayer(), sBlock, e.getExplodedBlocks(), null ); if ( mine == null ) { // Prison is unable to process blocks outside of mines right now, so exit: return; } + + // If not minable, then display message and exit. + if ( !mine.getMineStateMutex().isMinable() ) { + + SpigotPlayer sPlayer = new SpigotPlayer( e.getPlayer() ); + sPlayer.setActionBar( "Mine " + mine.getTag() + " is being reset... please wait." ); + e.setCancelled( true ); + return; + } MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); // If ignore all block events, then exit this function without logging anything: if ( targetBlock.isIgnoreAllBlockEvents() ) { + e.setCancelled( true ); return; } @@ -1530,17 +1595,31 @@ protected void genericExplosiveEvent( ExplosiveBlockBreakEvent e, boolean monito // Check to see if the event should be ignored. SpigotBlock sBlock = new SpigotBlock( e.getBlock() ); - + if ( BlockUtils.getInstance().isUnbreakable( sBlock ) ) { + e.setCancelled( true ); + return; + } + Mine mine = findMine( e.getPlayer(), sBlock, e.getExplodedBlocks(), null ); if ( mine == null ) { // Prison is unable to process blocks outside of mines right now, so exit: return; } + + // If not minable, then display message and exit. + if ( !mine.getMineStateMutex().isMinable() ) { + + SpigotPlayer sPlayer = new SpigotPlayer( e.getPlayer() ); + sPlayer.setActionBar( "Mine " + mine.getTag() + " is being reset... please wait." ); + e.setCancelled( true ); + return; + } MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); // If ignore all block events, then exit this function without logging anything: if ( targetBlock.isIgnoreAllBlockEvents() ) { + e.setCancelled( true ); return; } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java index ae6a06cad..b5459de20 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java @@ -72,7 +72,7 @@ public void onInteract( PlayerInteractEvent event ) { // The item was a bomb and it was activated. // Cancel the event so the item will not be placed or processed farther. - Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent 03 Bomb detected - May not have been set. " ); +// Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent 03 Bomb detected - May not have been set. " ); event.setCancelled( true ); } From df380b2b094b6a0f22abc5648aba8cf6d4f56ade Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Tue, 23 Nov 2021 06:17:33 -0500 Subject: [PATCH 135/283] Setup a mutex for locking the mine resets, which prevents active block break attempts, including explosions, from trying to break blocks while a mine is actively being reset. --- .../prison/mines/data/MineStateMutex.java | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineStateMutex.java diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineStateMutex.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineStateMutex.java new file mode 100644 index 000000000..7dbef5007 --- /dev/null +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineStateMutex.java @@ -0,0 +1,99 @@ +package tech.mcprison.prison.mines.data; + +public class MineStateMutex +{ + private MineState mineState; + private int mineStateSn = 0; + + private boolean cloned = false; + + public enum MineState { + LOCKED, + UNLOCKED; + } + + public MineStateMutex() { + + this.mineState = MineState.UNLOCKED; + + this.mineStateSn = 0; + + this.cloned = false; + } + + private MineStateMutex( MineStateMutex cloneSource ) { + + this.mineState = cloneSource.getMineState(); + + this.mineStateSn = cloneSource.getMineStateSn(); + + this.cloned = true; + } + + public void setMineStateResetStart() { + + synchronized ( this ) { + + this.mineState = MineState.LOCKED; + this.mineStateSn++; + } + + } + + public void setMineStateResetFinished() { + + synchronized ( this ) { + + this.mineState = MineState.UNLOCKED; + } + + } + + public boolean isMinable() { + boolean results = false; + + synchronized ( this ) { + + if ( getMineState() == MineState.UNLOCKED ) { + + results = true; + } + } + + return results; + } + + public boolean isValidState( MineStateMutex mutex ) { + boolean results = false; + + synchronized ( this ) { + + if ( getMineState() == MineState.UNLOCKED && + getMineStateSn() == mutex.getMineStateSn() ) { + + results = true; + } + } + + return results; + } + + public MineStateMutex clone() { + MineStateMutex results = new MineStateMutex( this ); + + return results; + } + + public MineState getMineState() { + return mineState; + } + + public int getMineStateSn() { + return mineStateSn; + } + + public boolean isCloned() { + return cloned; + } + +} From 3639c686c5f3dcdb2e633f3c6f7afdbb6f34cf25 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Tue, 23 Nov 2021 12:23:41 -0500 Subject: [PATCH 136/283] Refactored some of the checks to determin if the event should be processed or not, so this can be used with a new feature that may help to auto manage access when WorldGuard is being used. --- docs/changelog_v3.3.x.md | 4 + .../spigot/block/OnBlockBreakEventCore.java | 471 +++++++++--------- .../spigot/block/OnBlockBreakMines.java | 212 ++++++++ 3 files changed, 453 insertions(+), 234 deletions(-) create mode 100644 prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakMines.java diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index d4a7c5313..4f9187a75 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.5 2021-11-23 + +* **Refactored some of the checks to determin if the event should be processed or not, so this can be used with a new feature that may help to auto manage access when WorldGuard is being used.** + + * **Setup a mutex for locking the mine resets, which prevents active block break attempts, including explosions, from trying to break blocks while a mine is actively being reset.** This helps to reduce the chance of hitting a concurrent modification exception. diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index 7b3ab8cab..ae3cc8af8 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -46,10 +46,9 @@ import tech.mcprison.prison.util.Text; public class OnBlockBreakEventCore + extends OnBlockBreakMines { - private PrisonMines prisonMineManager; - private boolean mineModuleDisabled = false; private int uses = 0; private long usesElapsedTimeNano = 0L; @@ -69,7 +68,7 @@ public OnBlockBreakEventCore() { this.autoFeatureWrapper = AutoFeaturesWrapper.getInstance(); - this.prisonMineManager = null; + this.teExplosionTriggerEnabled = true; @@ -275,6 +274,41 @@ protected void genericBlockExplodeEventAutoManager( ExplosiveBlockBreakEvent e ) genericExplosiveEvent( e, false, blockEventsOnly, true ); } +// protected boolean processMinesBlockBreakEvent( Cancellable event, Player player, Block block ) { +// boolean processEvent = true; +// +// SpigotBlock sBlock = new SpigotBlock( block ); +// if ( BlockUtils.getInstance().isUnbreakable( sBlock ) ) { +// event.setCancelled( true ); +// processEvent = false; +// } +// +// Mine mine = findMine( player, sBlock, null, null ); +// +// if ( mine == null ) { +// // Prison is unable to process blocks outside of mines right now, so exit: +// processEvent = false; +// } +// +// // If not minable, then display message and exit. +// if ( !mine.getMineStateMutex().isMinable() ) { +// +// SpigotPlayer sPlayer = new SpigotPlayer( player ); +// sPlayer.setActionBar( "Mine " + mine.getTag() + " is being reset... please wait." ); +// event.setCancelled( true ); +// processEvent = false; +// } +// MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); +// +// // If ignore all block events, then exit this function without logging anything: +// if ( targetBlock.isIgnoreAllBlockEvents() ) { +// event.setCancelled( true ); +// processEvent = false; +// } +// +// +// return processEvent; +// } /** *

This genericBlockEvent handles the basics of a BlockBreakEvent to see if it has happened @@ -295,39 +329,48 @@ protected void genericBlockEvent( BlockBreakEvent e, boolean monitor, boolean bl long start = System.nanoTime(); - if ( e.isCancelled() && !monitor ) { + if ( e.isCancelled() || ignoreMinesBlockBreakEvent( e, e.getPlayer(), e.getBlock()) ) { + return; + } + + +// if ( e.isCancelled() && !monitor ) { // Check to see if the event should be ignored. - SpigotBlock sBlock = new SpigotBlock( e.getBlock() ); - if ( BlockUtils.getInstance().isUnbreakable( sBlock ) ) { - e.setCancelled( true ); - return; - } - - Mine mine = findMine( e.getPlayer(), sBlock, null, null ); - - if ( mine == null ) { - // Prison is unable to process blocks outside of mines right now, so exit: - return; - } - - // If not minable, then display message and exit. - if ( !mine.getMineStateMutex().isMinable() ) { - - SpigotPlayer sPlayer = new SpigotPlayer( e.getPlayer() ); - sPlayer.setActionBar( "Mine " + mine.getTag() + " is being reset... please wait." ); - e.setCancelled( true ); - return; - } - MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); - - // If ignore all block events, then exit this function without logging anything: - if ( targetBlock.isIgnoreAllBlockEvents() ) { - e.setCancelled( true ); - return; - } +// if ( processMinesBlockBreakEvent( e, e.getPlayer(), e.getBlock()) ) { +// return; +// } +// +// SpigotBlock sBlock = new SpigotBlock( e.getBlock() ); +// if ( BlockUtils.getInstance().isUnbreakable( sBlock ) ) { +// e.setCancelled( true ); +// return; +// } +// +// Mine mine = findMine( e.getPlayer(), sBlock, null, null ); +// +// if ( mine == null ) { +// // Prison is unable to process blocks outside of mines right now, so exit: +// return; +// } +// +// // If not minable, then display message and exit. +// if ( !mine.getMineStateMutex().isMinable() ) { +// +// SpigotPlayer sPlayer = new SpigotPlayer( e.getPlayer() ); +// sPlayer.setActionBar( "Mine " + mine.getTag() + " is being reset... please wait." ); +// e.setCancelled( true ); +// return; +// } +// MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); +// +// // If ignore all block events, then exit this function without logging anything: +// if ( targetBlock.isIgnoreAllBlockEvents() ) { +// e.setCancelled( true ); +// return; +// } - } +// } // Register all external events such as mcMMO and EZBlocks: OnBlockBreakExternalEvents.getInstance().registerAllExternalEvents(); @@ -528,50 +571,7 @@ private List finalizeBreakTheBlocksCollectEm( PrisonMinesBlockBreak return blocks; } - private Mine findMine( Player player, SpigotBlock sBlock, - List altBlocksSource, PrisonMinesBlockBreakEvent pmEvent ) { - - Long playerUUIDLSB = Long.valueOf( player.getUniqueId().getLeastSignificantBits() ); - - // Get the cached mine, if it exists: - Mine mine = getPlayerCache().get( playerUUIDLSB ); - - if ( mine == null || - sBlock != null && !mine.isInMineExact( sBlock.getLocation() ) ) { - // Look for the correct mine to use. - // Set mine to null so if cannot find the right one it will return a null: - mine = findMineLocation( sBlock ); - - // Thanks to CrazyEnchant, where they do not identify the block the player breaks, we - // have to go through all of the unprecessedRawBlocks to see if any are within a mine. - // If we find a block that's in a mine, then use that block as the primary block. - if ( mine == null && altBlocksSource != null ) { - - for ( Block bBlock : altBlocksSource ) - { - SpigotBlock sBlockAltBlock = new SpigotBlock( bBlock ); - mine = findMineLocation( sBlockAltBlock ); - if ( mine != null ) { - - if ( pmEvent != null ) { - pmEvent.setSpigotBlock( sBlockAltBlock ); - } - - break; - } - } - } - - // Store the mine in the player cache if not null: - if ( mine != null ) { - getPlayerCache().put( playerUUIDLSB, mine ); - } - } - - return mine; - } - /** *

This function an attempt to provide a uniform procedure to validate if the event should @@ -993,39 +993,47 @@ private void genericBlockExplodeEvent( TEBlockExplodeEvent e, boolean monitor, b long start = System.nanoTime(); - if ( e.isCancelled() && !monitor ) { + if ( e.isCancelled() || ignoreMinesBlockBreakEvent( e, e.getPlayer(), e.getBlock()) ) { + return; + } + +// if ( e.isCancelled() && !monitor ) { // Check to see if the event should be ignored. - SpigotBlock sBlock = new SpigotBlock( e.getBlock() ); - if ( BlockUtils.getInstance().isUnbreakable( sBlock ) ) { - e.setCancelled( true ); - return; - } - - Mine mine = findMine( e.getPlayer(), sBlock, e.blockList(), null ); - - if ( mine == null ) { - // Prison is unable to process blocks outside of mines right now, so exit: - return; - } - - // If not minable, then display message and exit. - if ( !mine.getMineStateMutex().isMinable() ) { - - SpigotPlayer sPlayer = new SpigotPlayer( e.getPlayer() ); - sPlayer.setActionBar( "Mine " + mine.getTag() + " is being reset... please wait." ); - e.setCancelled( true ); - return; - } - MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); +// if ( processMinesBlockBreakEvent( e, e.getPlayer(), e.getBlock()) ) { +// return; +// } - // If ignore all block events, then exit this function without logging anything: - if ( targetBlock.isIgnoreAllBlockEvents() ) { - e.setCancelled( true ); - return; - } +// SpigotBlock sBlock = new SpigotBlock( e.getBlock() ); +// if ( BlockUtils.getInstance().isUnbreakable( sBlock ) ) { +// e.setCancelled( true ); +// return; +// } +// +// Mine mine = findMine( e.getPlayer(), sBlock, e.blockList(), null ); +// +// if ( mine == null ) { +// // Prison is unable to process blocks outside of mines right now, so exit: +// return; +// } +// +// // If not minable, then display message and exit. +// if ( !mine.getMineStateMutex().isMinable() ) { +// +// SpigotPlayer sPlayer = new SpigotPlayer( e.getPlayer() ); +// sPlayer.setActionBar( "Mine " + mine.getTag() + " is being reset... please wait." ); +// e.setCancelled( true ); +// return; +// } +// MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); +// +// // If ignore all block events, then exit this function without logging anything: +// if ( targetBlock.isIgnoreAllBlockEvents() ) { +// e.setCancelled( true ); +// return; +// } - } +// } // Register all external events such as mcMMO and EZBlocks: OnBlockBreakExternalEvents.getInstance().registerAllExternalEvents(); @@ -1234,39 +1242,47 @@ protected void genericBlastUseEvent( BlastUseEvent e, boolean monitor, boolean b long start = System.nanoTime(); - if ( e.isCancelled() && !monitor ) { + if ( e.isCancelled() || ignoreMinesBlockBreakEvent( e, e.getPlayer(), e.getBlockList().get( 0 )) ) { + return; + } + +// if ( e.isCancelled() && !monitor ) { // Check to see if the event should be ignored. - SpigotBlock sBlock = new SpigotBlock( e.getBlockList().get( 0 ) ); - if ( BlockUtils.getInstance().isUnbreakable( sBlock ) ) { - e.setCancelled( true ); - return; - } - - Mine mine = findMine( e.getPlayer(), sBlock, e.getBlockList(), null ); - - if ( mine == null ) { - // Prison is unable to process blocks outside of mines right now, so exit: - return; - } - - // If not minable, then display message and exit. - if ( !mine.getMineStateMutex().isMinable() ) { - - SpigotPlayer sPlayer = new SpigotPlayer( e.getPlayer() ); - sPlayer.setActionBar( "Mine " + mine.getTag() + " is being reset... please wait." ); - e.setCancelled( true ); - return; - } - MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); +// if ( processMinesBlockBreakEvent( e, e.getPlayer(), e.getBlockList().get( 0 ) ) ) { +// return; +// } - // If ignore all block events, then exit this function without logging anything: - if ( targetBlock.isIgnoreAllBlockEvents() ) { - e.setCancelled( true ); - return; - } +// SpigotBlock sBlock = new SpigotBlock( e.getBlockList().get( 0 ) ); +// if ( BlockUtils.getInstance().isUnbreakable( sBlock ) ) { +// e.setCancelled( true ); +// return; +// } +// +// Mine mine = findMine( e.getPlayer(), sBlock, e.getBlockList(), null ); +// +// if ( mine == null ) { +// // Prison is unable to process blocks outside of mines right now, so exit: +// return; +// } +// +// // If not minable, then display message and exit. +// if ( !mine.getMineStateMutex().isMinable() ) { +// +// SpigotPlayer sPlayer = new SpigotPlayer( e.getPlayer() ); +// sPlayer.setActionBar( "Mine " + mine.getTag() + " is being reset... please wait." ); +// e.setCancelled( true ); +// return; +// } +// MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); +// +// // If ignore all block events, then exit this function without logging anything: +// if ( targetBlock.isIgnoreAllBlockEvents() ) { +// e.setCancelled( true ); +// return; +// } - } +// } // Register all external events such as mcMMO and EZBlocks: OnBlockBreakExternalEvents.getInstance().registerAllExternalEvents(); @@ -1444,39 +1460,47 @@ protected void genericExplosiveEvent( PEExplosionEvent e, boolean monitor, boole long start = System.nanoTime(); - if ( e.isCancelled() && !monitor ) { + if ( e.isCancelled() || processMinesBlockBreakEvent( e, e.getPlayer(), e.getBlockBroken()) ) { + return; + } + +// if ( e.isCancelled() && !monitor ) { // Check to see if the event should be ignored. - SpigotBlock sBlock = new SpigotBlock( e.getBlockBroken() ); - if ( BlockUtils.getInstance().isUnbreakable( sBlock ) ) { - e.setCancelled( true ); - return; - } - - Mine mine = findMine( e.getPlayer(), sBlock, e.getExplodedBlocks(), null ); - - if ( mine == null ) { - // Prison is unable to process blocks outside of mines right now, so exit: - return; - } - - // If not minable, then display message and exit. - if ( !mine.getMineStateMutex().isMinable() ) { - - SpigotPlayer sPlayer = new SpigotPlayer( e.getPlayer() ); - sPlayer.setActionBar( "Mine " + mine.getTag() + " is being reset... please wait." ); - e.setCancelled( true ); - return; - } - MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); +// if ( processMinesBlockBreakEvent( e, e.getPlayer(), e.getBlockBroken()) ) { +// return; +// } - // If ignore all block events, then exit this function without logging anything: - if ( targetBlock.isIgnoreAllBlockEvents() ) { - e.setCancelled( true ); - return; - } +// SpigotBlock sBlock = new SpigotBlock( e.getBlockBroken() ); +// if ( BlockUtils.getInstance().isUnbreakable( sBlock ) ) { +// e.setCancelled( true ); +// return; +// } +// +// Mine mine = findMine( e.getPlayer(), sBlock, e.getExplodedBlocks(), null ); +// +// if ( mine == null ) { +// // Prison is unable to process blocks outside of mines right now, so exit: +// return; +// } +// +// // If not minable, then display message and exit. +// if ( !mine.getMineStateMutex().isMinable() ) { +// +// SpigotPlayer sPlayer = new SpigotPlayer( e.getPlayer() ); +// sPlayer.setActionBar( "Mine " + mine.getTag() + " is being reset... please wait." ); +// e.setCancelled( true ); +// return; +// } +// MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); +// +// // If ignore all block events, then exit this function without logging anything: +// if ( targetBlock.isIgnoreAllBlockEvents() ) { +// e.setCancelled( true ); +// return; +// } - } +// } // Register all external events such as mcMMO and EZBlocks: OnBlockBreakExternalEvents.getInstance().registerAllExternalEvents(); @@ -1591,39 +1615,47 @@ protected void genericExplosiveEvent( ExplosiveBlockBreakEvent e, boolean monito long start = System.nanoTime(); - if ( e.isCancelled() && !monitor ) { + if ( e.isCancelled() || ignoreMinesBlockBreakEvent( e, e.getPlayer(), e.getBlock()) ) { + return; + } + +// if ( e.isCancelled() && !monitor ) { // Check to see if the event should be ignored. - SpigotBlock sBlock = new SpigotBlock( e.getBlock() ); - if ( BlockUtils.getInstance().isUnbreakable( sBlock ) ) { - e.setCancelled( true ); - return; - } - - Mine mine = findMine( e.getPlayer(), sBlock, e.getExplodedBlocks(), null ); - - if ( mine == null ) { - // Prison is unable to process blocks outside of mines right now, so exit: - return; - } - - // If not minable, then display message and exit. - if ( !mine.getMineStateMutex().isMinable() ) { - - SpigotPlayer sPlayer = new SpigotPlayer( e.getPlayer() ); - sPlayer.setActionBar( "Mine " + mine.getTag() + " is being reset... please wait." ); - e.setCancelled( true ); - return; - } - MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); +// if ( processMinesBlockBreakEvent( e, e.getPlayer(), e.getBlock()) ) { +// return; +// } - // If ignore all block events, then exit this function without logging anything: - if ( targetBlock.isIgnoreAllBlockEvents() ) { - e.setCancelled( true ); - return; - } +// SpigotBlock sBlock = new SpigotBlock( e.getBlock() ); +// if ( BlockUtils.getInstance().isUnbreakable( sBlock ) ) { +// e.setCancelled( true ); +// return; +// } +// +// Mine mine = findMine( e.getPlayer(), sBlock, e.getExplodedBlocks(), null ); +// +// if ( mine == null ) { +// // Prison is unable to process blocks outside of mines right now, so exit: +// return; +// } +// +// // If not minable, then display message and exit. +// if ( !mine.getMineStateMutex().isMinable() ) { +// +// SpigotPlayer sPlayer = new SpigotPlayer( e.getPlayer() ); +// sPlayer.setActionBar( "Mine " + mine.getTag() + " is being reset... please wait." ); +// e.setCancelled( true ); +// return; +// } +// MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); +// +// // If ignore all block events, then exit this function without logging anything: +// if ( targetBlock.isIgnoreAllBlockEvents() ) { +// e.setCancelled( true ); +// return; +// } - } +// } // Register all external events such as mcMMO and EZBlocks: OnBlockBreakExternalEvents.getInstance().registerAllExternalEvents(); @@ -2076,19 +2108,19 @@ public void processBlockBreakage( PrisonMinesBlockBreakEvent pmEvent, StringBuil // return enabled; // } - - public void checkZeroBlockReset( Mine mine ) { - if ( mine != null ) { - - // submit a mine sweeper task. It will only run if it is enabled and another - // mine sweeper task has not been submitted. - mine.submitMineSweeperTask(); - - // Checks to see if the mine ran out of blocks, and if it did, then - // it will reset the mine: - mine.checkZeroBlockReset(); - } - } +// +// public void checkZeroBlockReset( Mine mine ) { +// if ( mine != null ) { +// +// // submit a mine sweeper task. It will only run if it is enabled and another +// // mine sweeper task has not been submitted. +// mine.submitMineSweeperTask(); +// +// // Checks to see if the mine ran out of blocks, and if it did, then +// // it will reset the mine: +// mine.checkZeroBlockReset(); +// } +// } private void applyBlockFinalizations( PrisonMinesBlockBreakEvent pmEvent, MineTargetPrisonBlock targetBlock ) { @@ -2718,38 +2750,9 @@ private int checkCrazyEnchant( Player player, Block block, ItemStack item ) { return bonusXp; } - - private Mine findMineLocation( SpigotBlock block ) { - return getPrisonMineManager() == null ? - null : getPrisonMineManager().findMineLocationExact( block.getLocation() ); - } - - private TreeMap getPlayerCache() { - return getPrisonMineManager() == null ? - new TreeMap() : - getPrisonMineManager().getPlayerCache(); - } - private PrisonMines getPrisonMineManager() { - if ( prisonMineManager == null && !isMineModuleDisabled() ) { - Optional mmOptional = Prison.get().getModuleManager().getModule( PrisonMines.MODULE_NAME ); - if ( mmOptional.isPresent() && mmOptional.get().isEnabled() ) { - PrisonMines prisonMines = (PrisonMines) mmOptional.get(); - this.prisonMineManager = prisonMines; - } else { - setMineModuleDisabled( true ); - } - } - return prisonMineManager; - } - private boolean isMineModuleDisabled() { - return mineModuleDisabled; - } - private void setMineModuleDisabled( boolean mineModuleDisabled ) { - this.mineModuleDisabled = mineModuleDisabled; - } @SuppressWarnings( "unused" ) diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakMines.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakMines.java new file mode 100644 index 000000000..16ae492c2 --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakMines.java @@ -0,0 +1,212 @@ +package tech.mcprison.prison.spigot.block; + +import java.util.List; +import java.util.Optional; +import java.util.TreeMap; + +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; + +import me.pulsi_.prisonenchants.events.PEExplosionEvent; +import tech.mcprison.prison.Prison; +import tech.mcprison.prison.internal.block.MineTargetPrisonBlock; +import tech.mcprison.prison.mines.PrisonMines; +import tech.mcprison.prison.mines.data.Mine; +import tech.mcprison.prison.modules.Module; +import tech.mcprison.prison.spigot.api.PrisonMinesBlockBreakEvent; +import tech.mcprison.prison.spigot.game.SpigotPlayer; +import tech.mcprison.prison.spigot.utils.BlockUtils; + +public class OnBlockBreakMines +{ + private PrisonMines prisonMineManager; + private boolean mineModuleDisabled = false; + + public OnBlockBreakMines() { + super(); + + this.prisonMineManager = null; + + } + + protected Mine findMine( Player player, SpigotBlock sBlock, List altBlocksSource, PrisonMinesBlockBreakEvent pmEvent ) + { + + Long playerUUIDLSB = Long.valueOf( player.getUniqueId().getLeastSignificantBits() ); + + // Get the cached mine, if it exists: + Mine mine = getPlayerCache().get( playerUUIDLSB ); + + if ( mine == null || sBlock != null && !mine.isInMineExact( sBlock.getLocation() ) ) + { + // Look for the correct mine to use. + // Set mine to null so if cannot find the right one it will return a + // null: + mine = findMineLocation( sBlock ); + + // Thanks to CrazyEnchant, where they do not identify the block the + // player breaks, we + // have to go through all of the unprecessedRawBlocks to see if any + // are within a mine. + // If we find a block that's in a mine, then use that block as the + // primary block. + if ( mine == null && altBlocksSource != null ) + { + + for ( Block bBlock : altBlocksSource ) + { + SpigotBlock sBlockAltBlock = new SpigotBlock( bBlock ); + mine = findMineLocation( sBlockAltBlock ); + if ( mine != null ) + { + + if ( pmEvent != null ) + { + pmEvent.setSpigotBlock( sBlockAltBlock ); + } + + break; + } + } + } + + // Store the mine in the player cache if not null: + if ( mine != null ) + { + getPlayerCache().put( playerUUIDLSB, mine ); + } + } + + return mine; + } + + + protected boolean ignoreMinesBlockBreakEvent( Cancellable event, Player player, Block block ) { + boolean ignoreEvent = false; + + SpigotBlock sBlock = new SpigotBlock( block ); + if ( BlockUtils.getInstance().isUnbreakable( sBlock ) ) { + event.setCancelled( true ); + ignoreEvent = true; + } + + Mine mine = findMine( player, sBlock, null, null ); + + if ( mine == null ) { + // Prison is unable to process blocks outside of mines right now, so exit: + ignoreEvent = true; + } + + // If not minable, then display message and exit. + if ( !mine.getMineStateMutex().isMinable() ) { + + SpigotPlayer sPlayer = new SpigotPlayer( player ); + sPlayer.setActionBar( "Mine " + mine.getTag() + " is being reset... please wait." ); + event.setCancelled( true ); + ignoreEvent = true; + } + MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); + + // If ignore all block events, then exit this function without logging anything: + if ( targetBlock.isIgnoreAllBlockEvents() ) { + event.setCancelled( true ); + ignoreEvent = true; + } + + + return ignoreEvent; + } + + /** + *

Warning... this is a temp copy of the real function and will be removed + * if PEExplosionEvent adds the interface Cancellable. + *

+ * + * @param event + * @param player + * @param block + * @return + */ + protected boolean processMinesBlockBreakEvent( PEExplosionEvent event, Player player, Block block ) { + boolean processEvent = true; + + SpigotBlock sBlock = new SpigotBlock( block ); + if ( BlockUtils.getInstance().isUnbreakable( sBlock ) ) { + event.setCancelled( true ); + processEvent = false; + } + + Mine mine = findMine( player, sBlock, null, null ); + + if ( mine == null ) { + // Prison is unable to process blocks outside of mines right now, so exit: + processEvent = false; + } + + // If not minable, then display message and exit. + if ( !mine.getMineStateMutex().isMinable() ) { + + SpigotPlayer sPlayer = new SpigotPlayer( player ); + sPlayer.setActionBar( "Mine " + mine.getTag() + " is being reset... please wait." ); + event.setCancelled( true ); + processEvent = false; + } + MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); + + // If ignore all block events, then exit this function without logging anything: + if ( targetBlock.isIgnoreAllBlockEvents() ) { + event.setCancelled( true ); + processEvent = false; + } + + + return processEvent; + } + + public void checkZeroBlockReset( Mine mine ) { + if ( mine != null ) { + + // submit a mine sweeper task. It will only run if it is enabled and another + // mine sweeper task has not been submitted. + mine.submitMineSweeperTask(); + + // Checks to see if the mine ran out of blocks, and if it did, then + // it will reset the mine: + mine.checkZeroBlockReset(); + } + } + + + private Mine findMineLocation( SpigotBlock block ) { + return getPrisonMineManager() == null ? + null : getPrisonMineManager().findMineLocationExact( block.getLocation() ); + } + + + private TreeMap getPlayerCache() { + return getPrisonMineManager() == null ? + new TreeMap() : + getPrisonMineManager().getPlayerCache(); + } + + private PrisonMines getPrisonMineManager() { + if ( prisonMineManager == null && !isMineModuleDisabled() ) { + Optional mmOptional = Prison.get().getModuleManager().getModule( PrisonMines.MODULE_NAME ); + if ( mmOptional.isPresent() && mmOptional.get().isEnabled() ) { + PrisonMines prisonMines = (PrisonMines) mmOptional.get(); + this.prisonMineManager = prisonMines; + } else { + setMineModuleDisabled( true ); + } + } + return prisonMineManager; + } + + private boolean isMineModuleDisabled() { + return mineModuleDisabled; + } + private void setMineModuleDisabled( boolean mineModuleDisabled ) { + this.mineModuleDisabled = mineModuleDisabled; + } +} From 06cb41543177c25846e0b46755affa77c726328f Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Tue, 23 Nov 2021 12:28:35 -0500 Subject: [PATCH 137/283] Added a check to detect that a block has been altered and is not the block that was placed there by the mine reset. There have been drops of other materials making it in to an explosion event, and mostly due to block changes that happen due to other means. --- docs/changelog_v3.3.x.md | 3 + .../internal/block/PrisonBlockStatusData.java | 17 +++++ .../spigot/block/OnBlockBreakEventCore.java | 67 ++++++++++++++++--- 3 files changed, 76 insertions(+), 11 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 4f9187a75..37247a545 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.5 2021-11-23 +* **Added a check to detect that a block has been altered and is not the block that was placed there by the mine reset.** +There have been drops of other materials making it in to an explosion event, and mostly due to block changes that happen due to other means. + * **Refactored some of the checks to determin if the event should be processed or not, so this can be used with a new feature that may help to auto manage access when WorldGuard is being used.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/block/PrisonBlockStatusData.java b/prison-core/src/main/java/tech/mcprison/prison/internal/block/PrisonBlockStatusData.java index 12998768e..c2ff50d8b 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/block/PrisonBlockStatusData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/block/PrisonBlockStatusData.java @@ -64,6 +64,23 @@ public PrisonBlockStatusData( String blockName, double chance, long blockCountTo this.gravity = checkGravityAffects( blockName ); } + + + @Override + public boolean equals( Object obj ) + { + boolean results = false; + + if ( obj instanceof PrisonBlockStatusData ) { + PrisonBlockStatusData pbsBlock = (PrisonBlockStatusData) obj; + + results = getBlockName().equalsIgnoreCase( pbsBlock.getBlockName() ); + } + + return results; + } + + public void resetAfterSave() { blockCountUnsaved = 0; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index ae3cc8af8..6a28082b5 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -638,6 +638,7 @@ private boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent, StringBuilder int outsideOfMine = 0; int alreadyMined = 0; int noTargetBlock = 0; + int blockTypeNotExpected = 0; boolean targetBlockAlreadyMined = false; @@ -645,7 +646,7 @@ private boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent, StringBuilder MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( pmEvent.getSpigotBlock() ); pmEvent.setTargetBlock( targetBlock ); - // If ignore all block evnts has been set on this target block, then shutdown + // If ignore all block events has been set on this target block, then shutdown if ( targetBlock.isIgnoreAllBlockEvents() ) { debugInfo.setLength( 0 ); @@ -671,7 +672,26 @@ private boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent, StringBuilder // being processed more than once: targetBlock.setMined( true ); - targetBlock.setMinedBlock( pmEvent.getSpigotBlock() ); + if ( targetBlock.getPrisonBlock().equals( pmEvent.getSpigotBlock().getPrisonBlock() ) ) { + + targetBlock.setMinedBlock( pmEvent.getSpigotBlock() ); + } + else { + // The block is not the correct type. It has been changed since the mine was reset + // so it cannot be processed. + + // Prevent this block from being processed again, or attempted to be processed: + + targetBlockAlreadyMined = true; + + targetBlock.setMined( true ); + targetBlock.setAirBroke( true ); + targetBlock.setIgnoreAllBlockEvents( true ); + + blockTypeNotExpected++; + } + + } else { alreadyMined++; @@ -705,6 +725,7 @@ private boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent, StringBuilder results = false; } + for ( Block bukkitBlock : pmEvent.getUnprocessedRawBlocks() ) { SpigotBlock sBlock = new SpigotBlock( bukkitBlock ); @@ -731,15 +752,35 @@ else if ( mine.isInMineExact( sBlock.getLocation() ) ) { } else if ( results && !targetExplodedBlock.isMined() ) { - // If a chain reaction on explosions, this will prevent the same block from - // being processed more than once: - targetExplodedBlock.setMined( true ); + // Check to make sure the block is the same block that was placed there. + // If not, then do not process it. + SpigotBlock sBlockMined = new SpigotBlock( bukkitBlock ); + + if ( targetExplodedBlock.getPrisonBlock().equals( sBlockMined.getPrisonBlock() ) ) { + + // If a chain reaction on explosions, this will prevent the same block from + // being processed more than once: + targetExplodedBlock.setMined( true ); + + targetExplodedBlock.setMinedBlock( sBlock ); + + pmEvent.getExplodedBlocks().add( sBlock ); + pmEvent.getTargetExplodedBlocks().add( targetExplodedBlock ); + } + else { + // The block is not the correct type. It has been changed since the mine was reset + // so it cannot be processed. + + // Prevent this block from being processed again, or attempted to be processed: + + targetExplodedBlock.setMined( true ); + targetExplodedBlock.setAirBroke( true ); + targetExplodedBlock.setIgnoreAllBlockEvents( true ); + + blockTypeNotExpected++; + } - targetExplodedBlock.setMinedBlock( sBlock ); - pmEvent.getExplodedBlocks().add( sBlock ); - pmEvent.getTargetExplodedBlocks().add( targetExplodedBlock ); - } } else if ( results ) { @@ -753,10 +794,9 @@ else if ( results ) { outsideOfMine++; } } - - } + if ( pmEvent.getExplodedBlocks().size() > 0 ) { debugInfo.append( "VALIDATED_BLOCKS_IN_EXPLOSION (" + @@ -783,6 +823,11 @@ else if ( results ) { debugInfo.append( "NO_TARGET_BLOCKS (" + noTargetBlock + " ) " ); } + if ( blockTypeNotExpected > 0 ) { + + debugInfo.append( "BLOCK_TYPE_NOT_EXPECTED__CANNOT_PROCESS (" + blockTypeNotExpected + + " ) " ); + } // If target block aready was mined and there are no exploded blocks, then this whole event From aa18930065af791604f7fdc6b22114ad73b76ff5 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Wed, 24 Nov 2021 00:08:34 -0500 Subject: [PATCH 138/283] Player cache timing improvements. This fixes issues with tracking the timing when mining. Not 100% sure it is perfect, but it's actually working much better. Will need to revisit later. --- docs/changelog_v3.3.x.md | 6 +- .../prison/cache/PlayerCachePlayerData.java | 164 +++++++++++------- 2 files changed, 103 insertions(+), 67 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 37247a545..3aa072f38 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,11 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.5 2021-11-23 +# 3.2.11-alpha.6 2021-11-24 + + +* **Player cache timing improvements.** This fixes issues with tracking the timing when mining. +Not 100% sure it is perfect, but it's actually working much better. Will need to revisit later. * **Added a check to detect that a block has been altered and is not the block that was placed there by the mine reset.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java index 761c19b64..61e054ed6 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java @@ -80,7 +80,7 @@ public class PlayerCachePlayerData { private transient SessionType sessionType; - private transient long sessionTimingStart = 0; +// private transient long sessionTimingStart = 0; private transient long sessionTimingLastCheck = 0; // sessionLastLocation is used for afk calculations: @@ -116,8 +116,8 @@ public PlayerCachePlayerData() { this.sessionType = SessionType.active; - this.sessionTimingStart = System.currentTimeMillis(); - this.sessionTimingLastCheck = sessionTimingStart; +// this.sessionTimingStart = System.currentTimeMillis(); + this.sessionTimingLastCheck = System.currentTimeMillis(); // this.sessionLastLocation = null; @@ -149,8 +149,9 @@ public void checkTimers() { if ( isOnline() ) { - // Do not change the session type, so pass it the current: - checkTimersMining( sessionType, getLastMine() ); + // Do not change the session type, but pass null for the mine to indicate + // that this is a checkTimers... + checkTimersMining( sessionType, null ); } } @@ -173,12 +174,16 @@ public void checkTimers() { *

If prior session type was mining, then do nothing if the last * @param mine */ - private void checkTimersMining( SessionType targetType, String mine ) { - final long currentTime = System.currentTimeMillis(); + private void checkTimersMining( SessionType currentSessionType, String mine ) { if ( !isOnline() ) { return; } + + final long currentTime = System.currentTimeMillis(); + final long duration = currentTime - sessionTimingLastCheck; + + // temp fix: if ( onlineTimeTotal < 0 ) { @@ -188,89 +193,116 @@ private void checkTimersMining( SessionType targetType, String mine ) { onlineMiningTimeTotal = 0; } - if ( sessionType == targetType && sessionType != SessionType.mining) { - // No change in status - - sessionTimingLastCheck = currentTime; - final long duration = currentTime - sessionTimingLastCheck; - // if duration is greater than 15 minutes, then move the session start - // point and save it. - if ( duration > 900000 ) { - - sessionTimingStart = currentTime; - dirty = true; - } - - } - else if ( sessionType != SessionType.mining ) { - - // Always Save as total time. Use sessionTimingStart. Ignore sessionTimingLastCheck. - final long duration = currentTime - sessionTimingStart; - onlineTimeTotal += duration; + if ( currentSessionType != SessionType.mining ) { //checkTimersAfk(); - sessionType = targetType; - sessionTimingStart = currentTime; + setLastMine( null ); + sessionType = currentSessionType; + sessionTimingLastCheck = currentTime; + dirty = true; } - else { - // The session type is still mining... + + else if ( currentSessionType == SessionType.mining ) { + // The current session type is still mining... and was before. // Must check sessionTimingLastCheck to see if we went over the // max mining idle time: - final long duration = currentTime - sessionTimingLastCheck; - - // If the duration is less than the session mining timeout, then player - // is still mining. Just set the sessionTimingLastCheck. - if ( duration < SESSION_TIMEOUT_MINING_MS ) { - - sessionTimingLastCheck = currentTime; + if ( sessionType != SessionType.mining || + getLastMine() == null ) { + + dirty = true; + } - // Mining can only be active for no more than SESSION_TIMEOUT_MINING_MS - // after the last block was broken. So check duration between now and - // sessionOnlineTimeLastCheck and if more than permitted, then shutdown - // mining session and log it for a duration since session start to - // last check plus the mining timeout value. Then set session start to - // that position. + else if ( mine == null && getLastMine() != null && + duration > SESSION_TIMEOUT_MINING_MS ) { + + addTimeToMine( getLastMine(), SESSION_TIMEOUT_MINING_MS ); + + onlineMiningTimeTotal += SESSION_TIMEOUT_MINING_MS; + + // Since this is being called from checkTimer(), need to + // set lastMine to null and sessionType to active: + + setLastMine( null ); + sessionType = SessionType.active; + + // Save as total online time. + onlineTimeTotal += duration; + + dirty = true; + return; + } - else if ( duration > SESSION_TIMEOUT_MINING_MS || getLastMine() == null || - mine.equalsIgnoreCase( getLastMine() )) { + else if ( mine == null ) { - // Calculate the end point of the mining session, which will be 30 seconds after - // the last time check: - final long tempTime = sessionTimingLastCheck + SESSION_TIMEOUT_MINING_MS; - final long miningDuration = tempTime - sessionTimingStart; -// final long miningDuration = sessionTimingStart - tempTime; - onlineTimeTotal += miningDuration; - onlineMiningTimeTotal += miningDuration; + // This is running in checkTimers() and not enough time has passed to + // exceed the SESSION_TIMEOUT_MINING_MS. So need to wait longer. + // return without setting anything. - addTimeToMine( mine, miningDuration ); + return; + } + + // Mine has changed since last check, so apply duration to last mine: + else if ( getLastMine() != null && + (mine == null || + !mine.equalsIgnoreCase( getLastMine() ) )) { - // Set new session to this boundary: - sessionTimingStart = tempTime; - sessionTimingLastCheck = tempTime; - // Since the last SessionType and current are mining, then the duration from - // the new sessionTimingStart to currentTime needs to go to active: - final long durationActive = currentTime - sessionTimingStart; - onlineTimeTotal += durationActive; + if ( duration > SESSION_TIMEOUT_MINING_MS ) { + addTimeToMine( getLastMine(), SESSION_TIMEOUT_MINING_MS ); + + onlineMiningTimeTotal += SESSION_TIMEOUT_MINING_MS; + + } + else { + + addTimeToMine( getLastMine(), duration ); + + onlineMiningTimeTotal += duration; + } + + } + + + else if ( duration > SESSION_TIMEOUT_MINING_MS ) { - //checkTimersAfk(); + // Same mine, but exceeded the duration: + addTimeToMine( mine, SESSION_TIMEOUT_MINING_MS ); - // Now reset the current session: - sessionType = targetType; - sessionTimingStart = currentTime; - sessionTimingLastCheck = currentTime; - dirty = true; + onlineMiningTimeTotal += SESSION_TIMEOUT_MINING_MS; + + } + else { + // same mine and less than session length, so add duration: + + addTimeToMine( mine, duration ); + onlineMiningTimeTotal += duration; + } + + + // Now change the active mine + setLastMine( mine ); + + // Should already be mining: +// sessionType = currentSessionType; + + // Set new session to this boundary and discard the extra time: + sessionTimingLastCheck = currentTime; + + dirty = true; } + + // Always Save as total online time. + onlineTimeTotal += duration; } From 24a6cb5cedbee5dcf0f7a25dbeff38369bb527e2 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Wed, 24 Nov 2021 11:38:02 -0500 Subject: [PATCH 139/283] Reworked how the drops were processed to prevent dropping the wrong contents. There was an issue where the drops were retrieved later in the process that allowed it to incorrectly pickup drops that were related to a decay function. This resolves the incorrect drops. --- docs/changelog_v3.3.x.md | 4 + .../spigot/block/OnBlockBreakEventCore.java | 89 ++++++++++++++----- 2 files changed, 72 insertions(+), 21 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 3aa072f38..63d8b72fa 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.6 2021-11-24 +* **Reworked how the drops were processed to prevent dropping the wrong contents.** +There was an issue where the drops were retrieved later in the process that allowed it to incorrectly pickup drops that were related to a decay function. This resolves the incorrect drops. + + * **Player cache timing improvements.** This fixes issues with tracking the timing when mining. Not 100% sure it is perfect, but it's actually working much better. Will need to revisit later. diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index 6a28082b5..0e1a745ac 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -672,9 +672,11 @@ private boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent, StringBuilder // being processed more than once: targetBlock.setMined( true ); - if ( targetBlock.getPrisonBlock().equals( pmEvent.getSpigotBlock().getPrisonBlock() ) ) { + if ( targetBlock.getPrisonBlock().equals( pmEvent.getSpigotBlock().getPrisonBlock() ) && + collectBukkitDrops( pmEvent.getBukkitDrops(), targetBlock, pmEvent.getItemInHand() )) { targetBlock.setMinedBlock( pmEvent.getSpigotBlock() ); + } else { // The block is not the correct type. It has been changed since the mine was reset @@ -756,7 +758,8 @@ else if ( results && !targetExplodedBlock.isMined() ) { // If not, then do not process it. SpigotBlock sBlockMined = new SpigotBlock( bukkitBlock ); - if ( targetExplodedBlock.getPrisonBlock().equals( sBlockMined.getPrisonBlock() ) ) { + if ( targetExplodedBlock.getPrisonBlock().equals( sBlockMined.getPrisonBlock() ) && + collectBukkitDrops( pmEvent.getBukkitDrops(), targetExplodedBlock, pmEvent.getItemInHand() ) ) { // If a chain reaction on explosions, this will prevent the same block from // being processed more than once: @@ -766,6 +769,8 @@ else if ( results && !targetExplodedBlock.isMined() ) { pmEvent.getExplodedBlocks().add( sBlock ); pmEvent.getTargetExplodedBlocks().add( targetExplodedBlock ); + + } else { // The block is not the correct type. It has been changed since the mine was reset @@ -830,6 +835,10 @@ else if ( results ) { } + // Need to compress the drops to eliminate duplicates: + pmEvent.setBukkitDrops( mergeDrops( pmEvent.getBukkitDrops() ) ); + + // If target block aready was mined and there are no exploded blocks, then this whole event // needs to be canceled since it sounds like a blockevent fired a prison util explosion that // has zero blocks tied to it. @@ -892,6 +901,8 @@ else if ( results ) { results = false; } + + if ( results && pmEvent.isBlockEventsOnly() ) { // NOTE: This "should" never be activated since blockEventsOnly used to be enabled @@ -948,23 +959,35 @@ else if ( results && pmEvent.isMonitor() && mine != null ) { } - if ( results ) { - // Collect the bukkit drops && cancel the drops if needed - - collectBukkitDrops( pmEvent.getBukkitDrops(), pmEvent.getSpigotBlock(), - pmEvent.getItemInHand() ); + if ( results && isBoolean( AutoFeatures.cancelAllBlockEventBlockDrops ) ) { + + clearBukkitDrops( pmEvent.getBukkitDrops(), pmEvent.getTargetBlock() ); - for ( SpigotBlock explodedBlock : pmEvent.getExplodedBlocks() ) + for ( MineTargetPrisonBlock targetBlock : pmEvent.getTargetExplodedBlocks() ) { - collectBukkitDrops( pmEvent.getBukkitDrops(), explodedBlock, - pmEvent.getItemInHand() ); + clearBukkitDrops( pmEvent.getBukkitDrops(), targetBlock ); } - - // Need to compress the drops to eliminate duplicates: - pmEvent.setBukkitDrops( mergeDrops( pmEvent.getBukkitDrops() ) ); + } +// if ( results ) { +// // Collect the bukkit drops && cancel the drops if needed +// +// collectBukkitDrops( pmEvent.getBukkitDrops(), pmEvent.getTargetBlock(), +// pmEvent.getItemInHand() ); +// +// for ( MineTargetPrisonBlock targetBlock : pmEvent.getTargetExplodedBlocks() ) +// { +// collectBukkitDrops( pmEvent.getBukkitDrops(), targetBlock, +// pmEvent.getItemInHand() ); +// +// } +// +// // Need to compress the drops to eliminate duplicates: +// pmEvent.setBukkitDrops( mergeDrops( pmEvent.getBukkitDrops() ) ); +// } + if ( results ) { debugInfo.append( "(PassedValidation) " ); @@ -977,21 +1000,45 @@ else if ( results && pmEvent.isMonitor() && mine != null ) { return results; } - private void collectBukkitDrops( List bukkitDrops, SpigotBlock spigotBlock, + private boolean collectBukkitDrops( List bukkitDrops, MineTargetPrisonBlock targetBlock, SpigotItemStack itemInHand ) { - List drops = SpigotUtil.getDrops(spigotBlock, itemInHand); - - bukkitDrops.addAll( drops ); + boolean results = false; + + SpigotBlock sBlock = (SpigotBlock) targetBlock.getMinedBlock(); - // This clears the drops for the given block, so if the event is not canceled, it will - // not result in duplicate drops. - if ( isBoolean( AutoFeatures.cancelAllBlockEventBlockDrops ) ) { - spigotBlock.clearDrops(); + if ( targetBlock.getPrisonBlock().equals( sBlock.getPrisonBlock() ) ) { + + List drops = SpigotUtil.getDrops(sBlock, itemInHand); + + bukkitDrops.addAll( drops ); + +// // This clears the drops for the given block, so if the event is not canceled, it will +// // not result in duplicate drops. +// if ( isBoolean( AutoFeatures.cancelAllBlockEventBlockDrops ) ) { +// sBlock.clearDrops(); +// } + + results = true; + + } + else { + Output.get().logWarn( "collectBukkitDrops: block was changed and not what was expected. " + + "Block: " + sBlock.getBlockName() + " expecting: " + targetBlock.getPrisonBlock().getBlockName() ); } + return results; } + + private void clearBukkitDrops( List bukkitDrops, MineTargetPrisonBlock targetBlock ) + { + + SpigotBlock sBlock = (SpigotBlock) targetBlock.getMinedBlock(); + sBlock.clearDrops(); + + } + /** *

The List of drops must have only one ItemStack per block type (name). * This function combines multiple occurrences together and adds up their From fb93e7930a2d0e4671587173a78433398c86a86e Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Wed, 24 Nov 2021 11:41:33 -0500 Subject: [PATCH 140/283] Added the ability to remove mine spawn points. --- docs/changelog_v3.3.x.md | 3 +++ .../main/resources/lang/mines/de_DE.properties | 3 ++- .../main/resources/lang/mines/en_US.properties | 3 ++- .../main/resources/lang/mines/es_ES.properties | 3 ++- .../main/resources/lang/mines/hu_HU.properties | 3 ++- .../main/resources/lang/mines/it_IT.properties | 3 ++- .../main/resources/lang/mines/nl_BE.properties | 3 ++- .../main/resources/lang/mines/nl_NL.properties | 3 ++- .../main/resources/lang/mines/zh_TW.properties | 3 ++- .../prison/mines/commands/MinesCommands.java | 15 ++++++++++++--- 10 files changed, 31 insertions(+), 11 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 63d8b72fa..92b902110 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.6 2021-11-24 +* **Add the ability to remove a mine's spawn point.** + + * **Reworked how the drops were processed to prevent dropping the wrong contents.** There was an issue where the drops were retrieved later in the process that allowed it to incorrectly pickup drops that were related to a decay function. This resolves the incorrect drops. diff --git a/prison-core/src/main/resources/lang/mines/de_DE.properties b/prison-core/src/main/resources/lang/mines/de_DE.properties index 03c93341b..4ed2f1679 100644 --- a/prison-core/src/main/resources/lang/mines/de_DE.properties +++ b/prison-core/src/main/resources/lang/mines/de_DE.properties @@ -51,7 +51,7 @@ -messages__version=1 +messages__version=2 messages__auto_refresh=true @@ -77,6 +77,7 @@ world_diff=&7Du kannst keine Minen in zwei verschiedenen Welten erstellen. mine_exists=&7Eine Mine mit diesem Namen existiert bereits. mine_does_not_exist=&7Eine Mine mit diesem Namen existiert nicht. spawn_set=&7Der Minen-spawnpoint wurde festgelegt. +spawn_removed=&7The mine spawnpoint has been removed. spawnpoint_same_world=&7Der &cspawnpoint &7muss in derselben &cWelt &7 sein wie die Mine. not_a_block=&c%1 &7ist kein Block. block_already_added=&7Dieser Block wurde bereits zu der Mine hinzugefügt. diff --git a/prison-core/src/main/resources/lang/mines/en_US.properties b/prison-core/src/main/resources/lang/mines/en_US.properties index 9f298827b..ae80f0c4b 100644 --- a/prison-core/src/main/resources/lang/mines/en_US.properties +++ b/prison-core/src/main/resources/lang/mines/en_US.properties @@ -51,7 +51,7 @@ -messages__version=1 +messages__version=2 messages__auto_refresh=true @@ -77,6 +77,7 @@ world_diff=&7You may not create mines across two different worlds. mine_exists=&7A mine by that name already exists. mine_does_not_exist=&7A mine by that name does not exist. spawn_set=&7The mine spawnpoint has been set. +spawn_removed=&7The mine spawnpoint has been removed. spawnpoint_same_world=&7The &cspawnpoint &7must be in the same &cworld &7as the mine. not_a_block=&c%1 &7is not a block. block_already_added=&7That block has already been added to the mine. diff --git a/prison-core/src/main/resources/lang/mines/es_ES.properties b/prison-core/src/main/resources/lang/mines/es_ES.properties index 015de3856..4781c4bb3 100644 --- a/prison-core/src/main/resources/lang/mines/es_ES.properties +++ b/prison-core/src/main/resources/lang/mines/es_ES.properties @@ -51,7 +51,7 @@ -messages__version=1 +messages__version=2 messages__auto_refresh=true @@ -77,6 +77,7 @@ world_diff=&7No debes crear minas a través de dos mundos distintos. mine_exists=&7Ya existe una mina con ese nombre. mine_does_not_exist=&7No existe una mina con ese nombre. spawn_set=&7El punto de aparición (spawnpoint) de la mina ha sido definid. +spawn_removed=&7The mine spawnpoint has been removed. spawnpoint_same_world=&7El &cpunto de aparición &7debe estar en el mismo &cmundo &7que la mina. not_a_block=&c%1 &7no es un bloque. block_already_added=&7Ese bloque ya ha sido añadido a la mina. diff --git a/prison-core/src/main/resources/lang/mines/hu_HU.properties b/prison-core/src/main/resources/lang/mines/hu_HU.properties index 45893d91d..d5d8ab858 100644 --- a/prison-core/src/main/resources/lang/mines/hu_HU.properties +++ b/prison-core/src/main/resources/lang/mines/hu_HU.properties @@ -51,7 +51,7 @@ -messages__version=1 +messages__version=2 messages__auto_refresh=true @@ -77,6 +77,7 @@ world_diff=&7Nem hozhatsz létre bányákat két különböző világon. mine_exists=&7A bánya ezzel a névvel már létezik. mine_does_not_exist=&7A bánya ezzel a névvel nem létezik. spawn_set=&7A bánya spawnpontja beállítva. +spawn_removed=&7The mine spawnpoint has been removed. spawnpoint_same_world=&7A &cspawnpont-nak&7 ugyanabban a &cvilágban&7 bányában kell lennie. not_a_block=&c%1 &7nem egy blokk. block_already_added=&7Ez a blokk már felkerült a bányába. diff --git a/prison-core/src/main/resources/lang/mines/it_IT.properties b/prison-core/src/main/resources/lang/mines/it_IT.properties index 9b4359aa1..2116e07d5 100644 --- a/prison-core/src/main/resources/lang/mines/it_IT.properties +++ b/prison-core/src/main/resources/lang/mines/it_IT.properties @@ -51,7 +51,7 @@ -messages__version=1 +messages__version=2 messages__auto_refresh=true @@ -77,6 +77,7 @@ world_diff=&7Non puoi creare due miniere attraverso due mondi differenti. mine_exists=&7Una miniera con quel nome esiste già. mine_does_not_exist=&7Una miniera con quel nome non esiste. spawn_set=&7Il punto di spawn della miniera è stato settato. +spawn_removed=&7The mine spawnpoint has been removed. spawnpoint_same_world=&7Il &cPunto di spawn &7deve essere nello stesso &cmondo &7della miniera. not_a_block=&c%1 &7non è un blocco. block_already_added=&7Quel blocco è già stato aggiunto alla miniera. diff --git a/prison-core/src/main/resources/lang/mines/nl_BE.properties b/prison-core/src/main/resources/lang/mines/nl_BE.properties index ed01bbabf..7c3a5bfaf 100644 --- a/prison-core/src/main/resources/lang/mines/nl_BE.properties +++ b/prison-core/src/main/resources/lang/mines/nl_BE.properties @@ -51,7 +51,7 @@ -messages__version=1 +messages__version=2 messages__auto_refresh=true @@ -75,6 +75,7 @@ world_diff=&7Je kan geen mijn creëren over twee werelden. mine_exists=&7Een mijn met die naam bestaat al. mine_does_not_exist=&7Een mijn met die naam bestaat niet. spawn_set=&7De mijn zijn startpunt is gezet. +spawn_removed=&7The mine spawnpoint has been removed. spawnpoint_same_world=&7Het startpunt moet in dezelfde wereld als de mijn zijn . not_a_block=&c%1 &7is geen blok. block_already_added=&7Deze blok is al in de mijn toegevoegd. diff --git a/prison-core/src/main/resources/lang/mines/nl_NL.properties b/prison-core/src/main/resources/lang/mines/nl_NL.properties index ed01bbabf..7c3a5bfaf 100644 --- a/prison-core/src/main/resources/lang/mines/nl_NL.properties +++ b/prison-core/src/main/resources/lang/mines/nl_NL.properties @@ -51,7 +51,7 @@ -messages__version=1 +messages__version=2 messages__auto_refresh=true @@ -75,6 +75,7 @@ world_diff=&7Je kan geen mijn creëren over twee werelden. mine_exists=&7Een mijn met die naam bestaat al. mine_does_not_exist=&7Een mijn met die naam bestaat niet. spawn_set=&7De mijn zijn startpunt is gezet. +spawn_removed=&7The mine spawnpoint has been removed. spawnpoint_same_world=&7Het startpunt moet in dezelfde wereld als de mijn zijn . not_a_block=&c%1 &7is geen blok. block_already_added=&7Deze blok is al in de mijn toegevoegd. diff --git a/prison-core/src/main/resources/lang/mines/zh_TW.properties b/prison-core/src/main/resources/lang/mines/zh_TW.properties index 1a521c308..90bc197d6 100644 --- a/prison-core/src/main/resources/lang/mines/zh_TW.properties +++ b/prison-core/src/main/resources/lang/mines/zh_TW.properties @@ -51,7 +51,7 @@ -messages__version=2 +messages__version=3 messages__auto_refresh=true @@ -77,6 +77,7 @@ world_diff=&7您不能在多個世界中建立礦場 mine_exists=&7此礦場名稱已經存在 mine_does_not_exist=&7此礦場名稱並不存在 spawn_set=&7礦場出生點 已成功 設定 +spawn_removed=&7The mine spawnpoint has been removed. spawnpoint_same_world=&7這個 &c出生點 &7必須與其他 礦場 在同一個 &c世界 not_a_block=&c%1 &7不是一個方塊 block_already_added=&7此方塊已經被新增到礦場 diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java index b003feeaf..7090cf3ef 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java @@ -465,7 +465,8 @@ public void tpAccessByRankCommand(CommandSender sender, @Command(identifier = "mines set spawn", description = "Set the mine's spawn to where you're standing.", onlyPlayers = true, permissions = "mines.set") public void spawnpointCommand(CommandSender sender, - @Arg(name = "mineName", description = "The name of the mine to edit.") String mineName) { + @Arg(name = "mineName", description = "The name of the mine to edit.") String mineName, + @Arg(name = "options", description = "Options: Option to remove a spawn. [*remove*]") String options ) { Player player = getPlayer( sender ); @@ -508,9 +509,17 @@ public void spawnpointCommand(CommandSender sender, setLastMineReferenced(mineName); - mine.setSpawn(((Player) sender).getLocation()); + if ( options != null && options.toLowerCase().contains( "*remove*" ) ) { + mine.setSpawn( null ); + pMines.getMinesMessages().getLocalizable("spawn_removed").sendTo(sender); + } + else { + + mine.setSpawn(((Player) sender).getLocation()); + pMines.getMinesMessages().getLocalizable("spawn_set").sendTo(sender); + } + pMines.getMineManager().saveMine(mine); - pMines.getMinesMessages().getLocalizable("spawn_set").sendTo(sender); } From 1be78b9f211629b713e999db995279106ba7b20e Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Thu, 25 Nov 2021 15:19:18 -0500 Subject: [PATCH 141/283] Ran in to another Java format exception. Not sure what caused this problem, but added it to the catch so it can be reported in details so it can be fixed. --- docs/changelog_v3.3.x.md | 4 ++++ .../src/main/java/tech/mcprison/prison/output/Output.java | 8 +++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 92b902110..10a61c848 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.6 2021-11-24 +* **Ran in to another Java format exception.** +Not sure what caused this problem, but added it to the catch so it can be reported in details so it can be fixed. + + * **Add the ability to remove a mine's spawn point.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/output/Output.java b/prison-core/src/main/java/tech/mcprison/prison/output/Output.java index 7a6a79c9b..8289c1e27 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/output/Output.java +++ b/prison-core/src/main/java/tech/mcprison/prison/output/Output.java @@ -19,6 +19,7 @@ package tech.mcprison.prison.output; import java.util.Arrays; +import java.util.FormatFlagsConversionMismatchException; import java.util.HashSet; import java.util.MissingFormatArgumentException; import java.util.Set; @@ -237,7 +238,8 @@ public void log(String message, LogLevel level, Object... args) { getLogColorCode(LogLevel.ERROR) + errorMessage ); } - catch ( UnknownFormatConversionException e) + catch ( UnknownFormatConversionException | + FormatFlagsConversionMismatchException e) { StringBuilder sb = new StringBuilder(); @@ -245,10 +247,10 @@ public void log(String message, LogLevel level, Object... args) { sb.append( "[" ).append( arg ).append( "] " ); } - String errorMessage = "Error with Java conversion format (eg %s): " + + String errorMessage = "Error with Java format usage (eg %s): " + " LogLevel: " + level.name() + " message: [" + message + "] params: " + sb.toString() + - " error: " + e.getMessage(); + " error: [" + e.getMessage() + "]"; Prison.get().getPlatform().logCore( prefixTemplatePrison + " " + From 83917cb59222ceb343b340a3c573d7122a2bb8a2 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 26 Nov 2021 10:41:09 -0500 Subject: [PATCH 142/283] Mine Bombs: Added the collections for sound effects and visual effects. Both share the same object, MineBombEffectsData. An effect has a name, plus an EffectState, and an offset in ticks that will apply that effect based upon the EffectState. The EffectState can be placed, explode, or finished. --- docs/changelog_v3.3.x.md | 8 +- .../mcprison/prison/bombs/MineBombData.java | 39 ++++- .../prison/bombs/MineBombEffectsData.java | 147 ++++++++++++++++++ 3 files changed, 192 insertions(+), 2 deletions(-) create mode 100644 prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombEffectsData.java diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 10a61c848..412ac6c07 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,13 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.6 2021-11-24 +# 3.2.11-alpha.6 2021-11-26 + + +* **Mine Bombs: Added the collections for sound effects and visual effects.** +Both share the same object, MineBombEffectsData. +An effect has a name, plus an EffectState, and an offset in ticks that will apply that effect based upon the EffectState. +The EffectState can be placed, explode, or finished. * **Ran in to another Java format exception.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java index d4177ecaf..11b6e2a79 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java @@ -2,6 +2,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.TreeSet; import tech.mcprison.prison.internal.block.PrisonBlock; @@ -113,10 +114,18 @@ public class MineBombData { private boolean activated = false; + + private TreeSet soundEffects; + + private TreeSet visualEffects; + public MineBombData() { super(); + + this.soundEffects = new TreeSet<>( new MineBombEffectsData() ); + this.visualEffects = new TreeSet<>( new MineBombEffectsData() ); } @@ -177,10 +186,24 @@ public MineBombData clone() { cloned.setAutosell( isAutosell() ); cloned.setActivated( isActivated() ); - for ( String l : lore ) { + + for ( String l : getLore() ) { cloned.getLore().add( l ); } + + for ( MineBombEffectsData soundEffect : getSoundEffects() ) + { + cloned.getSoundEffects().add( soundEffect.clone() ); + } + + + for ( MineBombEffectsData visualEffect : getVisualEffects() ) + { + cloned.getVisualEffects().add( visualEffect.clone() ); + } + + return cloned; } @@ -314,5 +337,19 @@ public boolean isActivated() { public void setActivated( boolean activated ) { this.activated = activated; } + + public TreeSet getSoundEffects() { + return soundEffects; + } + public void setSoundEffects( TreeSet soundEffects ) { + this.soundEffects = soundEffects; + } + + public TreeSet getVisualEffects() { + return visualEffects; + } + public void setVisualEffects( TreeSet visualEffects ) { + this.visualEffects = visualEffects; + } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombEffectsData.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombEffectsData.java new file mode 100644 index 000000000..21e9a5b44 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombEffectsData.java @@ -0,0 +1,147 @@ +package tech.mcprison.prison.bombs; + +import java.util.Comparator; + +/** + *

The effectsName that is used should be one of the following, or it will not work. + * These effects depend upon the server's version too. If what you enter does not work, + * then try something else what would be compatible. It's important to test to make + * sure.

+ * + *

For Sound Effects: + *

+ * + * + * + *

For Visual Effects: + *

+ * https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Particle.html + * + */ +public class MineBombEffectsData + implements Comparator, + Comparable +{ + + private String effectName; + + private EffectState effectState; + + private int offsetTicks; + + private float volumne; + private float pitch; + + public enum EffectState { + placed, + explode, + finished; + } + + protected MineBombEffectsData() { + super(); + } + + public MineBombEffectsData( String effectName, EffectState effectState, + int offsetTicks ) { + super(); + + this.effectName = effectName; + this.effectState = effectState; + this.offsetTicks = offsetTicks; + + this.volumne = 1.0f; + this.pitch = 1.0f; + } + + + public MineBombEffectsData( String effectName, EffectState effectState, + int offsetTicks, float volume, float pitch ) { + this( effectName, effectState, offsetTicks ); + + this.volumne = volume; + this.pitch = pitch; + } + + + public MineBombEffectsData clone() { + return new MineBombEffectsData( getEffectName(), getEffectState(), getOffsetTicks(), + getVolumne(), getPitch() ); + } + + @Override + public String toString() { + return getEffectName() + " (state: " + getEffectState().name() + " offset: " + getOffsetTicks() + + " ticks v: " + getVolumne() + " p: " + getPitch() + ")"; + } + public String toStringShort() { + return getEffectName() + " (state: " + getEffectState().name() + " offset: " + getOffsetTicks() + + " ticks)"; + } + + @Override + public int compare( MineBombEffectsData o1, MineBombEffectsData o2 ) + { + int results = o1.getEffectState().compareTo( o2.getEffectState() ); + + if ( results == 0 ) { + results = Integer.compare( o1.getOffsetTicks(), o2.getOffsetTicks() ); + + if ( results == 0 ) { + results = o1.getEffectName().compareTo( o2.getEffectName() ); + } + } + return results; + } + + @Override + public int compareTo( MineBombEffectsData o ) + { + return compare( this, o ); + } + + + public String getEffectName() { + return effectName; + } + public void setEffectName( String effectName ) { + this.effectName = effectName; + } + + public EffectState getEffectState() { + return effectState; + } + public MineBombEffectsData setEffectState( EffectState effectState ) { + this.effectState = effectState; + + return this; + } + + public int getOffsetTicks() { + return offsetTicks; + } + public MineBombEffectsData setOffsetTicks( int offsetTicks ) { + this.offsetTicks = offsetTicks; + + return this; + } + + public float getVolumne() { + return volumne; + } + public MineBombEffectsData setVolumne( float volumne ) { + this.volumne = volumne; + + return this; + } + + public float getPitch() { + return pitch; + } + public MineBombEffectsData setPitch( float pitch ) { + this.pitch = pitch; + + return this; + } + +} From f3801d9f267c10e32ef669721600adec20214b48 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 26 Nov 2021 10:47:15 -0500 Subject: [PATCH 143/283] Mine Bombs: Added a few new shapes. Disk and Ring. Available in each plane x, y, and z. --- docs/changelog_v3.3.x.md | 4 ++ .../tech/mcprison/prison/bombs/MineBombs.java | 61 +++++++++++++++++-- .../spigot/utils/PrisonUtilsMineBombs.java | 6 ++ 3 files changed, 66 insertions(+), 5 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 412ac6c07..d003a178c 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.6 2021-11-26 +* **Mine Bombs: Added a few new shapes.** +Disk and Ring. Available in each plane x, y, and z. + + * **Mine Bombs: Added the collections for sound effects and visual effects.** Both share the same object, MineBombEffectsData. An effect has a name, plus an EffectState, and an offset in ticks that will apply that effect based upon the EffectState. diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java index 164f2ae1f..d1a535aac 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java @@ -21,6 +21,14 @@ public class MineBombs public enum ExplosionShape { + ring_x, + ring_y, + ring_z, + + disk_x, + disk_y, + disk_z, + cube, sphere, @@ -42,6 +50,26 @@ public static ExplosionShape fromString( String shape ) { return results; } + + public static List asList() + { + List results = new ArrayList<>(); + + for ( ExplosionShape shape : values() ) + { + results.add( shape.name() ); + } + + return results; + } + } + + public enum ExplosionOrientation { + x_axis, + y_axis, + z_axis, + + full } private MineBombs() { @@ -126,12 +154,29 @@ public void loadConfigJson() { } } + + public List calculateCylinder( Location loc, int radius, boolean hollow ) { + List results = new ArrayList<>(); + + + + return results; + } + public List calculateSphere( Location loc, int radius, boolean hollow ) { - return calculateSphere( loc, radius, hollow, 0 ); + return calculateSphere( loc, radius, hollow, 0, ExplosionOrientation.full ); + } + + public List calculateSphere( Location loc, int radius, boolean hollow, + int radiusInner ) { + return calculateSphere( loc, radius, hollow, radiusInner, ExplosionOrientation.full ); } - public List calculateSphere( Location loc, int radius, boolean hollow, int radiusInner ) { + + + public List calculateSphere( Location loc, int radius, boolean hollow, + int radiusInner, ExplosionOrientation explosionOrientation ) { List results = new ArrayList<>(); if ( loc != null && radius > 0 ) { @@ -139,6 +184,10 @@ public List calculateSphere( Location loc, int radius, boolean hollow, int cenY = loc.getBlockY(); int cenZ = loc.getBlockZ(); + boolean xOri = explosionOrientation == ExplosionOrientation.x_axis; + boolean yOri = explosionOrientation == ExplosionOrientation.y_axis; + boolean zOri = explosionOrientation == ExplosionOrientation.z_axis; + double radiusSqr = radius * radius; // If the radiusInner is not specified (== 0), then subtract one from radius. @@ -146,11 +195,13 @@ public List calculateSphere( Location loc, int radius, boolean hollow, ((radius - 1) * (radius - 1)) : (radiusInner * radiusInner); - for ( int x = cenX - radius ; x <= cenX + radius ; x++ ) { + for ( int x = (xOri ? cenX : cenX - radius) ; x <= (xOri ? cenX : cenX + radius) ; x++ ) { double xSqr = (cenX - x) * (cenX - x); - for ( int y = cenY - radius ; y <= cenY + radius ; y++ ) { + + for ( int y = (yOri ? cenY : cenY - radius) ; y <= (yOri ? cenY : cenY + radius) ; y++ ) { double ySqr = (cenY - y) * (cenY - y); - for ( int z = cenZ - radius ; z <= cenZ + radius ; z++ ) { + + for ( int z = (zOri ? cenZ : cenZ - radius) ; z <= (zOri ? cenZ : cenZ + radius) ; z++ ) { double zSqr = (cenZ - z) * (cenZ - z); double distSqr = xSqr + ySqr + zSqr; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java index 0ac51542c..d6fbf5b34 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java @@ -210,6 +210,9 @@ public void utilsMineBombsList( CommandSender sender } case sphereHollow: + case ring_x: + case ring_y: + case ring_z: { messageShape = String.format( " Shape: %s Radius: %d.5 RadiusInner: %d.5", @@ -218,6 +221,9 @@ public void utilsMineBombsList( CommandSender sender } case sphere: + case disk_x: + case disk_y: + case disk_z: { messageShape = String.format( " Shape: %s Radius: %d.5", From a034b1c58af4ae902fce7be31c4a6a506f52e986 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 26 Nov 2021 10:49:04 -0500 Subject: [PATCH 144/283] Bug fix: Auto Features Auto Pickup is now ignored if sellall has not been setup on the server. If getting an instance of SellAll when it is disabled, will result in a null value. --- docs/changelog_v3.3.x.md | 4 ++++ .../prison/spigot/autofeatures/AutoManagerFeatures.java | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index d003a178c..ad18f6915 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.6 2021-11-26 +* **Bug fix: Auto Features Auto Pickup is now ignored if sellall has not been setup on the server.** +If getting an instance of SellAll when it is disabled, will result in a null value. + + * **Mine Bombs: Added a few new shapes.** Disk and Ring. Available in each plane x, y, and z. diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java index 2a1b20064..ff94ebf02 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java @@ -500,8 +500,8 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, // Try to autosell if enabled: - if (isBoolean(AutoFeatures.isAutoSellPerBlockBreakEnabled) || - pmEvent.isForceAutoSell() ) { + if ( SellAllUtil.get() != null && (isBoolean(AutoFeatures.isAutoSellPerBlockBreakEnabled) || + pmEvent.isForceAutoSell()) ) { double amount = SellAllUtil.get().sellAllSell( player, itemStack, false, false, true ); autosellTotal += amount; @@ -530,7 +530,7 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, // sold will zero out the number of drops for that item stack. if ( !isBoolean(AutoFeatures.isAutoSellPerBlockBreakEnabled) || itemStack.getAmount() != 0 ) { - if ( Output.get().isDebug() ) { + if ( Output.get().isDebug() && SellAllUtil.get() != null ) { // Just get the calculated value for the drops... do not sell: double amount = SellAllUtil.get().sellAllSell( player, itemStack, true, false, false ); From 9500bb892b22232ae4f154748cfd04dc3558b263 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 26 Nov 2021 10:52:31 -0500 Subject: [PATCH 145/283] Bug fix: Auto features get drops not always working with explosions. The get drops was moved around to help ensure it does not try to get the block drops if the block is not what it is expected. This is now passing the needed object used for the check, instead of extracting it from the target blocks, which have not yet been set. --- docs/changelog_v3.3.x.md | 4 ++++ .../spigot/block/OnBlockBreakEventCore.java | 22 +++++++++++-------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index ad18f6915..60a4979d4 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.6 2021-11-26 +* **Bug fix: Auto features get drops not always working with explosions.** +The get drops was moved around to help ensure it does not try to get the block drops if the block is not what it is expected. This is now passing the needed object used for the check, instead of extracting it from the target blocks, which have not yet been set. + + * **Bug fix: Auto Features Auto Pickup is now ignored if sellall has not been setup on the server.** If getting an instance of SellAll when it is disabled, will result in a null value. diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index 0e1a745ac..b92ae6f91 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -673,7 +673,7 @@ private boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent, StringBuilder targetBlock.setMined( true ); if ( targetBlock.getPrisonBlock().equals( pmEvent.getSpigotBlock().getPrisonBlock() ) && - collectBukkitDrops( pmEvent.getBukkitDrops(), targetBlock, pmEvent.getItemInHand() )) { + collectBukkitDrops( pmEvent.getBukkitDrops(), targetBlock, pmEvent.getItemInHand(), pmEvent.getSpigotBlock() )) { targetBlock.setMinedBlock( pmEvent.getSpigotBlock() ); @@ -757,9 +757,10 @@ else if ( results && !targetExplodedBlock.isMined() ) { // Check to make sure the block is the same block that was placed there. // If not, then do not process it. SpigotBlock sBlockMined = new SpigotBlock( bukkitBlock ); + PrisonBlock pBlockMined = sBlockMined.getPrisonBlock(); - if ( targetExplodedBlock.getPrisonBlock().equals( sBlockMined.getPrisonBlock() ) && - collectBukkitDrops( pmEvent.getBukkitDrops(), targetExplodedBlock, pmEvent.getItemInHand() ) ) { + if ( targetExplodedBlock.getPrisonBlock().equals( pBlockMined ) && + collectBukkitDrops( pmEvent.getBukkitDrops(), targetExplodedBlock, pmEvent.getItemInHand(), sBlockMined ) ) { // If a chain reaction on explosions, this will prevent the same block from // being processed more than once: @@ -1001,15 +1002,18 @@ else if ( results && pmEvent.isMonitor() && mine != null ) { } private boolean collectBukkitDrops( List bukkitDrops, MineTargetPrisonBlock targetBlock, - SpigotItemStack itemInHand ) + SpigotItemStack itemInHand, SpigotBlock sBlockMined ) { boolean results = false; - SpigotBlock sBlock = (SpigotBlock) targetBlock.getMinedBlock(); +// if ( sBlockMined == null && targetBlock.getMinedBlock() != null ) { +// sBlockMined = (SpigotBlock) targetBlock.getMinedBlock(); +// } + //SpigotBlock sBlock = (SpigotBlock) targetBlock.getMinedBlock(); - if ( targetBlock.getPrisonBlock().equals( sBlock.getPrisonBlock() ) ) { + if ( sBlockMined != null && targetBlock.getPrisonBlock().equals( sBlockMined.getPrisonBlock() ) ) { - List drops = SpigotUtil.getDrops(sBlock, itemInHand); + List drops = SpigotUtil.getDrops(sBlockMined, itemInHand); bukkitDrops.addAll( drops ); @@ -1022,9 +1026,9 @@ private boolean collectBukkitDrops( List bukkitDrops, MineTarge results = true; } - else { + else if ( sBlockMined != null) { Output.get().logWarn( "collectBukkitDrops: block was changed and not what was expected. " + - "Block: " + sBlock.getBlockName() + " expecting: " + targetBlock.getPrisonBlock().getBlockName() ); + "Block: " + sBlockMined.getBlockName() + " expecting: " + targetBlock.getPrisonBlock().getBlockName() ); } return results; From 062ae5e996558c078ffaea4a3ca42c7526ba3375 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 26 Nov 2021 10:55:20 -0500 Subject: [PATCH 146/283] Mine Bombs: Add the sound effects and visual effects to the default test bombs. NOTE: Some of these settings may not work on all versions of spigot, and some may not work on any version. --- docs/changelog_v3.3.x.md | 4 + .../tech/mcprison/prison/bombs/MineBombs.java | 84 +++++++++++++++++++ 2 files changed, 88 insertions(+) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 60a4979d4..54d2559ff 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.6 2021-11-26 +* **Mine Bombs: Add the sound effects and visual effects to the default test bombs.** +NOTE: Some of these settings may not work on all versions of spigot, and some may not work on any version. + + * **Bug fix: Auto features get drops not always working with explosions.** The get drops was moved around to help ensure it does not try to get the block drops if the block is not what it is expected. This is now passing the needed object used for the check, instead of extracting it from the target blocks, which have not yet been set. diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java index d1a535aac..3707f8375 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.List; +import tech.mcprison.prison.bombs.MineBombEffectsData.EffectState; import tech.mcprison.prison.file.JsonFileIO; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.util.Location; @@ -243,6 +244,8 @@ public List calculateCube( Location loc, int radius ) { return results; } + + @SuppressWarnings( "unused" ) public void setupDefaultMineBombData() { if ( getConfigData().getBombs().size() == 0 ) { @@ -254,6 +257,29 @@ public void setupDefaultMineBombData() // XMaterial.DIAMOND_PICKAXE; // XMaterial.NETHERITE_PICKAXE; + MineBombEffectsData mbeSound01 = new MineBombEffectsData( "ENTITY_CREEPER_PRIMED", EffectState.placed, 0 ); + MineBombEffectsData mbeSound02 = new MineBombEffectsData( "CAT_HISS", EffectState.placed, 0 ); + + MineBombEffectsData mbeSound03 = new MineBombEffectsData( "ENTITY_GENERIC_EXPLODE", EffectState.explode, 0 ); + MineBombEffectsData mbeSound04 = new MineBombEffectsData( "ENTITY_DRAGON_FIREBALL_EXPLODE", EffectState.explode, 0 ); + + + MineBombEffectsData mbeExplode01 = new MineBombEffectsData( "FIREWORKS_SPARK", EffectState.placed, 0 ); + MineBombEffectsData mbeExplode02 = new MineBombEffectsData( "BUBBLE_COLUMN_UP", EffectState.placed, 0 ); + MineBombEffectsData mbeExplode03 = new MineBombEffectsData( "ENCHANTMENT_TABLE", EffectState.placed, 0 ); + +// MineBombEffectsData mbeExplode05 = new MineBombEffectsData( "END_ROD", EffectState.placed, 0 ); + MineBombEffectsData mbeExplode04 = new MineBombEffectsData( "FLAME", EffectState.placed, 0 ); + MineBombEffectsData mbeExplode08 = new MineBombEffectsData( "DRAGON_BREATH", EffectState.placed, 0 ); + + MineBombEffectsData mbeExplode06 = new MineBombEffectsData( "SMOKE_NORMAL", EffectState.placed, 0 ); + MineBombEffectsData mbeExplode07 = new MineBombEffectsData( "SMOKE_LARGE", EffectState.placed, 0 ); + + MineBombEffectsData mbeExplode10 = new MineBombEffectsData( "EXPLOSION_NORMAL", EffectState.explode, 0 ); + MineBombEffectsData mbeExplode11 = new MineBombEffectsData( "EXPLOSION_LARGE", EffectState.explode, 0 ); + MineBombEffectsData mbeExplode12 = new MineBombEffectsData( "EXPLOSION_HUGE", EffectState.explode, 0 ); + + { MineBombData mbd = new MineBombData( "SmallBomb", "brewing_stand", ExplosionShape.sphere.name(), 2, "Small Mine Bomb" ); @@ -261,6 +287,13 @@ public void setupDefaultMineBombData() mbd.setToolInHandFortuneLevel( 0 ); mbd.setDescription("A small mine bomb made with some chemicals and a brewing stand."); + mbd.getSoundEffects().add( mbeSound01.clone() ); + mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 30 ) ); + mbd.getSoundEffects().add( mbeSound03.clone() ); + + mbd.getVisualEffects().add( mbeExplode01.clone() ); + mbd.getVisualEffects().add( mbeExplode02.clone().setOffsetTicks( 30 ) ); + getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); } @@ -272,7 +305,16 @@ public void setupDefaultMineBombData() "but supercharged with a strange green glowing liquid."); mbd.setToolInHandName( "DIAMOND_PICKAXE" ); mbd.setToolInHandFortuneLevel( 3 ); + + mbd.getSoundEffects().add( mbeSound01.clone() ); + mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 30 ) ); + mbd.getSoundEffects().add( mbeSound03.clone() ); + + mbd.getVisualEffects().add( mbeExplode01.clone() ); + mbd.getVisualEffects().add( mbeExplode02.clone().setOffsetTicks( 30 ) ); + mbd.setCooldownTicks( 60 ); + getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); } @@ -286,6 +328,15 @@ public void setupDefaultMineBombData() mbd.setToolInHandName( "DIAMOND_PICKAXE" ); mbd.setToolInHandFortuneLevel( 3 ); + mbd.getSoundEffects().add( mbeSound01.clone() ); + mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 30 ) ); + mbd.getSoundEffects().add( mbeSound03.clone().setVolumne( 2.0f ) ); + + mbd.getVisualEffects().add( mbeExplode01.clone() ); + mbd.getVisualEffects().add( mbeExplode02.clone().setOffsetTicks( 30 ) ); + + mbd.setCooldownTicks( 60 ); + getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); } @@ -299,10 +350,25 @@ public void setupDefaultMineBombData() mbd.setToolInHandName( "GOLDEN_PICKAXE" ); mbd.setToolInHandFortuneLevel( 13 ); + mbd.getSoundEffects().add( mbeSound01.clone() ); + mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 30 ).setVolumne( 2.0f ) ); + mbd.getSoundEffects().add( mbeSound03.clone().setVolumne( 3.0f ) ); + mbd.getSoundEffects().add( mbeSound03.clone().setOffsetTicks( 30 ).setVolumne( 1.5f ) ); + mbd.getSoundEffects().add( mbeSound04.clone().setOffsetTicks( 10 ).setVolumne( 2.0f ) ); + + mbd.getVisualEffects().add( mbeExplode06.clone() ); + mbd.getVisualEffects().add( mbeExplode12.clone() ); + mbd.getVisualEffects().add( mbeExplode12.clone().setOffsetTicks( 30 ) ); + mbd.getVisualEffects().add( mbeExplode12.clone().setOffsetTicks( 60 ) ); + mbd.getVisualEffects().add( mbeExplode07.clone().setOffsetTicks( 60 ) ); + mbd.getVisualEffects().add( mbeExplode08.clone().setOffsetTicks( 90 ) ); + mbd.setAutosell( true ); mbd.setGlowing( true ); mbd.setAutosell( true ); + mbd.setCooldownTicks( 60 ); + getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); } @@ -319,12 +385,21 @@ public void setupDefaultMineBombData() mbd.setToolInHandFortuneLevel( 0 ); mbd.setRemovalChance( 40.0d ); + mbd.getSoundEffects().add( mbeSound01.clone() ); + mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 30 ) ); + mbd.getSoundEffects().add( mbeSound03.clone() ); + + mbd.getVisualEffects().add( mbeExplode01.clone() ); + mbd.getVisualEffects().add( mbeExplode02.clone().setOffsetTicks( 30 ) ); + mbd.setCooldownTicks( 3 * 20 ); // 3 seconds mbd.setFuseDelayTicks( 2 * 20 ); // 2 seconds mbd.setGlowing( true ); mbd.setGravity( false ); + mbd.setCooldownTicks( 60 ); + getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); } @@ -340,8 +415,17 @@ public void setupDefaultMineBombData() mbd.setToolInHandFortuneLevel( 7 ); mbd.setRemovalChance( 100.0d ); + mbd.getSoundEffects().add( mbeSound01.clone() ); + mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 30 ) ); + mbd.getSoundEffects().add( mbeSound03.clone() ); + + mbd.getVisualEffects().add( mbeExplode01.clone() ); + mbd.getVisualEffects().add( mbeExplode02.clone().setOffsetTicks( 30 ) ); + mbd.setGlowing( true ); + mbd.setCooldownTicks( 60 ); + getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); } From dadedef8a823047a6f3be962033809c972edbb37 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 26 Nov 2021 11:00:05 -0500 Subject: [PATCH 147/283] Mine Bombs: Setup a test unit test to confirm that the sorting of the EffectStates is as expected. Needs to be: placed, explode, finished. --- docs/changelog_v3.3.x.md | 4 ++ .../prison/bombs/MineBombEffectsDataTest.java | 38 +++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 prison-core/src/test/java/tech/mcprison/prison/bombs/MineBombEffectsDataTest.java diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 54d2559ff..a70f4c696 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.6 2021-11-26 +* **Mine Bombs: Setup a test unit test to confirm that the sorting of the EffectStates is as expected.** +Needs to be: placed, explode, finished. + + * **Mine Bombs: Add the sound effects and visual effects to the default test bombs.** NOTE: Some of these settings may not work on all versions of spigot, and some may not work on any version. diff --git a/prison-core/src/test/java/tech/mcprison/prison/bombs/MineBombEffectsDataTest.java b/prison-core/src/test/java/tech/mcprison/prison/bombs/MineBombEffectsDataTest.java new file mode 100644 index 000000000..791b3ae71 --- /dev/null +++ b/prison-core/src/test/java/tech/mcprison/prison/bombs/MineBombEffectsDataTest.java @@ -0,0 +1,38 @@ +package tech.mcprison.prison.bombs; + +import static org.junit.Assert.*; + +import java.util.TreeSet; + +import org.junit.Test; + +public class MineBombEffectsDataTest + extends MineBombEffectsData +{ + + @Test + public final void testCompare() + { + + MineBombEffectsData mbef01 = new MineBombEffectsData("ABC", EffectState.explode, 0 ); + MineBombEffectsData mbef02 = new MineBombEffectsData("ABC", EffectState.placed, 0 ); + + MineBombEffectsData mbef03 = new MineBombEffectsData("XYZ", EffectState.placed, 3 ); + + assertEquals( 1, compare( mbef01, mbef02 ) ); + + TreeSet xParticleEffects = new TreeSet<>( new MineBombEffectsData() ); + + xParticleEffects.add( mbef02 ); + xParticleEffects.add( mbef03 ); + xParticleEffects.add( mbef01 ); + + // mbef02 should be sorted "first": + assertEquals( mbef02, xParticleEffects.first() ); + + // mbef01 should be sorted "last": + assertEquals( mbef01, xParticleEffects.last() ); + + } + +} From 8437d88a9ec253fdf03be9b696eeaac7a5769732 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 26 Nov 2021 11:08:53 -0500 Subject: [PATCH 148/283] Mine Bombs: Updated the junit test for validating that the EffectState is sorted in the proper order when using the MineBombEffectsData as a comparator. --- docs/changelog_v3.3.x.md | 3 ++ .../prison/bombs/MineBombEffectsDataTest.java | 35 ++++++++++++++----- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index a70f4c696..46d0c6fee 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.6 2021-11-26 +* **Mine Bombs: Updated the junit test for validating that the EffectState is sorted in the proper order when using the MineBombEffectsData as a comparator.** + + * **Mine Bombs: Setup a test unit test to confirm that the sorting of the EffectStates is as expected.** Needs to be: placed, explode, finished. diff --git a/prison-core/src/test/java/tech/mcprison/prison/bombs/MineBombEffectsDataTest.java b/prison-core/src/test/java/tech/mcprison/prison/bombs/MineBombEffectsDataTest.java index 791b3ae71..e958991ff 100644 --- a/prison-core/src/test/java/tech/mcprison/prison/bombs/MineBombEffectsDataTest.java +++ b/prison-core/src/test/java/tech/mcprison/prison/bombs/MineBombEffectsDataTest.java @@ -1,7 +1,9 @@ package tech.mcprison.prison.bombs; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import java.util.ArrayList; +import java.util.List; import java.util.TreeSet; import org.junit.Test; @@ -15,23 +17,40 @@ public final void testCompare() { MineBombEffectsData mbef01 = new MineBombEffectsData("ABC", EffectState.explode, 0 ); - MineBombEffectsData mbef02 = new MineBombEffectsData("ABC", EffectState.placed, 0 ); + MineBombEffectsData mbef02 = new MineBombEffectsData("XYZ", EffectState.placed, 3 ); - MineBombEffectsData mbef03 = new MineBombEffectsData("XYZ", EffectState.placed, 3 ); + MineBombEffectsData mbef03 = new MineBombEffectsData("BDF", EffectState.finished, 14 ); + MineBombEffectsData mbef04 = new MineBombEffectsData("DEF", EffectState.finished, 0 ); + MineBombEffectsData mbef05 = new MineBombEffectsData("ABC", EffectState.placed, 0 ); + + assertEquals( 1, compare( mbef01, mbef02 ) ); TreeSet xParticleEffects = new TreeSet<>( new MineBombEffectsData() ); + xParticleEffects.add( mbef01 ); xParticleEffects.add( mbef02 ); xParticleEffects.add( mbef03 ); - xParticleEffects.add( mbef01 ); + xParticleEffects.add( mbef04 ); + xParticleEffects.add( mbef05 ); + + List testList = new ArrayList<>( xParticleEffects ); + + // mbef05 should be sorted "first": + assertEquals( mbef05, xParticleEffects.first() ); + + // mbef03 should be sorted "last": + assertEquals( mbef03, xParticleEffects.last() ); + - // mbef02 should be sorted "first": - assertEquals( mbef02, xParticleEffects.first() ); + assertEquals( 5, testList.size() ); - // mbef01 should be sorted "last": - assertEquals( mbef01, xParticleEffects.last() ); + assertEquals( mbef05, testList.get( 0 ) ); + assertEquals( mbef02, testList.get( 1 ) ); + assertEquals( mbef01, testList.get( 2 ) ); + assertEquals( mbef04, testList.get( 3 ) ); + assertEquals( mbef03, testList.get( 4 ) ); } From 52863d66d514b22aaa91bc961b2942529604b448 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 26 Nov 2021 11:13:25 -0500 Subject: [PATCH 149/283] Mine Bombs: Updated the listings of the mine bombs, which now includes full detail including the visual and sound effects, the list of shapes, list of sounds, and list of visual effects that can be used. --- docs/changelog_v3.3.x.md | 3 + .../spigot/utils/PrisonUtilsMineBombs.java | 146 +++++++++++++++++- 2 files changed, 144 insertions(+), 5 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 46d0c6fee..44ac36523 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.6 2021-11-26 +* **Mine Bombs: Updated the listings of the mine bombs, which now includes full detail including the visual and sound effects, the list of shapes, list of sounds, and list of visual effects that can be used.** + + * **Mine Bombs: Updated the junit test for validating that the EffectState is sorted in the proper order when using the MineBombEffectsData as a comparator.** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java index d6fbf5b34..5bd142222 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java @@ -86,7 +86,7 @@ public void utilsMineBombs( CommandSender sender, String worldCoordinates, - @Arg(name = "shape", description = "Shape of Explosion. [sphere]", + @Arg(name = "shape", description = "Shape of Explosion. Use the command '/prison utils bomb list' for a list of shapes. [sphere]", def = "sphere") String shape, @Arg(name = "radiusSize", description = "Size of Explosion in block radius. [1 though 20]", def = "3" ) @@ -160,10 +160,14 @@ public void utilsMineBombs( CommandSender sender, @Command(identifier = "prison utils bomb list", - description = "A list of all available bombs.", + description = "A list of all available bombs, including their full details. " + + "This command also shows a list of settings for shapes, sounds, and visual effects.", onlyPlayers = false, permissions = "prison.utils.bombs" ) - public void utilsMineBombsList( CommandSender sender + public void utilsMineBombsList( CommandSender sender, + @Arg(name = "option", description = "Options: Show 'all' bomb details. " + + "'shapes', 'sounds', and 'visuals' lists valid settings " + + "to be used with the bombs. [all shapes sounds visuals]", def = "" ) String options ) { @@ -177,6 +181,102 @@ public void utilsMineBombsList( CommandSender sender List messages = new ArrayList<>(); + boolean optAll = options != null && options.toLowerCase().contains( "all" ); + + if ( options != null && options.toLowerCase().contains( "shapes" ) ) { + // exit after showing shapes: + + messages.add( "&7Shapes:" ); + List shapes = ExplosionShape.asList(); + messages.addAll( Text.formatColumnsFromList( shapes, 4 ) ); + + sender.sendMessage( messages.toArray( new String[0] ) ); + return; + } + + if ( options != null && options.toLowerCase().contains( "sounds" ) ) { + List sounds = new ArrayList<>(); + +// // If running less than MC 1.9.0, ie 1.8.x, then use different code for effects: +// boolean is18 = new BluesSpigetSemVerComparator().compareMCVersionTo( "1.9.0" ) < 0 ; +// +// if ( is18 ) { +// +// } + +// for ( Sound p : Sound.values() ) { +// sounds.add( p.name() ); +// } +// +// messages.add( "&7Sound Effects:" ); +// for ( String line : Text.formatColumnsFromList( sounds, 3 ) ) { +// messages.add( " " + line ); +// } +// sounds.clear(); + + + + for ( XSound p : XSound.values() ) { + sounds.add( p.name() ); + } + Collections.sort( sounds ); + + messages.add( "&7XSound Effects:" ); + for ( String line : Text.formatColumnsFromList( sounds, 3 ) ) { + messages.add( " " + line ); + } + + sender.sendMessage( messages.toArray( new String[0] ) ); + return; + } + + if ( options != null && options.toLowerCase().contains( "visuals" ) ) { + List visuals = new ArrayList<>(); + + // bukkit 1.8.8: +// Effect.values() + + // If running less than MC 1.9.0, ie 1.8.x, then use different code for effects: + boolean is18 = new BluesSpigetSemVerComparator().compareMCVersionTo( "1.9.0" ) < 0 ; + + if ( is18 ) { + for ( Effect p : Effect.values() ) { + visuals.add( p.name() ); + } + Collections.sort( visuals ); +// for ( Particle p : Particle.values() ) { +// visuals.add( p.name() ); +// } + + messages.add( "&7Visual Effects (bukkit 1.8.x: Effect):" ); + for ( String line : Text.formatColumnsFromList( visuals, 4 ) ) { + messages.add( " " + line ); + } + + } + else { + + for ( Particle p : Particle.values() ) { + visuals.add( p.name() ); + } + Collections.sort( visuals ); +// for ( Particle p : Particle.values() ) { +// visuals.add( p.name() ); +// } + + messages.add( "&7Visual Effects (Particle):" ); + for ( String line : Text.formatColumnsFromList( visuals, 4 ) ) { + messages.add( " " + line ); + } + + } + + + + sender.sendMessage( messages.toArray( new String[0] ) ); + return; + } + Set keys = mBombs.getConfigData().getBombs().keySet(); for ( String key : keys ) { @@ -260,6 +360,36 @@ public void utilsMineBombsList( CommandSender sender messages.add( " " + bomb.getDescription() ); + if ( optAll ) { + + + List sounds = new ArrayList<>(); + for ( MineBombEffectsData sfx : bomb.getSoundEffects() ) + { + sounds.add( " " + sfx.toString() ); + + } + if ( sounds.size() > 0 ) { + messages.add( " Sound Effects:" ); + messages.addAll( sounds ); + } + + + List visual = new ArrayList<>(); + for ( MineBombEffectsData vfx : bomb.getVisualEffects() ) + { + visual.add( " " + vfx.toStringShort() ); + + } + if ( visual.size() > 0 ) { + messages.add( " Visual Effects:" ); + messages.addAll( visual ); + } + + + + } + // Output.get().log( message, LogLevel.PLAIN ); } @@ -278,7 +408,7 @@ public void utilsMineBombsGive( CommandSender sender, @Arg(name = "playerName", description = "Player name") String playerName, @Arg(name = "bombName", description = "The bomb name, or 'list' to show all available " + - "bombs. [list]", + "bombs, with 'listall' including sound and visual effects. [list listall]", def = "list") String bombName, @Arg(name = "quantity", description = "Quantity of bombs to give. [1 > +]", def = "1" ) @@ -295,7 +425,13 @@ public void utilsMineBombsGive( CommandSender sender, if ( "list".equalsIgnoreCase( bombName ) ) { - utilsMineBombsList( sender ); + utilsMineBombsList( sender, null ); + return; + } + + if ( "listall".equalsIgnoreCase( bombName ) ) { + + utilsMineBombsList( sender, "all" ); return; } From 33dd384dbad6e1d1c4283ec0578d69bd12b32836 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 26 Nov 2021 11:15:57 -0500 Subject: [PATCH 150/283] Mine Bombs: Got the sounds and visual effects hooked up to the explosions. Made many revisions on how all of this works, but pushed the tasks to a new class PrisonUtilsMinBombsTask. --- docs/changelog_v3.3.x.md | 4 + .../tech/mcprison/prison/output/Output.java | 2 +- .../spigot/utils/PrisonUtilsMineBombs.java | 231 +-------- .../utils/PrisonUtilsMineBombsTasks.java | 444 ++++++++++++++++++ 4 files changed, 456 insertions(+), 225 deletions(-) create mode 100644 prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombsTasks.java diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 44ac36523..d5498ab29 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.6 2021-11-26 +* **Mine Bombs: Got the sounds and visual effects hooked up to the explosions.** +Made many revisions on how all of this works, but pushed the tasks to a new class PrisonUtilsMinBombsTask. + + * **Mine Bombs: Updated the listings of the mine bombs, which now includes full detail including the visual and sound effects, the list of shapes, list of sounds, and list of visual effects that can be used.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/output/Output.java b/prison-core/src/main/java/tech/mcprison/prison/output/Output.java index 8289c1e27..9b6d89074 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/output/Output.java +++ b/prison-core/src/main/java/tech/mcprison/prison/output/Output.java @@ -249,7 +249,7 @@ public void log(String message, LogLevel level, Object... args) { String errorMessage = "Error with Java format usage (eg %s): " + " LogLevel: " + level.name() + - " message: [" + message + "] params: " + sb.toString() + + " message: [" + message + "] params: [" + sb.toString() + "]" + " error: [" + e.getMessage() + "]"; Prison.get().getPlatform().logCore( diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java index 5bd142222..282903af8 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java @@ -2,23 +2,23 @@ import java.text.DecimalFormat; import java.util.ArrayList; +import java.util.Collections; import java.util.List; -import java.util.Map; -import java.util.Random; import java.util.Set; -import java.util.TreeMap; import org.bukkit.Bukkit; -import org.bukkit.enchantments.Enchantment; +import org.bukkit.Effect; +import org.bukkit.Particle; import org.bukkit.entity.Item; import org.bukkit.entity.Player; -import org.bukkit.scheduler.BukkitRunnable; import com.cryptomorin.xseries.XMaterial; +import com.cryptomorin.xseries.XSound; import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; import tech.mcprison.prison.autofeatures.AutoFeaturesWrapper; import tech.mcprison.prison.bombs.MineBombData; +import tech.mcprison.prison.bombs.MineBombEffectsData; import tech.mcprison.prison.bombs.MineBombs; import tech.mcprison.prison.bombs.MineBombs.ExplosionShape; import tech.mcprison.prison.commands.Arg; @@ -26,7 +26,6 @@ import tech.mcprison.prison.internal.CommandSender; import tech.mcprison.prison.internal.block.Block; import tech.mcprison.prison.output.Output; -import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.api.ExplosiveBlockBreakEvent; import tech.mcprison.prison.spigot.block.SpigotBlock; import tech.mcprison.prison.spigot.block.SpigotItemStack; @@ -38,7 +37,7 @@ import tech.mcprison.prison.util.Text; public class PrisonUtilsMineBombs - extends PrisonUtils + extends PrisonUtilsMineBombsTasks { public static final String MINE_BOMBS_LORE_1 = "&4Prison Mine Bomb:"; public static final String MINE_BOMBS_LORE_2_PREFIX = " &7"; @@ -46,7 +45,7 @@ public class PrisonUtilsMineBombs private boolean enableMineBombs = false; - public static final Map playerCooldowns = new TreeMap<>(); + public PrisonUtilsMineBombs() { super(); @@ -818,209 +817,7 @@ else if ( bomb != null ) { return isABomb; } -// public static boolean addPlayerCooldown( String playerUUID ) { -// return addPlayerCooldown( playerUUID, MINE_BOMBS_COOLDOWN_TICKS ); -// } - - /** - *

If a cooldown is not setup for the player, this will try to add one and - * will return a value of true to indicate the a cooldown was set. If a cooldown - * already exists, then this will return a value of false. - *

- * - * @param playerUUID - * @param ticks - * @return - */ - public static boolean addPlayerCooldown( String playerUUID, int ticks ) { - boolean results = false; - - if ( !playerCooldowns.containsKey( playerUUID ) || - playerCooldowns.get( playerUUID ) <= 0 ) { - - playerCooldowns.put( playerUUID, ticks ); - - new BukkitRunnable() { - - @Override - public void run() { - - int ticksRemaining = playerCooldowns.get( playerUUID ) - 10; - - if ( ticksRemaining <= 0 ) { - playerCooldowns.remove( playerUUID ); - this.cancel(); - } - else { - playerCooldowns.put( playerUUID, ticksRemaining ); - } - - } - }.runTaskTimer( SpigotPrison.getInstance(), 10, 10); - - results = true; - } - - return results; - } - - public static int checkPlayerCooldown( String playerUUID ) { - int results = 0; - - if ( playerCooldowns.containsKey( playerUUID ) ) { - results = playerCooldowns.get( playerUUID ); - } - - return results; - } - public static boolean setoffBombDelayed( SpigotPlayer sPlayer, MineBombData bomb, Item droppedBomb, - SpigotBlock targetBlock ) { - boolean results = false; - - new BukkitRunnable() { - - @Override - public void run() { - - // Remove the item that the player threw: - droppedBomb.remove(); - - Location location = targetBlock.getLocation(); - - if ( location == null ) { - location = sPlayer.getLocation(); - } - - - MineBombs mBombs = MineBombs.getInstance(); - - List blocks = calculatBlocksForExplosion( bomb, location, mBombs ); - - -// SpigotBlock targetBlock = (SpigotBlock) world.getBlockAt( location ); - - - ExplosiveBlockBreakEvent explodeEvent = new ExplosiveBlockBreakEvent( - targetBlock.getWrapper(), sPlayer.getWrapper(), blocks ); - explodeEvent.setTriggeredBy( bomb.getName() ); - explodeEvent.setMineBomb( bomb ); - - // Set the toolInHand that needs to be used for the bomb: - // Default to a diamond pickaxe if not specified. - // The bomb must define a tool, otherwise auto features will - // use the mine bombs that the player is holding, or if it was their - // last one, it would be just AIR: - String toolInHandName = bomb.getToolInHandName(); - if ( toolInHandName == null || toolInHandName.trim().isEmpty() ) { - XMaterial xMat = XMaterial.DIAMOND_PICKAXE; - toolInHandName = xMat.name(); - } - - XMaterial xMatTool = XMaterial.matchXMaterial( toolInHandName ) - .orElse( XMaterial.DIAMOND_PICKAXE ); - SpigotItemStack toolInHand = new SpigotItemStack( xMatTool.parseItem() ); - - setFortune( toolInHand, bomb.getToolInHandFortuneLevel() ); - - - explodeEvent.setToolInHand( toolInHand ); - - - // Mine bombs should not calculate durability: - explodeEvent.setCalculateDurability( false ); - - - // Normally the explosion will ONLY work if the center target block was non-AIR. - // This setting allows the explosion to be processed even if it is air. - explodeEvent.setForceIfAirBlock( true ); - - Bukkit.getServer().getPluginManager().callEvent( explodeEvent ); - - if ( explodeEvent.isCancelled() ) { - - if ( Output.get().isDebug() ) { - Output.get().logDebug( "Mine Bomb's ExplosiveBlockBreakEvent has been canceled. " + - "It may have been processed successfully." ); - } - } - else { - // If it wasn't canceled, then it may not have been handled - - if ( Output.get().isDebug() ) { - Output.get().logDebug( "Mine Bomb's ExplosiveBlockBreakEvent has NOT been canceled." ); - } - } - - - } - - private List calculatBlocksForExplosion( MineBombData bomb, Location location, - MineBombs mBombs ) - { - List blocks = new ArrayList<>(); - - // Calculate all the locations that are included in the explosion: - List blockLocations = null; - - - ExplosionShape shape = ExplosionShape.fromString( bomb.getExplosionShape() ); - - switch ( shape ) - { - case cube: - { - blockLocations = mBombs.calculateCube( location, - bomb.getRadius() ); - break; - } - - case sphereHollow: - { - blockLocations = mBombs.calculateSphere( location, - bomb.getRadius(), true, bomb.getRadiusInner() ); - break; - } - - case sphere: - default: - { - blockLocations = mBombs.calculateSphere( location, - bomb.getRadius(), false ); - break; - } - } - - - SpigotWorld world = (SpigotWorld) location.getWorld(); - - - // Honor the percent chance for including the block: - double removalChance = bomb.getRemovalChance(); - Random random = new Random(); - - - // Convert to spigot blocks: - for ( Location bLocation : blockLocations ) { - double chance = random.nextDouble() * 100.0d; - - if ( chance <= removalChance ) { - - SpigotBlock sBlock = (SpigotBlock) world.getBlockAt( bLocation ); - if ( !sBlock.isEmpty() ) { - - blocks.add( sBlock.getWrapper() ); - } - } - } - return blocks; - } - }.runTaskLater( SpigotPrison.getInstance(), bomb.getFuseDelayTicks() ); - - //.runTaskTimer( SpigotPrison.getInstance(), 10, 10); - - return results; - } // protected short getFortune(SpigotItemStack itemInHand){ @@ -1042,21 +839,7 @@ private List calculatBlocksForExplosion( MineBombData bo // return results; // } - protected static void setFortune( SpigotItemStack itemInHand, int fortuneLevel ) { - - if ( itemInHand != null && - itemInHand.getBukkitStack() != null && - itemInHand.getBukkitStack().hasItemMeta() ) { - - itemInHand.getBukkitStack().addUnsafeEnchantment( Enchantment.LOOT_BONUS_BLOCKS, fortuneLevel ); - -// ItemMeta meta = itemInHand.getBukkitStack().getItemMeta(); -// meta.addEnchant( Enchantment.LOOT_BONUS_BLOCKS, fortuneLevel, true ); -// itemInHand.getBukkitStack().setItemMeta( meta ); - - } - } public static double getPlayerCoolDownRemaining() { diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombsTasks.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombsTasks.java new file mode 100644 index 000000000..a004625bd --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombsTasks.java @@ -0,0 +1,444 @@ +package tech.mcprison.prison.spigot.utils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.TreeMap; + +import org.bukkit.Bukkit; +import org.bukkit.Effect; +import org.bukkit.Particle; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Item; +import org.bukkit.scheduler.BukkitRunnable; + +import com.cryptomorin.xseries.XMaterial; +import com.cryptomorin.xseries.XSound; +import com.cryptomorin.xseries.particles.ParticleDisplay; + +import tech.mcprison.prison.bombs.MineBombData; +import tech.mcprison.prison.bombs.MineBombEffectsData; +import tech.mcprison.prison.bombs.MineBombs; +import tech.mcprison.prison.bombs.MineBombEffectsData.EffectState; +import tech.mcprison.prison.bombs.MineBombs.ExplosionOrientation; +import tech.mcprison.prison.bombs.MineBombs.ExplosionShape; +import tech.mcprison.prison.output.Output; +import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.api.ExplosiveBlockBreakEvent; +import tech.mcprison.prison.spigot.block.SpigotBlock; +import tech.mcprison.prison.spigot.block.SpigotItemStack; +import tech.mcprison.prison.spigot.game.SpigotPlayer; +import tech.mcprison.prison.spigot.game.SpigotWorld; +import tech.mcprison.prison.spigot.spiget.BluesSpigetSemVerComparator; +import tech.mcprison.prison.util.Location; + +public class PrisonUtilsMineBombsTasks + extends PrisonUtils +{ + public static final Map playerCooldowns = new TreeMap<>(); + + + public PrisonUtilsMineBombsTasks() { + super(); + + initialize(); + } + + @Override + protected Boolean initialize() + { + + return null; + } + + + protected static void setFortune( SpigotItemStack itemInHand, int fortuneLevel ) + { + + if ( itemInHand != null && itemInHand.getBukkitStack() != null && itemInHand.getBukkitStack().hasItemMeta() ) + { + + itemInHand.getBukkitStack().addUnsafeEnchantment( Enchantment.LOOT_BONUS_BLOCKS, fortuneLevel ); + + // ItemMeta meta = itemInHand.getBukkitStack().getItemMeta(); + // meta.addEnchant( Enchantment.LOOT_BONUS_BLOCKS, fortuneLevel, + // true ); + // itemInHand.getBukkitStack().setItemMeta( meta ); + + } + + } + + // public static boolean addPlayerCooldown( String playerUUID ) { + // return addPlayerCooldown( playerUUID, MINE_BOMBS_COOLDOWN_TICKS ); + // } + + /** + *

+ * If a cooldown is not setup for the player, this will try to add one and + * will return a value of true to indicate the a cooldown was set. If a + * cooldown already exists, then this will return a value of false. + *

+ * + * @param playerUUID + * @param ticks + * @return + */ + public static boolean addPlayerCooldown( String playerUUID, int ticks ) + { + boolean results = false; + + if ( !playerCooldowns.containsKey( playerUUID ) || playerCooldowns.get( playerUUID ) <= 0 ) + { + + playerCooldowns.put( playerUUID, ticks ); + + new BukkitRunnable() + { + + @Override + public void run() + { + + int ticksRemaining = playerCooldowns.get( playerUUID ) - 10; + + if ( ticksRemaining <= 0 ) + { + playerCooldowns.remove( playerUUID ); + this.cancel(); + } + else + { + playerCooldowns.put( playerUUID, ticksRemaining ); + } + + } + }.runTaskTimer( SpigotPrison.getInstance(), 10, 10 ); + + results = true; + } + + return results; + } + + public static int checkPlayerCooldown( String playerUUID ) + { + int results = 0; + + if ( playerCooldowns.containsKey( playerUUID ) ) + { + results = playerCooldowns.get( playerUUID ); + } + + return results; + } + + + public static void submitBombEffects( MineBombData bomb, EffectState effectState, + Location location, Item droppedBomb ) { + + long lastTick = -1; + + // If running MC 1.9.0 or higher, then can use the glowing feature. Ignore for 1.8.x. + boolean is18 = new BluesSpigetSemVerComparator().compareMCVersionTo( "1.9.0" ) < 0 ; + + SpigotBlock sBlock = (SpigotBlock) location.getBlockAt(); + org.bukkit.Location bLocation = sBlock.getWrapper().getLocation(); + + for ( MineBombEffectsData effect : bomb.getSoundEffects() ) + { + if ( effect.getEffectState() == effectState ) { + + new BukkitRunnable() { + + @Override + public void run() { + try { + + XSound xSound = XSound.matchXSound( effect.getEffectName() ).orElse( null ); + + if ( xSound != null ) { + xSound.play( bLocation, effect.getVolumne(), effect.getPitch() ); + } + } + catch ( IllegalArgumentException | + NullPointerException e ) { + Output.get().logWarn( + String.format( + "Invalid Sound Effect value in bomb %s: %s Error: [%s]", + bomb.getName(), + effect.toString(), e.getMessage()) ); + } + } + }.runTaskLater( SpigotPrison.getInstance(), effect.getOffsetTicks() ); + } + + if ( effect.getEffectState() == EffectState.finished && effect.getOffsetTicks() > lastTick ) { + lastTick = effect.getOffsetTicks(); + } + } + + for ( MineBombEffectsData effect : bomb.getVisualEffects() ) + { + if ( effect.getEffectState() == effectState ) { + + new BukkitRunnable() { + + @Override + public void run() { + + + try { + + if ( is18 ) { + + Effect eff18 = Effect.valueOf( effect.getEffectName() ); + + if ( eff18 != null ) { + bLocation.getWorld().playEffect( bLocation, eff18, 1.0f ); + } + } + else { + Particle particle = Particle.valueOf( effect.getEffectName() ); + if ( particle != null ) { + + ParticleDisplay.display( bLocation, particle ); + } + } + } + catch ( IllegalArgumentException | + NullPointerException e ) { + Output.get().logWarn( + String.format( + "Invalid Visual Effect value in bomb %s: %s Error: [%s]", + bomb.getName(), + effect.toString(), e.getMessage()) ); + } + + } + }.runTaskLater( SpigotPrison.getInstance(), effect.getOffsetTicks() ); + + } + + if ( effect.getEffectState() == EffectState.finished && effect.getOffsetTicks() > lastTick ) { + lastTick = effect.getOffsetTicks(); + } + + } + + // After the last sound and visual is played, then remove the dropped bomb: + if ( effectState == EffectState.finished && lastTick >= 0 ) { + new BukkitRunnable() { + + @Override + public void run() { + droppedBomb.remove(); + } + }.runTaskLater( SpigotPrison.getInstance(), lastTick + 1 ); + } + } + + public static boolean setoffBombDelayed( SpigotPlayer sPlayer, MineBombData bomb, Item droppedBomb, + SpigotBlock targetBlock ) { + boolean results = false; + + final Location location = ( targetBlock.getLocation() == null ? + sPlayer.getLocation() : targetBlock.getLocation() ); + + + submitBombEffects( bomb, EffectState.placed, location, droppedBomb ); + + new BukkitRunnable() { + + @Override + public void run() { + + // Remove the item that the player threw: +// droppedBomb.remove(); + + submitBombEffects( bomb, EffectState.explode, location, droppedBomb ); + + MineBombs mBombs = MineBombs.getInstance(); + + List blocks = calculatBlocksForExplosion( bomb, location, mBombs ); + + +// SpigotBlock targetBlock = (SpigotBlock) world.getBlockAt( location ); + + + ExplosiveBlockBreakEvent explodeEvent = new ExplosiveBlockBreakEvent( + targetBlock.getWrapper(), sPlayer.getWrapper(), blocks ); + explodeEvent.setTriggeredBy( bomb.getName() ); + explodeEvent.setMineBomb( bomb ); + + // Set the toolInHand that needs to be used for the bomb: + // Default to a diamond pickaxe if not specified. + // The bomb must define a tool, otherwise auto features will + // use the mine bombs that the player is holding, or if it was their + // last one, it would be just AIR: + String toolInHandName = bomb.getToolInHandName(); + if ( toolInHandName == null || toolInHandName.trim().isEmpty() ) { + XMaterial xMat = XMaterial.DIAMOND_PICKAXE; + toolInHandName = xMat.name(); + } + + XMaterial xMatTool = XMaterial.matchXMaterial( toolInHandName ) + .orElse( XMaterial.DIAMOND_PICKAXE ); + SpigotItemStack toolInHand = new SpigotItemStack( xMatTool.parseItem() ); + + setFortune( toolInHand, bomb.getToolInHandFortuneLevel() ); + + + explodeEvent.setToolInHand( toolInHand ); + + + // Mine bombs should not calculate durability: + explodeEvent.setCalculateDurability( false ); + + + // Normally the explosion will ONLY work if the center target block was non-AIR. + // This setting allows the explosion to be processed even if it is air. + explodeEvent.setForceIfAirBlock( true ); + + Bukkit.getServer().getPluginManager().callEvent( explodeEvent ); + + // We want the event to be cancelled since that means prison processed it: + if ( explodeEvent.isCancelled() ) { + + // Run all of the EffectState.finished effects: + submitBombEffects( bomb, EffectState.finished, location, droppedBomb ); + + if ( Output.get().isDebug() ) { + Output.get().logDebug( "Mine Bomb's ExplosiveBlockBreakEvent has been canceled. " + + "It may have been processed successfully." ); + } + } + else { + // If it wasn't canceled, then it may not have been handled + + droppedBomb.remove(); + + if ( Output.get().isDebug() ) { + Output.get().logDebug( "Mine Bomb's ExplosiveBlockBreakEvent has NOT been canceled." ); + } + } + + + } + + private List calculatBlocksForExplosion( MineBombData bomb, Location location, + MineBombs mBombs ) + { + List blocks = new ArrayList<>(); + + // Calculate all the locations that are included in the explosion: + List blockLocations = null; + + + ExplosionShape shape = ExplosionShape.fromString( bomb.getExplosionShape() ); + + switch ( shape ) + { + case cube: + { + blockLocations = mBombs.calculateCube( location, + bomb.getRadius() ); + break; + } + + case ring_x: + { + blockLocations = mBombs.calculateSphere( location, + bomb.getRadius(), true, bomb.getRadiusInner(), + ExplosionOrientation.x_axis ); + break; + } + case ring_y: + { + blockLocations = mBombs.calculateSphere( location, + bomb.getRadius(), true, bomb.getRadiusInner(), + ExplosionOrientation.y_axis ); + break; + } + case ring_z: + { + blockLocations = mBombs.calculateSphere( location, + bomb.getRadius(), true, bomb.getRadiusInner(), + ExplosionOrientation.z_axis ); + break; + } + + + case disk_x: + { + blockLocations = mBombs.calculateSphere( location, + bomb.getRadius(), false, 0, + ExplosionOrientation.x_axis ); + break; + } + case disk_y: + { + blockLocations = mBombs.calculateSphere( location, + bomb.getRadius(), false, 0, + ExplosionOrientation.y_axis ); + break; + } + case disk_z: + { + blockLocations = mBombs.calculateSphere( location, + bomb.getRadius(), false, 0, + ExplosionOrientation.z_axis ); + break; + } + + + + case sphereHollow: + { + blockLocations = mBombs.calculateSphere( location, + bomb.getRadius(), true, bomb.getRadiusInner() ); + break; + } + + case sphere: + default: + { + blockLocations = mBombs.calculateSphere( location, + bomb.getRadius(), false ); + break; + } + } + + + SpigotWorld world = (SpigotWorld) location.getWorld(); + + + // Honor the percent chance for including the block: + double removalChance = bomb.getRemovalChance(); + Random random = new Random(); + + + // Convert to spigot blocks: + for ( Location bLocation : blockLocations ) { + double chance = random.nextDouble() * 100.0d; + + if ( chance <= removalChance ) { + + SpigotBlock sBlock = (SpigotBlock) world.getBlockAt( bLocation ); + if ( !sBlock.isEmpty() ) { + + blocks.add( sBlock.getWrapper() ); + } + } + } + return blocks; + } + }.runTaskLater( SpigotPrison.getInstance(), bomb.getFuseDelayTicks() ); + + //.runTaskTimer( SpigotPrison.getInstance(), 10, 10); + + return results; + } + +} From fab7b20586e82d7926dd35811519116cd7b7475f Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 26 Nov 2021 20:51:20 -0500 Subject: [PATCH 151/283] Mine Bombs: Setup some changes in how classes are related to each other so as to prepare for significant changes. --- docs/changelog_v3.3.x.md | 3 +++ .../prison/spigot/game/SpigotWorld.java | 19 +++++++++++++++++++ .../spigot/utils/PrisonBombListener.java | 16 ++++++++++++++++ .../spigot/utils/PrisonUtilsModule.java | 2 +- 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index d5498ab29..683c806dd 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.6 2021-11-26 +* **Mine Bombs: Setup some changes in how classes are related to each other so as to prepare for significant changes.** + + * **Mine Bombs: Got the sounds and visual effects hooked up to the explosions.** Made many revisions on how all of this works, but pushed the tasks to a new class PrisonUtilsMinBombsTask. diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotWorld.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotWorld.java index 85a93fdc6..1b715f182 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotWorld.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotWorld.java @@ -27,6 +27,7 @@ import tech.mcprison.prison.PrisonAPI; import tech.mcprison.prison.integration.CustomBlockIntegration; +import tech.mcprison.prison.internal.ItemStack; import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.internal.PrisonStatsElapsedTimeNanos; import tech.mcprison.prison.internal.World; @@ -37,6 +38,7 @@ import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.SpigotUtil; import tech.mcprison.prison.spigot.block.SpigotBlock; +import tech.mcprison.prison.spigot.block.SpigotItemStack; import tech.mcprison.prison.spigot.compat.SpigotCompatibility; import tech.mcprison.prison.util.Location; @@ -75,6 +77,21 @@ public Block getBlockAt(Location location) { return new SpigotBlock( bukkitWorld.getBlockAt(SpigotUtil.prisonLocationToBukkit(location))); } + public SpigotBlock getSpigotBlockAt(Location location) { + return new SpigotBlock( + bukkitWorld.getBlockAt(SpigotUtil.prisonLocationToBukkit(location))); + } + + public org.bukkit.Location getBukkitLocation(Location location) { + return SpigotUtil.prisonLocationToBukkit(location); + } + + public org.bukkit.inventory.ItemStack getBukkitItemStack( ItemStack itemStack ) { + + SpigotItemStack sItemStack = (SpigotItemStack) itemStack; + + return sItemStack.getBukkitStack(); + } @Override public void setBlock( PrisonBlock block, int x, int y, int z ) { @@ -171,4 +188,6 @@ public void run() { public org.bukkit.World getWrapper() { return bukkitWorld; } + + } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java index b5459de20..f07aedb3a 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java @@ -31,6 +31,13 @@ public class PrisonBombListener implements Listener { + private PrisonUtilsMineBombs prisonUtilsMineBombs; + + public PrisonBombListener( PrisonUtilsMineBombs utilsMineBombs ) { + super(); + + prisonUtilsMineBombs = utilsMineBombs; + } @EventHandler( priority = EventPriority.LOW ) public void onInteract( PlayerInteractEvent event ) { @@ -149,6 +156,13 @@ public void onBlockPlace3( PlayerInteractEvent event ) { } + public PrisonUtilsMineBombs getPrisonUtilsMineBombs() { + return prisonUtilsMineBombs; + } + public void setPrisonUtilsMineBombs( PrisonUtilsMineBombs prisonUtilsMineBombs ) { + this.prisonUtilsMineBombs = prisonUtilsMineBombs; + } + // @EventHandler( priority = EventPriority.HIGHEST, ignoreCancelled = false ) // public void onBlockPlace3( BlockDropItemEvent event ) { // @@ -171,4 +185,6 @@ public void onBlockPlace3( PlayerInteractEvent event ) { // } // // } + + } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsModule.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsModule.java index 7cb23f1da..6778a9bd1 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsModule.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsModule.java @@ -134,7 +134,7 @@ public void enable() { // Only Register the Bomb Listener if bombs are active: Bukkit.getPluginManager().registerEvents( - new PrisonBombListener(), SpigotPrison.getInstance()); + new PrisonBombListener( utils ), SpigotPrison.getInstance()); } From ceaf313310ed704ebf4fccd6fb2b8e80a0122518 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 26 Nov 2021 20:53:46 -0500 Subject: [PATCH 152/283] Mine Bombs: Added more effects to the examples. Removed some that would not work. These are not perfectly selected and may not work for most versions of spigot. The visual effect do not appear to really do much. --- docs/changelog_v3.3.x.md | 4 ++ .../tech/mcprison/prison/bombs/MineBombs.java | 67 ++++++++++++++++--- 2 files changed, 60 insertions(+), 11 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 683c806dd..6d301af3c 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.6 2021-11-26 +* **Mine Bombs: Added more effects to the examples.** +Removed some that would not work. These are not perfectly selected and may not work for most versions of spigot. The visual effect do not appear to really do much. + + * **Mine Bombs: Setup some changes in how classes are related to each other so as to prepare for significant changes.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java index 3707f8375..579b4079b 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java @@ -263,20 +263,26 @@ public void setupDefaultMineBombData() MineBombEffectsData mbeSound03 = new MineBombEffectsData( "ENTITY_GENERIC_EXPLODE", EffectState.explode, 0 ); MineBombEffectsData mbeSound04 = new MineBombEffectsData( "ENTITY_DRAGON_FIREBALL_EXPLODE", EffectState.explode, 0 ); - + // Does not work with spigot 1.8.x: MineBombEffectsData mbeExplode01 = new MineBombEffectsData( "FIREWORKS_SPARK", EffectState.placed, 0 ); + // Does not work with spigot 1.8.x: MineBombEffectsData mbeExplode02 = new MineBombEffectsData( "BUBBLE_COLUMN_UP", EffectState.placed, 0 ); MineBombEffectsData mbeExplode03 = new MineBombEffectsData( "ENCHANTMENT_TABLE", EffectState.placed, 0 ); // MineBombEffectsData mbeExplode05 = new MineBombEffectsData( "END_ROD", EffectState.placed, 0 ); MineBombEffectsData mbeExplode04 = new MineBombEffectsData( "FLAME", EffectState.placed, 0 ); + // Does not work with spigot 1.8.x: MineBombEffectsData mbeExplode08 = new MineBombEffectsData( "DRAGON_BREATH", EffectState.placed, 0 ); + MineBombEffectsData mbeExplode06a = new MineBombEffectsData( "SMOKE", EffectState.placed, 0 ); + // Does not work with spigot 1.8.x: MineBombEffectsData mbeExplode06 = new MineBombEffectsData( "SMOKE_NORMAL", EffectState.placed, 0 ); + // Does not work with spigot 1.8.x: MineBombEffectsData mbeExplode07 = new MineBombEffectsData( "SMOKE_LARGE", EffectState.placed, 0 ); MineBombEffectsData mbeExplode10 = new MineBombEffectsData( "EXPLOSION_NORMAL", EffectState.explode, 0 ); MineBombEffectsData mbeExplode11 = new MineBombEffectsData( "EXPLOSION_LARGE", EffectState.explode, 0 ); + // Does not work with spigot 1.8.x: MineBombEffectsData mbeExplode12 = new MineBombEffectsData( "EXPLOSION_HUGE", EffectState.explode, 0 ); @@ -291,8 +297,12 @@ public void setupDefaultMineBombData() mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 30 ) ); mbd.getSoundEffects().add( mbeSound03.clone() ); - mbd.getVisualEffects().add( mbeExplode01.clone() ); - mbd.getVisualEffects().add( mbeExplode02.clone().setOffsetTicks( 30 ) ); + mbd.getVisualEffects().add( mbeExplode04.clone() ); + mbd.getVisualEffects().add( mbeExplode03.clone().setOffsetTicks( 30 ) ); + + mbd.getVisualEffects().add( mbeExplode06a.clone() ); + mbd.getVisualEffects().add( mbeExplode10.clone() ); + mbd.getVisualEffects().add( mbeExplode06.clone() ); getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); @@ -310,8 +320,11 @@ public void setupDefaultMineBombData() mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 30 ) ); mbd.getSoundEffects().add( mbeSound03.clone() ); - mbd.getVisualEffects().add( mbeExplode01.clone() ); - mbd.getVisualEffects().add( mbeExplode02.clone().setOffsetTicks( 30 ) ); + mbd.getVisualEffects().add( mbeExplode04.clone() ); + mbd.getVisualEffects().add( mbeExplode03.clone().setOffsetTicks( 30 ) ); + + mbd.getVisualEffects().add( mbeExplode10.clone() ); + mbd.getVisualEffects().add( mbeExplode06.clone() ); mbd.setCooldownTicks( 60 ); @@ -332,8 +345,12 @@ public void setupDefaultMineBombData() mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 30 ) ); mbd.getSoundEffects().add( mbeSound03.clone().setVolumne( 2.0f ) ); - mbd.getVisualEffects().add( mbeExplode01.clone() ); - mbd.getVisualEffects().add( mbeExplode02.clone().setOffsetTicks( 30 ) ); + mbd.getVisualEffects().add( mbeExplode04.clone() ); + mbd.getVisualEffects().add( mbeExplode03.clone().setOffsetTicks( 30 ) ); + + mbd.getVisualEffects().add( mbeExplode10.clone() ); + mbd.getVisualEffects().add( mbeExplode06.clone() ); + mbd.getVisualEffects().add( mbeExplode06a.clone() ); mbd.setCooldownTicks( 60 ); @@ -351,23 +368,44 @@ public void setupDefaultMineBombData() mbd.setToolInHandFortuneLevel( 13 ); mbd.getSoundEffects().add( mbeSound01.clone() ); - mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 30 ).setVolumne( 2.0f ) ); - mbd.getSoundEffects().add( mbeSound03.clone().setVolumne( 3.0f ) ); + mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 10 ).setVolumne( 0.25f ).setPitch( 0.25f ) ); + mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 20 ).setVolumne( 0.5f ).setPitch( 0.5f ) ); + mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 30 ).setVolumne( 1.0f ).setPitch( 0.75f ) ); + mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 40 ).setVolumne( 2.0f ).setPitch( 1.5f ) ); + mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 50 ).setVolumne( 5.0f ).setPitch( 2.5f ) ); + + mbd.getSoundEffects().add( mbeSound03.clone().setOffsetTicks( 0 ).setVolumne( 3.0f ) ); + mbd.getSoundEffects().add( mbeSound04.clone().setOffsetTicks( 5 ).setVolumne( 1.5f ) ); + mbd.getSoundEffects().add( mbeSound03.clone().setOffsetTicks( 10 ).setVolumne( 2.5f ) ); + mbd.getSoundEffects().add( mbeSound04.clone().setOffsetTicks( 15 ).setVolumne( 1.0f ) ); + mbd.getSoundEffects().add( mbeSound03.clone().setOffsetTicks( 20 ).setVolumne( 2.0f ) ); + mbd.getSoundEffects().add( mbeSound04.clone().setOffsetTicks( 25 ).setVolumne( 0.75f ) ); mbd.getSoundEffects().add( mbeSound03.clone().setOffsetTicks( 30 ).setVolumne( 1.5f ) ); - mbd.getSoundEffects().add( mbeSound04.clone().setOffsetTicks( 10 ).setVolumne( 2.0f ) ); + mbd.getSoundEffects().add( mbeSound04.clone().setOffsetTicks( 35 ).setVolumne( 0.55f ) ); + mbd.getSoundEffects().add( mbeSound03.clone().setOffsetTicks( 40 ).setVolumne( 1.0f ) ); + mbd.getSoundEffects().add( mbeSound04.clone().setOffsetTicks( 45 ).setVolumne( 0.25f ) ); + mbd.getSoundEffects().add( mbeSound03.clone().setOffsetTicks( 50 ).setVolumne( 0.5f ) ); + mbd.getSoundEffects().add( mbeSound04.clone().setOffsetTicks( 55 ).setVolumne( 0.15f ) ); + mbd.getVisualEffects().add( mbeExplode06.clone() ); + mbd.getVisualEffects().add( mbeExplode06a.clone() ); + mbd.getVisualEffects().add( mbeExplode03.clone() ); mbd.getVisualEffects().add( mbeExplode12.clone() ); mbd.getVisualEffects().add( mbeExplode12.clone().setOffsetTicks( 30 ) ); mbd.getVisualEffects().add( mbeExplode12.clone().setOffsetTicks( 60 ) ); mbd.getVisualEffects().add( mbeExplode07.clone().setOffsetTicks( 60 ) ); mbd.getVisualEffects().add( mbeExplode08.clone().setOffsetTicks( 90 ) ); + mbd.getVisualEffects().add( mbeExplode10.clone() ); + mbd.getVisualEffects().add( mbeExplode06.clone().setOffsetTicks( 20 ) ); + mbd.setAutosell( true ); mbd.setGlowing( true ); mbd.setAutosell( true ); mbd.setCooldownTicks( 60 ); + mbd.setFuseDelayTicks( 3 * 20 ); // 3 seconds getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); } @@ -391,6 +429,13 @@ public void setupDefaultMineBombData() mbd.getVisualEffects().add( mbeExplode01.clone() ); mbd.getVisualEffects().add( mbeExplode02.clone().setOffsetTicks( 30 ) ); + mbd.getVisualEffects().add( mbeExplode03.clone().setOffsetTicks( 10 ) ); + mbd.getVisualEffects().add( mbeExplode04.clone() ); + + mbd.getVisualEffects().add( mbeExplode10.clone() ); + mbd.getVisualEffects().add( mbeExplode06.clone() ); + mbd.getVisualEffects().add( mbeExplode06a.clone() ); + mbd.getVisualEffects().add( mbeExplode11.clone().setOffsetTicks( 05 ) ); mbd.setCooldownTicks( 3 * 20 ); // 3 seconds mbd.setFuseDelayTicks( 2 * 20 ); // 2 seconds @@ -419,7 +464,7 @@ public void setupDefaultMineBombData() mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 30 ) ); mbd.getSoundEffects().add( mbeSound03.clone() ); - mbd.getVisualEffects().add( mbeExplode01.clone() ); + mbd.getVisualEffects().add( mbeExplode04.clone() ); mbd.getVisualEffects().add( mbeExplode02.clone().setOffsetTicks( 30 ) ); mbd.setGlowing( true ); From 861bbb70ed7d95b0ebcc7b5868fd0611312d4881 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 26 Nov 2021 21:01:11 -0500 Subject: [PATCH 153/283] Mine Bombs: Added the use of a armor stand for holding the item, with an animation of swirling it around. The item's armor stand is managed in a task which removes itself when finished. This process is independent from the visual and sound effects. Removed the static functions that were being used (which is much better). --- docs/changelog_v3.3.x.md | 5 + .../mcprison/prison/bombs/MineBombData.java | 11 + .../spigot/block/OnBlockBreakMines.java | 2 +- .../spigot/utils/PrisonBombListener.java | 2 +- .../spigot/utils/PrisonUtilsMineBombs.java | 120 +++++++--- .../utils/PrisonUtilsMineBombsTasks.java | 215 +++++++++++++++--- 6 files changed, 295 insertions(+), 60 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 6d301af3c..721b16657 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,11 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.6 2021-11-26 +* **Mine Bombs: Added the use of a armor stand for holding the item, with an animation of swirling it around.** +The item's armor stand is managed in a task which removes itself when finished. This process is independent from the visual and sound effects. +Removed the static functions that were being used (which is much better). + + * **Mine Bombs: Added more effects to the examples.** Removed some that would not work. These are not perfectly selected and may not work for most versions of spigot. The visual effect do not appear to really do much. diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java index 11b6e2a79..db69ba23e 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java @@ -4,6 +4,7 @@ import java.util.List; import java.util.TreeSet; +import tech.mcprison.prison.internal.block.Block; import tech.mcprison.prison.internal.block.PrisonBlock; public class MineBombData { @@ -119,6 +120,8 @@ public class MineBombData { private TreeSet visualEffects; + private Block placedBombBlock; + public MineBombData() { super(); @@ -351,5 +354,13 @@ public TreeSet getVisualEffects() { public void setVisualEffects( TreeSet visualEffects ) { this.visualEffects = visualEffects; } + + public Block getPlacedBombBlock() { + return placedBombBlock; + } + public void setPlacedBombBlock( Block placedBombBlock ) { + this.placedBombBlock = placedBombBlock; + } + } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakMines.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakMines.java index 16ae492c2..2ea44b4ec 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakMines.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakMines.java @@ -30,7 +30,7 @@ public OnBlockBreakMines() { } - protected Mine findMine( Player player, SpigotBlock sBlock, List altBlocksSource, PrisonMinesBlockBreakEvent pmEvent ) + public Mine findMine( Player player, SpigotBlock sBlock, List altBlocksSource, PrisonMinesBlockBreakEvent pmEvent ) { Long playerUUIDLSB = Long.valueOf( player.getUniqueId().getLeastSignificantBits() ); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java index f07aedb3a..547670a64 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java @@ -74,7 +74,7 @@ public void onInteract( PlayerInteractEvent event ) { // Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent 02 " ); - if ( PrisonUtilsMineBombs.setBombInHand( player, sBlock ) ) { + if ( getPrisonUtilsMineBombs().setBombInHand( player, sBlock ) ) { // The item was a bomb and it was activated. // Cancel the event so the item will not be placed or processed farther. diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java index 282903af8..591b0c79b 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java @@ -9,7 +9,6 @@ import org.bukkit.Bukkit; import org.bukkit.Effect; import org.bukkit.Particle; -import org.bukkit.entity.Item; import org.bukkit.entity.Player; import com.cryptomorin.xseries.XMaterial; @@ -25,8 +24,10 @@ import tech.mcprison.prison.commands.Command; import tech.mcprison.prison.internal.CommandSender; import tech.mcprison.prison.internal.block.Block; +import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.api.ExplosiveBlockBreakEvent; +import tech.mcprison.prison.spigot.block.OnBlockBreakMines; import tech.mcprison.prison.spigot.block.SpigotBlock; import tech.mcprison.prison.spigot.block.SpigotItemStack; import tech.mcprison.prison.spigot.compat.SpigotCompatibility; @@ -639,10 +640,14 @@ public static SpigotItemStack getItemStackBomb( MineBombData bomb ) { * one. *

* + *

It's important that this returns a "true" if this is a bomb, even though the + * bomb cannot be activated. + *

+ * * @param player * @return */ - public static boolean setBombInHand( Player player, SpigotBlock sBlock ) { + public boolean setBombInHand( Player player, SpigotBlock sBlock ) { boolean isABomb = false; @@ -657,7 +662,6 @@ public static boolean setBombInHand( Player player, SpigotBlock sBlock ) { if ( prisonBombId.equalsIgnoreCase( Text.stripColor( MINE_BOMBS_LORE_1 )) ) { - // String bombName = lore1.trim(); MineBombs mBombs = MineBombs.getInstance(); @@ -668,16 +672,24 @@ public static boolean setBombInHand( Player player, SpigotBlock sBlock ) { AutoFeatures.ProcessPrisons_ExplosiveBlockBreakEventsPriority ); if ( bomb != null && "DISABLED".equalsIgnoreCase( prisonExplosiveHandlerPriority ) ) { - isABomb = true; Output.get().logWarn( "A Prison Mine Bomb was attempted to be used, but the " + "handling of its explosion is DISABLED. Edit the 'autoFeaturesConfig.yml' " + "file and set 'ProcessPrisons_ExplosiveBlockBreakEventsPriority: NORMAL'." ); + + // Must return a true from here on out so the original event is canceled. + // Returning a true does not mean the bomb was activated. + isABomb = true; + + return isABomb; } else if ( bomb != null ) { - isABomb = true; + // Must return a true from here on out so the original event is canceled. + // Returning a true does not mean the bomb was activated. + isABomb = true; + // XMaterial.GUNPOWDER; // XMaterial.BLAZE_POWDER; // XMaterial.WOODEN_PICKAXE; @@ -704,7 +716,7 @@ else if ( bomb != null ) { // Set cooldown: - PrisonUtilsMineBombs.addPlayerCooldown( playerUUID, bomb.getCooldownTicks() ); + addPlayerCooldown( playerUUID, bomb.getCooldownTicks() ); SpigotItemStack bombs = PrisonUtilsMineBombs.getItemStackBomb( bomb ); @@ -712,6 +724,7 @@ else if ( bomb != null ) { SpigotBlock bombBlock = sBlock != null ? sBlock : (SpigotBlock) player.getLocation().getBlock(); + // // If the clicked on block is empty, then the player probably clicked on air. // // Check the next lower block (y - 1) until a valid block is found, or until y < 1 // while ( sBlock.isEmpty() && sBlock.getLocation().getBlockY() > 0 ) { @@ -730,16 +743,6 @@ else if ( bomb != null ) { //// } //// } // } - - // Setting activated to true indicates the bomb is live and it has - // been removed from the player's inventory: - bomb.setActivated( true ); - - // Remove from inventory: - itemInHand.setAmount( itemInHand.getAmount() - 1 ); - - // Not sure if the following is needed? - SpigotCompatibility.getInstance().setItemInMainHand( player, itemInHand.getBukkitStack() ); @@ -760,35 +763,65 @@ else if ( bomb != null ) { // " " + bombBlock.getLocation().getBlockY() + " count= " + count ); } + bomb.setPlacedBombBlock( bombBlock ); + // Output.get().logInfo( // "#### PrisonUtilsMineBombs: bomb loc: " + bombBlock.getLocation().toWorldCoordinates() ); //int throwSpeed = 2; + + + + // check if in a mine: + OnBlockBreakMines obbm = new OnBlockBreakMines(); + Mine mine = obbm.findMine( player, bombBlock, null, null ); + + if ( mine == null ) { + // Cannot set the bomb outside of a mine, so cancel: + return isABomb; + } + + // Setting activated to true indicates the bomb is live and it has + // been removed from the player's inventory: + bomb.setActivated( true ); + + // Remove from inventory: + itemInHand.setAmount( itemInHand.getAmount() - 1 ); + + // Not sure if the following is needed? + SpigotCompatibility.getInstance().setItemInMainHand( player, itemInHand.getBukkitStack() ); + + PlacedMineBombItemTask submitPlacedMineBombItem = + submitPlacedMineBombItemTask( bomb, bombBlock, bombs ); +// placeMineBombItem( bomb, bombBlock, bombs ); + // This places the item so it will float: - final Item dropped = player.getWorld().dropItem( - bombBlock.getWrapper().getLocation(), bombs.getBukkitStack() ); +// final Item dropped = player.getWorld().dropItem( +// bombBlock.getWrapper().getLocation(), bombs.getBukkitStack() ); - dropped.setPickupDelay( Integer.MAX_VALUE ); - dropped.setCustomName( bomb.getName() ); +// dropped.setPickupDelay( Integer.MAX_VALUE ); +// dropped.setCustomName( bomb.getName() ); //dropped.setVelocity(player.getLocation().getDirection().multiply( throwSpeed ).normalize() ); // int delayInTicks = 5 * 20; // 5 secs // If running MC 1.9.0 or higher, then can use the glowing feature. Ignore for 1.8.x. - if ( new BluesSpigetSemVerComparator().compareMCVersionTo( "1.9.0" ) >= 0 ) { - - dropped.setGlowing( bomb.isGlowing() ); - - - // setGravity is invalid for spigot 1.8.8: - dropped.setGravity( bomb.isGravity() ); - } +// if ( new BluesSpigetSemVerComparator().compareMCVersionTo( "1.9.0" ) >= 0 ) { +// +// dropped.setGlowing( bomb.isGlowing() ); +// +// +// // setGravity is invalid for spigot 1.8.8: +// dropped.setGravity( bomb.isGravity() ); +// } + // Submit the bomb's task to go off: - PrisonUtilsMineBombs.setoffBombDelayed( sPlayer, bomb, dropped, bombBlock ); + + setoffBombDelayed( sPlayer, bomb, bombBlock ); @@ -817,6 +850,35 @@ else if ( bomb != null ) { return isABomb; } + + +// public void placeMineBombItem( MineBombData bomb, SpigotBlock sBlock, SpigotItemStack item ) { +// +// +// Location location = sBlock.getLocation(); +// +// SpigotWorld sWorld = (SpigotWorld) location.getWorld(); +// +// +// EulerAngle arm = new EulerAngle(1, 0, 0); +// +// ArmorStand as = sWorld.getWrapper().spawn( sWorld.getBukkitLocation( location ), ArmorStand.class); +// as.setCustomName( bomb.getName() ); +// as.setCustomNameVisible(false); +// as.setVisible(false); +// as.setRemoveWhenFarAway(false); +// as.setItemInHand( sWorld.getBukkitItemStack( item ) ); +// as.setRightArmPose(arm); +// as.setRemoveWhenFarAway(false); +// +// if ( new BluesSpigetSemVerComparator().compareMCVersionTo( "1.9.0" ) >= 0 ) { +// +// as.setGlowing( bomb.isGlowing() ); +// +// // setGravity is invalid for spigot 1.8.8: +// as.setGravity( bomb.isGravity() ); +// } +// } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombsTasks.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombsTasks.java index a004625bd..976ce8191 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombsTasks.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombsTasks.java @@ -10,8 +10,10 @@ import org.bukkit.Effect; import org.bukkit.Particle; import org.bukkit.enchantments.Enchantment; -import org.bukkit.entity.Item; +import org.bukkit.entity.ArmorStand; import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.scheduler.BukkitTask; +import org.bukkit.util.EulerAngle; import com.cryptomorin.xseries.XMaterial; import com.cryptomorin.xseries.XSound; @@ -19,8 +21,8 @@ import tech.mcprison.prison.bombs.MineBombData; import tech.mcprison.prison.bombs.MineBombEffectsData; -import tech.mcprison.prison.bombs.MineBombs; import tech.mcprison.prison.bombs.MineBombEffectsData.EffectState; +import tech.mcprison.prison.bombs.MineBombs; import tech.mcprison.prison.bombs.MineBombs.ExplosionOrientation; import tech.mcprison.prison.bombs.MineBombs.ExplosionShape; import tech.mcprison.prison.output.Output; @@ -53,7 +55,7 @@ protected Boolean initialize() } - protected static void setFortune( SpigotItemStack itemInHand, int fortuneLevel ) + protected void setFortune( SpigotItemStack itemInHand, int fortuneLevel ) { if ( itemInHand != null && itemInHand.getBukkitStack() != null && itemInHand.getBukkitStack().hasItemMeta() ) @@ -85,7 +87,7 @@ protected static void setFortune( SpigotItemStack itemInHand, int fortuneLevel ) * @param ticks * @return */ - public static boolean addPlayerCooldown( String playerUUID, int ticks ) + public boolean addPlayerCooldown( String playerUUID, int ticks ) { boolean results = false; @@ -135,10 +137,8 @@ public static int checkPlayerCooldown( String playerUUID ) } - public static void submitBombEffects( MineBombData bomb, EffectState effectState, - Location location, Item droppedBomb ) { + public void submitBombEffects( MineBombData bomb, EffectState effectState, Location location ) { - long lastTick = -1; // If running MC 1.9.0 or higher, then can use the glowing feature. Ignore for 1.8.x. boolean is18 = new BluesSpigetSemVerComparator().compareMCVersionTo( "1.9.0" ) < 0 ; @@ -174,9 +174,6 @@ public void run() { }.runTaskLater( SpigotPrison.getInstance(), effect.getOffsetTicks() ); } - if ( effect.getEffectState() == EffectState.finished && effect.getOffsetTicks() > lastTick ) { - lastTick = effect.getOffsetTicks(); - } } for ( MineBombEffectsData effect : bomb.getVisualEffects() ) @@ -221,25 +218,11 @@ public void run() { } - if ( effect.getEffectState() == EffectState.finished && effect.getOffsetTicks() > lastTick ) { - lastTick = effect.getOffsetTicks(); - } - } - // After the last sound and visual is played, then remove the dropped bomb: - if ( effectState == EffectState.finished && lastTick >= 0 ) { - new BukkitRunnable() { - - @Override - public void run() { - droppedBomb.remove(); - } - }.runTaskLater( SpigotPrison.getInstance(), lastTick + 1 ); - } } - public static boolean setoffBombDelayed( SpigotPlayer sPlayer, MineBombData bomb, Item droppedBomb, + public boolean setoffBombDelayed( SpigotPlayer sPlayer, MineBombData bomb, // Item droppedBomb, SpigotBlock targetBlock ) { boolean results = false; @@ -247,7 +230,7 @@ public static boolean setoffBombDelayed( SpigotPlayer sPlayer, MineBombData bomb sPlayer.getLocation() : targetBlock.getLocation() ); - submitBombEffects( bomb, EffectState.placed, location, droppedBomb ); + submitBombEffects( bomb, EffectState.placed, location ); new BukkitRunnable() { @@ -257,7 +240,7 @@ public void run() { // Remove the item that the player threw: // droppedBomb.remove(); - submitBombEffects( bomb, EffectState.explode, location, droppedBomb ); + submitBombEffects( bomb, EffectState.explode, location ); MineBombs mBombs = MineBombs.getInstance(); @@ -307,7 +290,7 @@ public void run() { if ( explodeEvent.isCancelled() ) { // Run all of the EffectState.finished effects: - submitBombEffects( bomb, EffectState.finished, location, droppedBomb ); + submitBombEffects( bomb, EffectState.finished, location ); if ( Output.get().isDebug() ) { Output.get().logDebug( "Mine Bomb's ExplosiveBlockBreakEvent has been canceled. " + @@ -317,7 +300,7 @@ public void run() { else { // If it wasn't canceled, then it may not have been handled - droppedBomb.remove(); + //droppedBomb.remove(); if ( Output.get().isDebug() ) { Output.get().logDebug( "Mine Bomb's ExplosiveBlockBreakEvent has NOT been canceled." ); @@ -440,5 +423,179 @@ private List calculatBlocksForExplosion( MineBombData bo return results; } + + public PlacedMineBombItemTask submitPlacedMineBombItemTask( MineBombData bomb, SpigotBlock sBlock, SpigotItemStack item ) { + + PlacedMineBombItemTask placedTask = new PlacedMineBombItemTask( bomb, sBlock, item ); + + BukkitTask task = placedTask.runTaskTimer( + SpigotPrison.getInstance(), 1, 1 ); + + placedTask.setBukkitTask( task ); + + return placedTask; + } + + public class PlacedMineBombItemTask + extends BukkitRunnable + { + + private MineBombData bomb; + private SpigotBlock sBlock; + private SpigotItemStack item; + + private double eulerAngleX = 1.0; + private double eulerAngleY = 0; + private double eulerAngleZ = 0; + + private double twoPI; + + private ArmorStand as; + + long ageTicks = 0L; + long terminateOnTicks = 0L; + + private BukkitTask bukkitTask; + + public PlacedMineBombItemTask( MineBombData bomb, + SpigotBlock sBombBlock, SpigotItemStack item ) { + super(); + + this.bomb = bomb; + this.sBlock = sBombBlock; + this.item = item; + + this.twoPI = Math.PI * 2; + + this.ageTicks = 0; + this.terminateOnTicks = setTaskLifeSpan(); + + initialize(); + } + + + /** + *

This will calculate how long the placed item needs to + * exist before removal, and this task will remove itself. + * While this item is placed, this task will run every 2 + * ticks and will spin the item in 3d space. + *

+ * + *

Removal is based upon the fuseDelayTicks which will take it to + * the explosion, then scanning the final effects to find how long + * the last one will be submitted for. Then add 15 ticks. + *

+ * + *

At this time, not 100% sure if this item or armor stand + * will be used to "place" the effects. Probably not. If it's not + * needed, then this can be removed when the explosions start. + *

+ * + * @return + */ + private long setTaskLifeSpan() + { + long ticks = bomb.getFuseDelayTicks(); + + long maxValue = 0; + for ( MineBombEffectsData effect : bomb.getSoundEffects() ) + { + if ( effect.getEffectState() == EffectState.finished && + effect.getOffsetTicks() > maxValue ) { + maxValue = effect.getOffsetTicks(); + } + } + for ( MineBombEffectsData effect : bomb.getVisualEffects() ) + { + if ( effect.getEffectState() == EffectState.finished && + effect.getOffsetTicks() > maxValue ) { + maxValue = effect.getOffsetTicks(); + } + } + + return ticks + maxValue + 15; + } + + + private void initialize() { + + Location location = sBlock.getLocation(); + location.setY( location.getY() + 2.5 ); + + SpigotWorld sWorld = (SpigotWorld) location.getWorld(); + + + EulerAngle arm = new EulerAngle( eulerAngleX, eulerAngleY, eulerAngleZ ); + + as = sWorld.getWrapper().spawn( + sWorld.getBukkitLocation( location ), + ArmorStand.class); + + as.setCustomName( bomb.getName() ); + as.setCustomNameVisible(true); + as.setVisible(false); + as.setRemoveWhenFarAway(false); + as.setItemInHand( sWorld.getBukkitItemStack( item ) ); + as.setRightArmPose(arm); + as.setRemoveWhenFarAway(false); + + + if ( new BluesSpigetSemVerComparator().compareMCVersionTo( "1.9.0" ) >= 0 ) { + + as.setGlowing( bomb.isGlowing() ); + + // setGravity is invalid for spigot 1.8.8: + as.setGravity( bomb.isGravity() ); + } + } + + @Override + public void run() + { + // Track the time that this has lived: + ageTicks += 1; + + double speed = 0.25; + + eulerAngleX += speed; + eulerAngleY += speed / 3; + eulerAngleZ += speed / 9; + + + EulerAngle arm = new EulerAngle( eulerAngleX, eulerAngleY, eulerAngleZ ); + + as.setRightArmPose(arm); + + + if ( eulerAngleX > twoPI ) { + eulerAngleX -= twoPI; + } + if ( eulerAngleY > twoPI ) { + eulerAngleY -= twoPI; + } + if ( eulerAngleZ > twoPI ) { + eulerAngleZ -= twoPI; + } + + + if ( ageTicks >= terminateOnTicks ) { + + as.remove(); + + this.cancel(); + } + + } + + public BukkitTask getBukkitTask() { + return bukkitTask; + } + public void setBukkitTask( BukkitTask bukkitTask ) { + this.bukkitTask = bukkitTask; + } + + } + + } From 9bc44ed5261190a1f06924e1dd3ce627e9974c7e Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 26 Nov 2021 21:22:28 -0500 Subject: [PATCH 154/283] Release v3.2.11-alpha.7 --- docs/changelog_v3.3.x.md | 8 +++++++- gradle.properties | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 721b16657..0c72ab0f9 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,13 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.6 2021-11-26 +# 3.2.11-alpha.7 2021-11-26 + + + + +* **3.2.11-alpha.7 2021-11-26** +Released alpha.7. Major advancements to mine bombs. * **Mine Bombs: Added the use of a armor stand for holding the item, with an animation of swirling it around.** diff --git a/gradle.properties b/gradle.properties index 8bb24c096..eb99efda2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ ## # This is actually the "correct" place to define the version for the project. ## # Used within build.gradle with ${project.version}. ## # Can be overridden on the command line: gradle -Pversion=3.2.1-alpha.3 -version=3.2.11-alpha.6 +version=3.2.11-alpha.7 #version=3.2.8.2 #version=3.3.0-alpha.6 From 4fd4f04d0200fb33016764cd983234afa8209205 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sat, 27 Nov 2021 20:47:45 -0500 Subject: [PATCH 155/283] Prison Tokens: Prison now is able to auto generate player tokens based upon blocks mined. It's enabled through AutoFeatures config file's setting 'tokensEnabled' and is able to set the blocks per token earnings rate with 'tokensBlocksPerToken'. More features will be added soon, such admin functions and top-n token holders.... etc... --- docs/changelog_v3.3.x.md | 6 +- .../autofeatures/AutoFeaturesFileConfig.java | 6 + .../prison/cache/PlayerCachePlayerData.java | 207 +++++++++++++++++- .../java/tech/mcprison/prison/util/Text.java | 13 +- .../prison/ranks/commands/RanksCommands.java | 24 +- .../autofeatures/AutoManagerFeatures.java | 3 +- 6 files changed, 248 insertions(+), 11 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 0c72ab0f9..f33f8dcc8 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,9 +13,13 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.7 2021-11-26 +# 3.2.11-alpha.7 2021-11-27 +* **Prison Tokens: Prison now is able to auto generate player tokens based upon blocks mined.** +It's enabled through AutoFeatures config file's setting 'tokensEnabled' and is able to set the blocks per token earnings rate with 'tokensBlocksPerToken'. +More features will be added soon, such admin functions and top-n token holders.... etc... + * **3.2.11-alpha.7 2021-11-26** diff --git a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java index b59ac68be..79a2000df 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java +++ b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java @@ -96,6 +96,12 @@ public enum AutoFeatures { // isAutoSellPerBlockBreakInlinedEnabled(general, false), + tokens(options), + + tokensEnabled( tokens, false ), + tokensBlocksPerToken( tokens, 100 ), + + permissions(options), permissionAutoPickup(permissions, "prison.automanager.pickup"), diff --git a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java index 61e054ed6..91c28e4b4 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java @@ -7,6 +7,8 @@ import java.util.List; import java.util.TreeMap; +import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; +import tech.mcprison.prison.autofeatures.AutoFeaturesWrapper; import tech.mcprison.prison.autofeatures.PlayerMessaging; import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.internal.block.PrisonBlock; @@ -70,12 +72,23 @@ public class PlayerCachePlayerData { private TreeMap timeByMine; private String lastMine = null; - private TreeMap earningsByMine; + private TreeMap earningsByMine; private transient TreeMap earningsPerMinute; + private long tokens; + private long tokensTotal; + private long tokensLastBlocksTotals; + + private TreeMap tokensByMine; + private transient TreeMap tokensPerMinute; + + + + + // This is the time when the "session" was started: private transient SessionType sessionType; @@ -114,6 +127,11 @@ public PlayerCachePlayerData() { this.earningsPerMinute = new TreeMap<>(); + + this.tokensByMine = new TreeMap<>(); + this.tokensPerMinute = new TreeMap<>(); + + this.sessionType = SessionType.active; // this.sessionTimingStart = System.currentTimeMillis(); @@ -308,6 +326,14 @@ else if ( duration > SESSION_TIMEOUT_MINING_MS ) { + /** + *

Also generates tokens based upon blocks mined. + *

+ * + * @param mine + * @param blockName + * @param quantity + */ public void addBlock( String mine, String blockName, int quantity ) { if ( quantity > 0 && blockName != null && @@ -326,6 +352,8 @@ public void addBlock( String mine, String blockName, int quantity ) checkTimersMining( SessionType.mining, mine ); dirty = true; } + + addTokensByBlocks( mine, quantity ); } private void addBlockByType( String blockName, int quantity ) { @@ -359,6 +387,16 @@ private void addEarningsByMine( String mine, double amount ) { getEarningsByMine().put( mine, amt ); } + private void addTokensByMine( String mine, long tokens ) { + long toks = 0; + + if ( getTokensByMine().containsKey( mine ) ) { + toks = getTokensByMine().get( mine ); + } + + getTokensByMine().put( mine, (toks + tokens) ); + } + private void addTimeToMine( String mine, long miningDuration ) { if ( mine != null && !mine.trim().isEmpty() ) { @@ -384,15 +422,17 @@ public void addEarnings( double earnings, String mineName ) { SimpleDateFormat dateFmt = new SimpleDateFormat("yyyy-MM-dd_hh:mm"); String key = dateFmt.format( new Date() ); - if ( earningsPerMinute.containsKey( key ) ) { - earnings += earningsPerMinute.get( key ) + earnings; + + double earningsPM = earnings; + if ( getEarningsPerMinute().containsKey( key ) ) { + earningsPM += getEarningsPerMinute().get( key ); } + getEarningsPerMinute().put( key, earningsPM ); - earningsPerMinute.put( key, earnings ); - if ( earningsPerMinute.size() > 5 ) { - earningsPerMinute.remove( - earningsPerMinute.firstEntry().getKey() ); + if ( getEarningsPerMinute().size() > 5 ) { + getEarningsPerMinute().remove( + getEarningsPerMinute().firstEntry().getKey() ); } if ( mineName != null && sessionType != SessionType.mining ) { @@ -432,6 +472,118 @@ public double getAverageEarningsPerMinute() { return ( size == 0 ? 0 : ( results / size )); } + private void addTokensByBlocks( String mineName, int blocks ) { + + if ( AutoFeaturesWrapper.getInstance().isBoolean( AutoFeatures.tokensEnabled ) ) { + int blocksPerToken = AutoFeaturesWrapper.getInstance().getInteger( AutoFeatures.tokensBlocksPerToken ); + + if ( blocksPerToken > 0 ) { + + // If blocksTotal > 10k and tokensLastBlocksTotals == 0, then this means + // the player was mining before tokens was enabled, so set the + // tokensLastBlocksTotals to the blocks total, minus current block count. + if ( tokensLastBlocksTotals == 0 && blocksTotal > 10000 ) { + tokensLastBlocksTotals = blocksTotal - blocks; + } + + // tokensLastBlocksTotals should never be greater than blocksTotal: + if ( tokensLastBlocksTotals > blocksTotal ) { + tokensLastBlocksTotals = blocksTotal; + } + + double delta = blocksTotal - tokensLastBlocksTotals; + + double tokens = delta / (double) blocksPerToken; + + if ( tokens >= 1.0 ) { + long tokensLong = (long) Math.floor( tokens ); + + long blocksForTokens = tokensLong * blocksPerToken; + tokensLastBlocksTotals += blocksForTokens; + + addTokens( tokensLong, mineName ); + + } + } + } + } + + /** + *

This stores the tokens from the player so they can + * be averaged to find their tokens per minute. Tokens are + * automatically generated based upon blocks mined so normally + * you wouldn't have to call this function. + *

+ * + *

If you just want to add tokens, you can pass a null for the + * mine name. + *

+ * + *

Note: Unlike adding blocks from mines, adding tokens with a mine name + * does not need to be concerned about session types. If a mine name is + * provided, then that's the mine it should be attributed to. + *

+ * + * @param newTokens + */ + public void addTokens( long newTokens, String mineName ) { + + this.tokens += newTokens; + this.tokensTotal += newTokens; + + SimpleDateFormat dateFmt = new SimpleDateFormat("yyyy-MM-dd_hh:mm"); + String key = dateFmt.format( new Date() ); + + + long tokensPM = newTokens; + if ( getTokensPerMinute().containsKey( key ) ) { + tokensPM += getTokensPerMinute().get( key ); + } + getTokensPerMinute().put( key, tokensPM ); + + + if ( getTokensPerMinute().size() > 5 ) { + getTokensPerMinute().remove( + getTokensPerMinute().firstEntry().getKey() ); + } + + // If we are getting tokens from mining, then we have the mine name. + // No need to mess with sessions. +// if ( mineName != null && sessionType != SessionType.mining ) { +// sessionType = SessionType.mining; +// } +// if ( mineName == null && getLastMine() != null ) { +// mineName = getLastMine(); +// } + + // If earnings are within the session timeout for mining, then add the + // earnings to the tokensByMine: + if ( mineName != null ) { + + addTokensByMine( mineName, newTokens ); + } + + dirty = true; + } + + /** + * This returns the average tokens earned per minute for the + * last 5 minutes. + * + * @return + */ + public double getAverageTokensPerMinute() { + double results = 0; + + int size = 0; + for ( double value : tokensPerMinute.values() ) { + results += value; + size++; + } + + return ( size == 0 ? 0 : ( results / size )); + } + @Override public String toString() { StringBuilder sb = new StringBuilder(); @@ -457,6 +609,12 @@ public String toString() { .append( " blocks: " ) .append( blocksByType ) + .append( " avg tokens/min: " ) + .append( getAverageTokensPerMinute() ) + .append( " totalTokens: " ) + .append( getTokensTotal() ) + .append( " tokens: " ) + .append( getTokens() ) ; return sb.toString(); @@ -563,6 +721,41 @@ public void setTimeByMine( TreeMap timeByMine ) { this.timeByMine = timeByMine; } + public long getTokens() { + return tokens; + } + public void setTokens( long tokens ) { + this.tokens = tokens; + } + + public long getTokensTotal() { + return tokensTotal; + } + public void setTokensTotal( long tokensTotal ) { + this.tokensTotal = tokensTotal; + } + + public long getTokensLastBlocksTotals() { + return tokensLastBlocksTotals; + } + public void setTokensLastBlocksTotals( long tokensLastBlocksTotals ) { + this.tokensLastBlocksTotals = tokensLastBlocksTotals; + } + + public TreeMap getTokensByMine() { + return tokensByMine; + } + public void setTokensByMine( TreeMap tokensByMine ) { + this.tokensByMine = tokensByMine; + } + + public TreeMap getTokensPerMinute() { + return tokensPerMinute; + } + public void setTokensPerMinute( TreeMap tokensPerMinute ) { + this.tokensPerMinute = tokensPerMinute; + } + public String getLastMine() { return lastMine; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/util/Text.java b/prison-core/src/main/java/tech/mcprison/prison/util/Text.java index 880a44ed9..a96f4a0ab 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/util/Text.java +++ b/prison-core/src/main/java/tech/mcprison/prison/util/Text.java @@ -577,6 +577,11 @@ public static String formatTimeDaysHhMmSs( long timeMs ) { public static List formatTreeMapStats( TreeMap statMap, int columns ) { + return formatTreeMapStats( statMap, columns, false ); + } + + public static List formatTreeMapStats( TreeMap statMap, + int columns, boolean timeFormat ) { List msgs = new ArrayList<>(); @@ -603,10 +608,16 @@ else if ( valueObj instanceof Integer ) { value = PlaceholdersUtil.formattedKmbtSISize( intVal, ( intVal < 1000 ? iFmt : dFmt ), " &9" ); } - else if ( valueObj instanceof Long ) { + else if ( valueObj instanceof Long && timeFormat ) { value = Text.formatTimeDaysHhMmSs( (Long) valueObj ); } + else if ( valueObj instanceof Long ) { + + long longVal = (Long) valueObj; + value = PlaceholdersUtil.formattedKmbtSISize( longVal, + ( longVal < 1000 ? iFmt : dFmt ), " &9" ); + } String msg = String.format( "&3%s&8: &b%s", earningKey, value ).trim(); diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java index 3b0b81b6f..fddf3ad31 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java @@ -13,6 +13,7 @@ import tech.mcprison.prison.PrisonAPI; import tech.mcprison.prison.PrisonCommand; import tech.mcprison.prison.autofeatures.AutoFeaturesWrapper; +import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; import tech.mcprison.prison.cache.PlayerCache; import tech.mcprison.prison.cache.PlayerCachePlayerData; import tech.mcprison.prison.chat.FancyMessage; @@ -1550,6 +1551,27 @@ public void rankPlayer(CommandSender sender, msgs.addAll( Text.formatTreeMapStats(cPlayer.getEarningsByMine(), 5 ) ); + + if ( cPlayer.getTokens() > 0 || cPlayer.getTokensTotal() > 0 || + cPlayer.getTokensByMine().size() > 0 ) { + + msgs.add( String.format( + " Tokens By Mine: &2Tokens: &3%s &2Avg Tokens per min: &3%s " + + "", + dFmt.format( cPlayer.getTokens() ), + dFmt.format( cPlayer.getAverageTokensPerMinute() )) ); + + msgs.add( String.format( + " &2Tokens Total: &3%s &2Tokens per Block: &3%d " + + "", + dFmt.format( cPlayer.getTokensTotal() ), + AutoFeaturesWrapper.getInstance().getInteger( AutoFeatures.tokensBlocksPerToken )) ); + + msgs.addAll( + Text.formatTreeMapStats(cPlayer.getTokensByMine(), 5 ) ); + } + + msgs.add( String.format( " &7Timings By Mine&8: &2Online&8: &3%s &2Mining&8: &3%s", Text.formatTimeDaysHhMmSs( cPlayer.getOnlineTimeTotal() ), @@ -1557,7 +1579,7 @@ public void rankPlayer(CommandSender sender, ); msgs.addAll( - Text.formatTreeMapStats(cPlayer.getTimeByMine(), 5 ) ); + Text.formatTreeMapStats(cPlayer.getTimeByMine(), 5, true ) ); // Print all earnings for all mines: diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java index ff94ebf02..60b6ea04f 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java @@ -507,7 +507,7 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, autosellTotal += amount; PlayerCache.getInstance().addPlayerEarnings( pmEvent.getSpigotPlayer(), - amount, mineName ); + amount, mineName ); if ( amount != 0 ) { debugInfo.append( "(sold: " + itemStack.getName() + " qty: " + itemStack.getAmount() + " value: " + amount + ") "); @@ -525,6 +525,7 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, } + // Add blocks to player's inventory IF autosell is disabled or the item had a value of ZERO // which indicates it cannot be sold. If it could not be sold, then amount would be non-zero since // sold will zero out the number of drops for that item stack. From 8efda10b54b3944acbe3dad8f8432a7bba72e936 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sat, 27 Nov 2021 23:35:27 -0500 Subject: [PATCH 156/283] Some adjustments to the overflow of the drops and other inventory controls. On normal drops, disconnected autosell except if it is forced through the pmEvent. Fix inventory full sounds. For 1.13 and up it had the wrong sound file. Using something less harsh than anvil and turned down the volume which was horribly excessive with the volume set to 10, when normal is 1. --- docs/changelog_v3.3.x.md | 6 ++ .../autofeatures/AutoFeaturesFileConfig.java | 20 +++++-- .../autofeatures/AutoManagerFeatures.java | 56 +++++++++++++++---- 3 files changed, 66 insertions(+), 16 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index f33f8dcc8..bbb7e69cf 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,12 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.7 2021-11-27 + +* **Some adjustments to the overflow of the drops and other inventory controls.** +On normal drops, disconnected autosell except if it is forced through the pmEvent. +Fix inventory full sounds. For 1.13 and up it had the wrong sound file. Using something less harsh than anvil and turned down the volume which was horribly excessive with the volume set to 10, when normal is 1. + + * **Prison Tokens: Prison now is able to auto generate player tokens based upon blocks mined.** It's enabled through AutoFeatures config file's setting 'tokensEnabled' and is able to set the blocks per token earnings rate with 'tokensBlocksPerToken'. More features will be added soon, such admin functions and top-n token holders.... etc... diff --git a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java index 79a2000df..37f7b291c 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java +++ b/prison-core/src/main/java/tech/mcprison/prison/autofeatures/AutoFeaturesFileConfig.java @@ -77,6 +77,8 @@ public enum AutoFeatures { "Use the following event priorities with the blockBreakEvents: " + "DISABLED, LOWEST, LOW, NORMAL, HIGH, HIGHEST, MONITOR" ), + + general(options), @@ -88,14 +90,24 @@ public enum AutoFeatures { isCalculateXPEnabled(general, true), givePlayerXPAsOrbDrops(general, false), - dropItemsIfInventoryIsFull(general, true), - playSoundIfInventoryIsFull(general, true), - hologramIfInventoryIsFull(general, false), + + + inventory(options), + - isAutoSellPerBlockBreakEnabled(general, false), + isAutoSellPerBlockBreakEnabled(inventory, false), // isAutoSellPerBlockBreakInlinedEnabled(general, false), + isAutoSellIfInventoryIsFull(inventory, true), + dropItemsIfInventoryIsFull(inventory, true), + playSoundIfInventoryIsFull(inventory, true), + + actionBarMessageIfInventoryIsFull(inventory, true), +// hologramIfInventoryIsFull(general, false), + + + tokens(options), tokensEnabled( tokens, false ), diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java index 60b6ea04f..bc948e029 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java @@ -37,6 +37,7 @@ import tech.mcprison.prison.spigot.compat.SpigotCompatibility; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.sellall.SellAllUtil; +import tech.mcprison.prison.spigot.spiget.BluesSpigetSemVerComparator; import tech.mcprison.prison.util.BlockType; import tech.mcprison.prison.util.Text; @@ -672,20 +673,24 @@ public int calculateNormalDrop( PrisonMinesBlockBreakEvent pmEvent, StringBuilde count += itemStack.getAmount(); - if (isBoolean(AutoFeatures.isAutoSellPerBlockBreakEnabled) || - pmEvent.isForceAutoSell() ) { + // Since this is not auto pickup, then only autosell if set in the pmEvent: + if ( pmEvent.isForceAutoSell() ) { Player player = pmEvent.getPlayer(); double amount = SellAllUtil.get().sellAllSell( player, itemStack, false, false, true ); autosellTotal += amount; - debugInfo.append( "(sold: " + itemStack.getName() + " qty: " + itemStack.getAmount() + " value: " + amount + ") "); + if ( amount != 0 ) { + debugInfo.append( "(sold: " + itemStack.getName() + " qty: " + itemStack.getAmount() + " value: " + amount + ") "); + + // Set to zero quantity since they have all been sold. + itemStack.setAmount( 0 ); + } - // Set to zero quantity since they have all been sold. - itemStack.setAmount( 0 ); } - else { + + if ( itemStack.getAmount() != 0 ) { if ( Output.get().isDebug() ) { @@ -990,16 +995,43 @@ private void notifyPlayerWithSound( Player player, AutoFeatures messageId ) { // This hard coding the Sound enum causes failures in spigot 1.8.8 since it does not exist: Sound sound; - try { - sound = Sound.valueOf("ANVIL_USE"); // pre 1.9 sound - } catch(IllegalArgumentException e) { - sound = Sound.valueOf("BLOCK_ANVIL_PLACE"); // post 1.9 sound + + + if ( new BluesSpigetSemVerComparator().compareMCVersionTo( "1.9.0" ) < 0 ) { + + // 1.8.x + sound = Sound.valueOf("NOTE_PLING"); + } + else if ( new BluesSpigetSemVerComparator().compareMCVersionTo( "1.13.0" ) < 0 ) { + + // 1.9.x through 1.12.x + sound = Sound.valueOf("BLOCK_NOTE_PLING"); } - player.playSound(player.getLocation(), sound, 10F, 1F); + else { + // 1.13.x and up: + + sound = Sound.valueOf("BLOCK_NOTE_BLOCK_PLING"); + } + +// try { +// sound = Sound.valueOf("ANVIL_USE"); // pre 1.9 sound +// } catch(IllegalArgumentException e) { +// sound = Sound.valueOf("BLOCK_NOTE_PLING "); // post 1.9 sound +// } + + player.playSound(player.getLocation(), sound, 4F, 1F); } - (new SpigotPlayer( player )).setActionBar( message ); + + if ( isBoolean( AutoFeatures.actionBarMessageIfInventoryIsFull ) ) { + + (new SpigotPlayer( player )).setActionBar( message ); + } + else { + + player.sendMessage( message ); + } // holographic display for showing full inventory does not work well. // if ( isBoolean( AutoFeatures.hologramIfInventoryIsFull ) ) { From d58752d05b070250162d34e7873af16f8cbad4d4 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 28 Nov 2021 00:03:52 -0500 Subject: [PATCH 157/283] Removed from the GUI the hologram on inventory full, and replaced it with actionBar. --- docs/changelog_v3.3.x.md | 2 ++ .../mcprison/prison/spigot/gui/ListenersPrisonManager.java | 4 ++-- .../spigot/gui/autofeatures/SpigotAutoFeaturesGUI.java | 6 +++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index bbb7e69cf..0ab7f5089 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,8 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.7 2021-11-27 +* **Removed from the GUI the hologram on inventory full, and replaced it with actionBar.** + * **Some adjustments to the overflow of the drops and other inventory controls.** On normal drops, disconnected autosell except if it is forced through the pmEvent. diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java index a5d8cf9ed..320662a3c 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java @@ -2503,8 +2503,8 @@ private void autoFeaturesGUI(InventoryClickEvent e, Player p, String[] parts) { saveConfigAutoFeatures(e, p); } - if (buttonName.equalsIgnoreCase("Full-Inventory-Hologram")){ - afConfig.setFeature(AutoFeatures.hologramIfInventoryIsFull, !enabled); + if (buttonName.equalsIgnoreCase("Full-Inventory-ActionBar")){ + afConfig.setFeature(AutoFeatures.actionBarMessageIfInventoryIsFull, !enabled); saveConfigAutoFeatures(e,p); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoFeaturesGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoFeaturesGUI.java index b7998b3e3..824c7ce85 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoFeaturesGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/autofeatures/SpigotAutoFeaturesGUI.java @@ -47,10 +47,10 @@ public void open() { gui.addButton(new Button(0, XMaterial.RED_STAINED_GLASS_PANE, enable, SpigotPrison.format("&cFull-Inventory-Sound Disabled"))); } - if (afConfig.isFeatureBoolean(AutoFeatures.hologramIfInventoryIsFull)) { - gui.addButton(new Button(8, XMaterial.LIME_STAINED_GLASS_PANE, disable, SpigotPrison.format("&aFull-Inventory-Hologram Enabled"))); + if (afConfig.isFeatureBoolean(AutoFeatures.actionBarMessageIfInventoryIsFull)) { + gui.addButton(new Button(8, XMaterial.LIME_STAINED_GLASS_PANE, disable, SpigotPrison.format("&aFull-Inventory-ActionBar Enabled"))); } else { - gui.addButton(new Button(8, XMaterial.RED_STAINED_GLASS_PANE, enable, SpigotPrison.format("&cFull-Inventory-Hologram Disabled"))); + gui.addButton(new Button(8, XMaterial.RED_STAINED_GLASS_PANE, enable, SpigotPrison.format("&cFull-Inventory-ActionBar Disabled"))); } if (afConfig.isFeatureBoolean(AutoFeatures.isAutoManagerEnabled)) { From a51751b07af236442229f4f89c0415472e8edb63 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 28 Nov 2021 12:33:45 -0500 Subject: [PATCH 158/283] Fixes a minor issue with the command '/mines set spawn' where it was requiring an option be specified. I fixed it by setting a default value of "set" which does nothing, but makes the optional options, optional now. --- docs/changelog_v3.3.x.md | 6 +++++- .../tech/mcprison/prison/mines/commands/MinesCommands.java | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 0ab7f5089..64e3ad7ca 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,11 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.7 2021-11-27 +# 3.2.11-alpha.7 2021-11-28 + + +* **Fixes a minor issue with the command '/mines set spawn' where it was requiring an option be specified.** +I fixed it by setting a default value of "set" which does nothing, but makes the optional options, optional now. * **Removed from the GUI the hologram on inventory full, and replaced it with actionBar.** diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java index 7090cf3ef..1d06053f0 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java @@ -466,7 +466,8 @@ public void tpAccessByRankCommand(CommandSender sender, onlyPlayers = true, permissions = "mines.set") public void spawnpointCommand(CommandSender sender, @Arg(name = "mineName", description = "The name of the mine to edit.") String mineName, - @Arg(name = "options", description = "Options: Option to remove a spawn. [*remove*]") String options ) { + @Arg(name = "options", def = "set", + description = "Options: Option to set or remove a spawn. [set *remove*]") String options ) { Player player = getPlayer( sender ); From fdf88be20bdc234e86f89c788c0116d2f3bf130b Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 28 Nov 2021 12:37:07 -0500 Subject: [PATCH 159/283] Fixed an issue with the mine state mutex being null. Not sure what's causing it, but I suspect it mabe an issue with loading the mine from a saved state on server startup and that field never gets initialized. So fixed it by doing a lazy initialization on the field. --- docs/changelog_v3.3.x.md | 4 ++++ .../main/java/tech/mcprison/prison/mines/data/MineData.java | 3 +++ 2 files changed, 7 insertions(+) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 64e3ad7ca..fe9f4795f 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.7 2021-11-28 +* **Fixed an issue with the mine state mutex being null.** +Not sure what's causing it, but I suspect it mabe an issue with loading the mine from a saved state on server startup and that field never gets initialized. So fixed it by doing a lazy initialization on the field. + + * **Fixes a minor issue with the command '/mines set spawn' where it was requiring an option be specified.** I fixed it by setting a default value of "set" which does nothing, but makes the optional options, optional now. diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java index dda88e9a0..e6dcf50cc 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java @@ -1352,6 +1352,9 @@ public void setDeleted( boolean isDeleted ) { } public MineStateMutex getMineStateMutex() { + if ( mineStateMutex == null ) { + this.mineStateMutex = new MineStateMutex(); + } return mineStateMutex; } } From c83a6cf6ffe3aa695342d5d889ec99802e0681d6 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 28 Nov 2021 17:16:50 -0500 Subject: [PATCH 160/283] Minor changes to clean up auto features a bit: move functions that are no longer used in the normal block break code to OnBlockBreakPlayerManualCore so it's not confused with the main-core functions and accidentally used. Also clean up the messaging and sellall usage to eliminate duplication. --- docs/changelog_v3.3.x.md | 4 + .../autofeatures/AutoManagerFeatures.java | 617 +++++++++--------- .../spigot/block/OnBlockBreakMines.java | 2 +- .../block/OnBlockBreakPlayerManualCore.java | 292 +++++++++ .../spigot/utils/PrisonUtilsMining.java | 14 +- 5 files changed, 629 insertions(+), 300 deletions(-) create mode 100644 prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakPlayerManualCore.java diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index fe9f4795f..df49dd2d7 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.7 2021-11-28 +* **Minor changes to clean up auto features a bit:** move functions that are no longer used in the normal block break code to OnBlockBreakPlayerManualCore so it's not confused with the main-core functions and accidentally used. +Also clean up the messaging and sellall usage to eliminate duplication. + + * **Fixed an issue with the mine state mutex being null.** Not sure what's causing it, but I suspect it mabe an issue with loading the mine from a saved state on server startup and that field never gets initialized. So fixed it by doing a lazy initialization on the field. diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java index bc948e029..4883bd1e6 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java @@ -527,10 +527,9 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, - // Add blocks to player's inventory IF autosell is disabled or the item had a value of ZERO - // which indicates it cannot be sold. If it could not be sold, then amount would be non-zero since - // sold will zero out the number of drops for that item stack. - if ( !isBoolean(AutoFeatures.isAutoSellPerBlockBreakEnabled) || itemStack.getAmount() != 0 ) { + // Add blocks to player's inventory IF autosell was unable to sell the item stack, hence + // it will have an amount of more than 0. + if ( itemStack.getAmount() > 0 ) { if ( Output.get().isDebug() && SellAllUtil.get() != null ) { @@ -738,71 +737,71 @@ public int calculateNormalDrop( PrisonMinesBlockBreakEvent pmEvent, StringBuilde - public void playerSmelt( SpigotPlayer player ) { - - List smelts = new ArrayList<>(); - - smelts.add( XMaterial.COBBLESTONE ); - smelts.add( XMaterial.GOLD_ORE ); - smelts.add( XMaterial.NETHER_GOLD_ORE ); - smelts.add( XMaterial.DEEPSLATE_GOLD_ORE ); - smelts.add( XMaterial.RAW_GOLD ); - - smelts.add( XMaterial.IRON_ORE ); - smelts.add( XMaterial.DEEPSLATE_IRON_ORE ); - smelts.add( XMaterial.RAW_IRON ); - - smelts.add( XMaterial.COAL_ORE ); - smelts.add( XMaterial.DEEPSLATE_COAL_ORE ); - - smelts.add( XMaterial.DIAMOND_ORE ); - smelts.add( XMaterial.DEEPSLATE_DIAMOND_ORE ); - - smelts.add( XMaterial.EMERALD_ORE ); - smelts.add( XMaterial.DEEPSLATE_EMERALD_ORE ); - - smelts.add( XMaterial.LAPIS_ORE ); - smelts.add( XMaterial.DEEPSLATE_LAPIS_ORE ); - - smelts.add( XMaterial.REDSTONE_ORE ); - smelts.add( XMaterial.DEEPSLATE_REDSTONE_ORE ); - - smelts.add( XMaterial.NETHER_QUARTZ_ORE ); - smelts.add( XMaterial.ANCIENT_DEBRIS ); - - smelts.add( XMaterial.COPPER_ORE ); - smelts.add( XMaterial.DEEPSLATE_COPPER_ORE ); - smelts.add( XMaterial.RAW_COPPER ); - - - for ( XMaterial xMat : smelts ) { - autoFeatureSmelt( player.getWrapper(), xMat ); - } - - } +// public void playerSmelt( SpigotPlayer player ) { +// +// List smelts = new ArrayList<>(); +// +// smelts.add( XMaterial.COBBLESTONE ); +// smelts.add( XMaterial.GOLD_ORE ); +// smelts.add( XMaterial.NETHER_GOLD_ORE ); +// smelts.add( XMaterial.DEEPSLATE_GOLD_ORE ); +// smelts.add( XMaterial.RAW_GOLD ); +// +// smelts.add( XMaterial.IRON_ORE ); +// smelts.add( XMaterial.DEEPSLATE_IRON_ORE ); +// smelts.add( XMaterial.RAW_IRON ); +// +// smelts.add( XMaterial.COAL_ORE ); +// smelts.add( XMaterial.DEEPSLATE_COAL_ORE ); +// +// smelts.add( XMaterial.DIAMOND_ORE ); +// smelts.add( XMaterial.DEEPSLATE_DIAMOND_ORE ); +// +// smelts.add( XMaterial.EMERALD_ORE ); +// smelts.add( XMaterial.DEEPSLATE_EMERALD_ORE ); +// +// smelts.add( XMaterial.LAPIS_ORE ); +// smelts.add( XMaterial.DEEPSLATE_LAPIS_ORE ); +// +// smelts.add( XMaterial.REDSTONE_ORE ); +// smelts.add( XMaterial.DEEPSLATE_REDSTONE_ORE ); +// +// smelts.add( XMaterial.NETHER_QUARTZ_ORE ); +// smelts.add( XMaterial.ANCIENT_DEBRIS ); +// +// smelts.add( XMaterial.COPPER_ORE ); +// smelts.add( XMaterial.DEEPSLATE_COPPER_ORE ); +// smelts.add( XMaterial.RAW_COPPER ); +// +// +// for ( XMaterial xMat : smelts ) { +// autoFeatureSmelt( player.getWrapper(), xMat ); +// } +// +// } - public void playerBlock( SpigotPlayer player ) { - - List blocks = new ArrayList<>(); - - blocks.add( XMaterial.GOLD_INGOT ); - blocks.add( XMaterial.IRON_INGOT ); - blocks.add( XMaterial.COAL ); - blocks.add( XMaterial.DIAMOND ); - blocks.add( XMaterial.REDSTONE ); - blocks.add( XMaterial.EMERALD ); - blocks.add( XMaterial.QUARTZ ); - blocks.add( XMaterial.PRISMARINE_SHARD ); - blocks.add( XMaterial.SNOW_BLOCK ); - blocks.add( XMaterial.GLOWSTONE_DUST ); - blocks.add( XMaterial.LAPIS_LAZULI ); - - - for ( XMaterial xMat : blocks ) { - autoFeatureBlock( player.getWrapper(), xMat ); - } - - } +// public void playerBlock( SpigotPlayer player ) { +// +// List blocks = new ArrayList<>(); +// +// blocks.add( XMaterial.GOLD_INGOT ); +// blocks.add( XMaterial.IRON_INGOT ); +// blocks.add( XMaterial.COAL ); +// blocks.add( XMaterial.DIAMOND ); +// blocks.add( XMaterial.REDSTONE ); +// blocks.add( XMaterial.EMERALD ); +// blocks.add( XMaterial.QUARTZ ); +// blocks.add( XMaterial.PRISMARINE_SHARD ); +// blocks.add( XMaterial.SNOW_BLOCK ); +// blocks.add( XMaterial.GLOWSTONE_DUST ); +// blocks.add( XMaterial.LAPIS_LAZULI ); +// +// +// for ( XMaterial xMat : blocks ) { +// autoFeatureBlock( player.getWrapper(), xMat ); +// } +// +// } /** *

The List of drops must have only one ItemStack per block type (name). @@ -877,31 +876,31 @@ protected boolean checkLore( SpigotItemStack itemInHand, String loreValue ) { } - - protected void autoSmelt( boolean autoSmelt, XMaterial source, XMaterial target, Player p ) { - - if ( autoSmelt && source != null && target != null ) { - - HashMap overflow = SpigotUtil.itemStackReplaceItems( p, source, target, 1 ); - dropExtra( overflow, p ); - - } - } - - - protected void autoBlock( boolean autoBlock, XMaterial source, XMaterial target, Player p ) { - autoBlock(autoBlock, source, target, 9, p ); - } - - - protected void autoBlock( boolean autoBlock, XMaterial source, XMaterial target, int ratio, Player p ) { - - if ( autoBlock && source != null && target != null ) { - HashMap overflow = SpigotUtil.itemStackReplaceItems( p, source, target, ratio ); - dropExtra( overflow, p ); - - } - } +// +// protected void autoSmelt( boolean autoSmelt, XMaterial source, XMaterial target, Player p ) { +// +// if ( autoSmelt && source != null && target != null ) { +// +// HashMap overflow = SpigotUtil.itemStackReplaceItems( p, source, target, 1 ); +// dropExtra( overflow, p ); +// +// } +// } +// +// +// protected void autoBlock( boolean autoBlock, XMaterial source, XMaterial target, Player p ) { +// autoBlock(autoBlock, source, target, 9, p ); +// } +// +// +// protected void autoBlock( boolean autoBlock, XMaterial source, XMaterial target, int ratio, Player p ) { +// +// if ( autoBlock && source != null && target != null ) { +// HashMap overflow = SpigotUtil.itemStackReplaceItems( p, source, target, ratio ); +// dropExtra( overflow, p ); +// +// } +// } @@ -913,51 +912,77 @@ protected void autoBlock( boolean autoBlock, XMaterial source, XMaterial target, * @param player * @param block */ - private void dropExtra( HashMap extra, Player player ) { - - if ( extra != null && extra.size() > 0 ) { - if (SpigotPrison.getInstance().isSellAllEnabled()) { - - SellAllUtil sellAllUtil = SellAllUtil.get(); - - if (sellAllUtil != null && sellAllUtil.isAutoSellEnabled) { - if (sellAllUtil.isAutoSellPerUserToggleable) { - if (sellAllUtil.isPlayerAutoSellEnabled(player)) { - if (sellAllUtil.isAutoSellNotificationEnabled) { - SellAllUtil.get().sellAllSell(player, false, false, true, true, false, true); - } else { - SellAllUtil.get().sellAllSell(player, false, true, false, false, false, true); - } - } - } else { - if (sellAllUtil.isAutoSellNotificationEnabled) { - SellAllUtil.get().sellAllSell(player, false, false, true, true, false, true); - } else { - SellAllUtil.get().sellAllSell(player, false, true, false, false, false, true); - } - } + protected void dropExtra( HashMap extra, Player player ) { - // Now that something might have been sold, try to add all the extra inventory items back to the - // player's inventory so it is not lost then pass the moreExtras along to be handled as the - // configurations require. - HashMap moreExtras = new HashMap<>(); - for (SpigotItemStack itemStack : extra.values()) { - moreExtras.putAll(SpigotUtil.addItemToPlayerInventory(player, itemStack)); - } - extra = moreExtras; + if ( extra != null && extra.size() > 0 && SpigotPrison.getInstance().isSellAllEnabled()) { + + SellAllUtil sellAllUtil = SellAllUtil.get(); + + if (sellAllUtil != null && sellAllUtil.isAutoSellEnabled) { + + + if ( !sellAllUtil.isAutoSellPerUserToggleable || + sellAllUtil.isAutoSellPerUserToggleable && sellAllUtil.isPlayerAutoSellEnabled(player) ) { + + boolean saNote = sellAllUtil.isAutoSellNotificationEnabled; + SellAllUtil.get().sellAllSell(player, false, !saNote, saNote, saNote, false, true); } - + + +// if (sellAllUtil.isAutoSellPerUserToggleable) { +// if (sellAllUtil.isPlayerAutoSellEnabled(player)) { +// if (sellAllUtil.isAutoSellNotificationEnabled) { +// SellAllUtil.get().sellAllSell(player, false, false, true, true, false, true); +// } else { +// SellAllUtil.get().sellAllSell(player, false, true, false, false, false, true); +// } +// } +// } else { +// if (sellAllUtil.isAutoSellNotificationEnabled) { +// SellAllUtil.get().sellAllSell(player, false, false, true, true, false, true); +// } else { +// SellAllUtil.get().sellAllSell(player, false, true, false, false, false, true); +// } +// } + + // Now that something might have been sold, try to add all the extra inventory items back to the + // player's inventory so it is not lost then pass the moreExtras along to be handled as the + // configurations require. + HashMap moreExtras = new HashMap<>(); for (SpigotItemStack itemStack : extra.values()) { + moreExtras.putAll(SpigotUtil.addItemToPlayerInventory(player, itemStack)); + } + extra = moreExtras; + } + - if (isBoolean(AutoFeatures.dropItemsIfInventoryIsFull)) { + // drop the player's items if they should be dropped. Also check to see if + // the player should be notified. Ignore zero count itemStacks. + boolean needToNotify = false; + for (SpigotItemStack itemStack : extra.values()) { + + if ( itemStack.getAmount() > 0 ) { + if (isBoolean(AutoFeatures.dropItemsIfInventoryIsFull)) { + SpigotUtil.dropPlayerItems(player, itemStack); - notifyPlayerThatInventoryIsFull(player); - } else { - notifyPlayerThatInventoryIsFullLosingItems(player); } + + needToNotify = true; + } + } + + + // Only send one notification, not matter how many stacks need to be dropped or lost: + if ( needToNotify ) { + if (isBoolean(AutoFeatures.dropItemsIfInventoryIsFull)) { + + notifyPlayerThatInventoryIsFull(player); + } else { + notifyPlayerThatInventoryIsFullLosingItems(player); } } + } } @@ -1330,173 +1355,173 @@ else if ( isBoolean( AutoFeatures.pickupBlockNameListEnabled ) && pickupBlockNam return count; } - - protected XMaterial autoFeatureSmelt( Player p, XMaterial source ) - { - XMaterial results = source; - - boolean isAll = isBoolean( AutoFeatures.smeltAllBlocks ); - -// XMaterial source = SpigotUtil.getXMaterial( block.getPrisonBlock() ); - if ( source != null ) { - - switch ( source ) - { - case COBBLESTONE: - autoSmelt( isAll || isBoolean( AutoFeatures.smeltCobblestone ), source, XMaterial.STONE, p ); - results = XMaterial.STONE; - break; - - case GOLD_ORE: - case NETHER_GOLD_ORE: - case DEEPSLATE_GOLD_ORE: - case RAW_GOLD: - autoSmelt( isAll || isBoolean( AutoFeatures.smeltGoldOre ), source, XMaterial.GOLD_INGOT, p ); - results = XMaterial.GOLD_INGOT; - break; - - case IRON_ORE: - case DEEPSLATE_IRON_ORE: - case RAW_IRON: - autoSmelt( isAll || isBoolean( AutoFeatures.smeltIronOre ), source, XMaterial.IRON_INGOT, p ); - results = XMaterial.IRON_INGOT; - break; - - case COAL_ORE: - case DEEPSLATE_COAL_ORE: - autoSmelt( isAll || isBoolean( AutoFeatures.smeltCoalOre ), source, XMaterial.COAL, p ); - results = XMaterial.COAL; - break; - - case DIAMOND_ORE: - case DEEPSLATE_DIAMOND_ORE: - autoSmelt( isAll || isBoolean( AutoFeatures.smeltDiamondlOre ), source, XMaterial.DIAMOND, p ); - results = XMaterial.DIAMOND; - break; - - case EMERALD_ORE: - case DEEPSLATE_EMERALD_ORE: - autoSmelt( isAll || isBoolean( AutoFeatures.smeltEmeraldOre ), source, XMaterial.EMERALD, p ); - results = XMaterial.EMERALD; - break; - - case LAPIS_ORE: - case DEEPSLATE_LAPIS_ORE: - autoSmelt( isAll || isBoolean( AutoFeatures.smeltLapisOre ), source, XMaterial.LAPIS_LAZULI, p ); - results = XMaterial.LAPIS_LAZULI; - break; - - case REDSTONE_ORE: - case DEEPSLATE_REDSTONE_ORE: - autoSmelt( isAll || isBoolean( AutoFeatures.smeltRedstoneOre ), source, XMaterial.REDSTONE, p ); - results = XMaterial.REDSTONE; - break; - - case NETHER_QUARTZ_ORE: - autoSmelt( isAll || isBoolean( AutoFeatures.smeltNetherQuartzOre ), source, XMaterial.QUARTZ, p ); - results = XMaterial.QUARTZ; - break; - - case ANCIENT_DEBRIS: - autoSmelt( isAll || isBoolean( AutoFeatures.smeltAncientDebris ), source, XMaterial.NETHERITE_SCRAP, p ); - results = XMaterial.NETHERITE_SCRAP; - break; - - // v1.17 !! - case COPPER_ORE: - case DEEPSLATE_COPPER_ORE: - case RAW_COPPER: - autoSmelt( isAll || isBoolean( AutoFeatures.smeltCopperOre ), source, XMaterial.COPPER_INGOT, p ); - results = XMaterial.COPPER_INGOT; - break; - - default: - break; - } - } - - - return results; - } - - protected void autoFeatureBlock( Player p, XMaterial source ) { - - boolean isAll = isBoolean( AutoFeatures.smeltAllBlocks ); - - if ( source != null ) { - - // Any autoBlock target could be enabled, and could have multiples of 9, so perform the - // checks within each block type's function call. So in one pass, could hit on more - // than one of these for multiple times too. - switch ( source ) - { - case GOLD_INGOT: - autoBlock( isAll || isBoolean( AutoFeatures.blockGoldBlock ), source, XMaterial.GOLD_BLOCK, p ); - - break; - - case IRON_INGOT: - autoBlock( isAll || isBoolean( AutoFeatures.blockIronBlock ), source, XMaterial.IRON_BLOCK, p ); - - break; - - case COAL: - autoBlock( isAll || isBoolean( AutoFeatures.blockCoalBlock ), source, XMaterial.COAL_BLOCK, p ); - - break; - - case DIAMOND: - autoBlock( isAll || isBoolean( AutoFeatures.blockDiamondBlock ), source, XMaterial.DIAMOND_BLOCK, p ); - - break; - - case REDSTONE: - autoBlock( isAll || isBoolean( AutoFeatures.blockRedstoneBlock ), source,XMaterial.REDSTONE_BLOCK, p ); - - break; - - case EMERALD: - autoBlock( isAll || isBoolean( AutoFeatures.blockEmeraldBlock ), source, XMaterial.EMERALD_BLOCK, p ); - - break; - - case QUARTZ: - autoBlock( isAll || isBoolean( AutoFeatures.blockQuartzBlock ), source, XMaterial.QUARTZ_BLOCK, 4, p ); - - break; - - case PRISMARINE_SHARD: - autoBlock( isAll || isBoolean( AutoFeatures.blockPrismarineBlock ), source, XMaterial.PRISMARINE, 4, p ); - - break; - - case SNOWBALL: - autoBlock( isAll || isBoolean( AutoFeatures.blockSnowBlock ), source, XMaterial.SNOW_BLOCK, 4, p ); - - break; - - case GLOWSTONE_DUST: - autoBlock( isAll || isBoolean( AutoFeatures.blockGlowstone ), source, XMaterial.GLOWSTONE, 4, p ); - - break; - - case LAPIS_LAZULI: - autoBlock( isAll || isBoolean( AutoFeatures.blockLapisBlock ), source, XMaterial.LAPIS_BLOCK, p ); - - break; - - case COPPER_INGOT: - autoBlock( isAll || isBoolean( AutoFeatures.blockCopperBlock ), source, XMaterial.COPPER_BLOCK, p ); - - break; - - default: - break; - } - } - - } - +// +// protected XMaterial autoFeatureSmelt( Player p, XMaterial source ) +// { +// XMaterial results = source; +// +// boolean isAll = isBoolean( AutoFeatures.smeltAllBlocks ); +// +//// XMaterial source = SpigotUtil.getXMaterial( block.getPrisonBlock() ); +// if ( source != null ) { +// +// switch ( source ) +// { +// case COBBLESTONE: +// autoSmelt( isAll || isBoolean( AutoFeatures.smeltCobblestone ), source, XMaterial.STONE, p ); +// results = XMaterial.STONE; +// break; +// +// case GOLD_ORE: +// case NETHER_GOLD_ORE: +// case DEEPSLATE_GOLD_ORE: +// case RAW_GOLD: +// autoSmelt( isAll || isBoolean( AutoFeatures.smeltGoldOre ), source, XMaterial.GOLD_INGOT, p ); +// results = XMaterial.GOLD_INGOT; +// break; +// +// case IRON_ORE: +// case DEEPSLATE_IRON_ORE: +// case RAW_IRON: +// autoSmelt( isAll || isBoolean( AutoFeatures.smeltIronOre ), source, XMaterial.IRON_INGOT, p ); +// results = XMaterial.IRON_INGOT; +// break; +// +// case COAL_ORE: +// case DEEPSLATE_COAL_ORE: +// autoSmelt( isAll || isBoolean( AutoFeatures.smeltCoalOre ), source, XMaterial.COAL, p ); +// results = XMaterial.COAL; +// break; +// +// case DIAMOND_ORE: +// case DEEPSLATE_DIAMOND_ORE: +// autoSmelt( isAll || isBoolean( AutoFeatures.smeltDiamondlOre ), source, XMaterial.DIAMOND, p ); +// results = XMaterial.DIAMOND; +// break; +// +// case EMERALD_ORE: +// case DEEPSLATE_EMERALD_ORE: +// autoSmelt( isAll || isBoolean( AutoFeatures.smeltEmeraldOre ), source, XMaterial.EMERALD, p ); +// results = XMaterial.EMERALD; +// break; +// +// case LAPIS_ORE: +// case DEEPSLATE_LAPIS_ORE: +// autoSmelt( isAll || isBoolean( AutoFeatures.smeltLapisOre ), source, XMaterial.LAPIS_LAZULI, p ); +// results = XMaterial.LAPIS_LAZULI; +// break; +// +// case REDSTONE_ORE: +// case DEEPSLATE_REDSTONE_ORE: +// autoSmelt( isAll || isBoolean( AutoFeatures.smeltRedstoneOre ), source, XMaterial.REDSTONE, p ); +// results = XMaterial.REDSTONE; +// break; +// +// case NETHER_QUARTZ_ORE: +// autoSmelt( isAll || isBoolean( AutoFeatures.smeltNetherQuartzOre ), source, XMaterial.QUARTZ, p ); +// results = XMaterial.QUARTZ; +// break; +// +// case ANCIENT_DEBRIS: +// autoSmelt( isAll || isBoolean( AutoFeatures.smeltAncientDebris ), source, XMaterial.NETHERITE_SCRAP, p ); +// results = XMaterial.NETHERITE_SCRAP; +// break; +// +// // v1.17 !! +// case COPPER_ORE: +// case DEEPSLATE_COPPER_ORE: +// case RAW_COPPER: +// autoSmelt( isAll || isBoolean( AutoFeatures.smeltCopperOre ), source, XMaterial.COPPER_INGOT, p ); +// results = XMaterial.COPPER_INGOT; +// break; +// +// default: +// break; +// } +// } +// +// +// return results; +// } +// +// protected void autoFeatureBlock( Player p, XMaterial source ) { +// +// boolean isAll = isBoolean( AutoFeatures.smeltAllBlocks ); +// +// if ( source != null ) { +// +// // Any autoBlock target could be enabled, and could have multiples of 9, so perform the +// // checks within each block type's function call. So in one pass, could hit on more +// // than one of these for multiple times too. +// switch ( source ) +// { +// case GOLD_INGOT: +// autoBlock( isAll || isBoolean( AutoFeatures.blockGoldBlock ), source, XMaterial.GOLD_BLOCK, p ); +// +// break; +// +// case IRON_INGOT: +// autoBlock( isAll || isBoolean( AutoFeatures.blockIronBlock ), source, XMaterial.IRON_BLOCK, p ); +// +// break; +// +// case COAL: +// autoBlock( isAll || isBoolean( AutoFeatures.blockCoalBlock ), source, XMaterial.COAL_BLOCK, p ); +// +// break; +// +// case DIAMOND: +// autoBlock( isAll || isBoolean( AutoFeatures.blockDiamondBlock ), source, XMaterial.DIAMOND_BLOCK, p ); +// +// break; +// +// case REDSTONE: +// autoBlock( isAll || isBoolean( AutoFeatures.blockRedstoneBlock ), source,XMaterial.REDSTONE_BLOCK, p ); +// +// break; +// +// case EMERALD: +// autoBlock( isAll || isBoolean( AutoFeatures.blockEmeraldBlock ), source, XMaterial.EMERALD_BLOCK, p ); +// +// break; +// +// case QUARTZ: +// autoBlock( isAll || isBoolean( AutoFeatures.blockQuartzBlock ), source, XMaterial.QUARTZ_BLOCK, 4, p ); +// +// break; +// +// case PRISMARINE_SHARD: +// autoBlock( isAll || isBoolean( AutoFeatures.blockPrismarineBlock ), source, XMaterial.PRISMARINE, 4, p ); +// +// break; +// +// case SNOWBALL: +// autoBlock( isAll || isBoolean( AutoFeatures.blockSnowBlock ), source, XMaterial.SNOW_BLOCK, 4, p ); +// +// break; +// +// case GLOWSTONE_DUST: +// autoBlock( isAll || isBoolean( AutoFeatures.blockGlowstone ), source, XMaterial.GLOWSTONE, 4, p ); +// +// break; +// +// case LAPIS_LAZULI: +// autoBlock( isAll || isBoolean( AutoFeatures.blockLapisBlock ), source, XMaterial.LAPIS_BLOCK, p ); +// +// break; +// +// case COPPER_INGOT: +// autoBlock( isAll || isBoolean( AutoFeatures.blockCopperBlock ), source, XMaterial.COPPER_BLOCK, p ); +// +// break; +// +// default: +// break; +// } +// } +// +// } +// /** *

This processes the normal drop smelting if it's enabled. Only the diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakMines.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakMines.java index 2ea44b4ec..f82bf468e 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakMines.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakMines.java @@ -93,7 +93,7 @@ protected boolean ignoreMinesBlockBreakEvent( Cancellable event, Player player, Mine mine = findMine( player, sBlock, null, null ); - if ( mine == null ) { + if ( mine == null ) { // Prison is unable to process blocks outside of mines right now, so exit: ignoreEvent = true; } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakPlayerManualCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakPlayerManualCore.java new file mode 100644 index 000000000..db847e715 --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakPlayerManualCore.java @@ -0,0 +1,292 @@ +package tech.mcprison.prison.spigot.block; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.bukkit.entity.Player; + +import com.cryptomorin.xseries.XMaterial; + +import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; +import tech.mcprison.prison.spigot.SpigotUtil; +import tech.mcprison.prison.spigot.autofeatures.AutoManagerFeatures; +import tech.mcprison.prison.spigot.game.SpigotPlayer; + +/** + *

This is a manual way of dealing with player inventory directly. It is + * added here to keep it out of the auto features. + * The use of this is through the prison utils functions blocking and smelting. + *

+ * + *

These should not be used with normal block break event handling since + * these manipulate the player's inventory for each process, + * instead of dealing with item stacks during the processing, then adding + * the drops, and the product of the smelting and blocking. + *

+ */ +public class OnBlockBreakPlayerManualCore + extends AutoManagerFeatures +{ + + + public void playerSmelt( SpigotPlayer player ) { + + List smelts = new ArrayList<>(); + + smelts.add( XMaterial.COBBLESTONE ); + smelts.add( XMaterial.GOLD_ORE ); + smelts.add( XMaterial.NETHER_GOLD_ORE ); + smelts.add( XMaterial.DEEPSLATE_GOLD_ORE ); + smelts.add( XMaterial.RAW_GOLD ); + + smelts.add( XMaterial.IRON_ORE ); + smelts.add( XMaterial.DEEPSLATE_IRON_ORE ); + smelts.add( XMaterial.RAW_IRON ); + + smelts.add( XMaterial.COAL_ORE ); + smelts.add( XMaterial.DEEPSLATE_COAL_ORE ); + + smelts.add( XMaterial.DIAMOND_ORE ); + smelts.add( XMaterial.DEEPSLATE_DIAMOND_ORE ); + + smelts.add( XMaterial.EMERALD_ORE ); + smelts.add( XMaterial.DEEPSLATE_EMERALD_ORE ); + + smelts.add( XMaterial.LAPIS_ORE ); + smelts.add( XMaterial.DEEPSLATE_LAPIS_ORE ); + + smelts.add( XMaterial.REDSTONE_ORE ); + smelts.add( XMaterial.DEEPSLATE_REDSTONE_ORE ); + + smelts.add( XMaterial.NETHER_QUARTZ_ORE ); + smelts.add( XMaterial.ANCIENT_DEBRIS ); + + smelts.add( XMaterial.COPPER_ORE ); + smelts.add( XMaterial.DEEPSLATE_COPPER_ORE ); + smelts.add( XMaterial.RAW_COPPER ); + + + for ( XMaterial xMat : smelts ) { + autoFeatureSmelt( player.getWrapper(), xMat ); + } + + } + + public void playerBlock( SpigotPlayer player ) { + + List blocks = new ArrayList<>(); + + blocks.add( XMaterial.GOLD_INGOT ); + blocks.add( XMaterial.IRON_INGOT ); + blocks.add( XMaterial.COAL ); + blocks.add( XMaterial.DIAMOND ); + blocks.add( XMaterial.REDSTONE ); + blocks.add( XMaterial.EMERALD ); + blocks.add( XMaterial.QUARTZ ); + blocks.add( XMaterial.PRISMARINE_SHARD ); + blocks.add( XMaterial.SNOW_BLOCK ); + blocks.add( XMaterial.GLOWSTONE_DUST ); + blocks.add( XMaterial.LAPIS_LAZULI ); + + + for ( XMaterial xMat : blocks ) { + autoFeatureBlock( player.getWrapper(), xMat ); + } + + } + + + protected XMaterial autoFeatureSmelt( Player p, XMaterial source ) + { + XMaterial results = source; + + boolean isAll = isBoolean( AutoFeatures.smeltAllBlocks ); + +// XMaterial source = SpigotUtil.getXMaterial( block.getPrisonBlock() ); + if ( source != null ) { + + switch ( source ) + { + case COBBLESTONE: + autoSmelt( isAll || isBoolean( AutoFeatures.smeltCobblestone ), source, XMaterial.STONE, p ); + results = XMaterial.STONE; + break; + + case GOLD_ORE: + case NETHER_GOLD_ORE: + case DEEPSLATE_GOLD_ORE: + case RAW_GOLD: + autoSmelt( isAll || isBoolean( AutoFeatures.smeltGoldOre ), source, XMaterial.GOLD_INGOT, p ); + results = XMaterial.GOLD_INGOT; + break; + + case IRON_ORE: + case DEEPSLATE_IRON_ORE: + case RAW_IRON: + autoSmelt( isAll || isBoolean( AutoFeatures.smeltIronOre ), source, XMaterial.IRON_INGOT, p ); + results = XMaterial.IRON_INGOT; + break; + + case COAL_ORE: + case DEEPSLATE_COAL_ORE: + autoSmelt( isAll || isBoolean( AutoFeatures.smeltCoalOre ), source, XMaterial.COAL, p ); + results = XMaterial.COAL; + break; + + case DIAMOND_ORE: + case DEEPSLATE_DIAMOND_ORE: + autoSmelt( isAll || isBoolean( AutoFeatures.smeltDiamondlOre ), source, XMaterial.DIAMOND, p ); + results = XMaterial.DIAMOND; + break; + + case EMERALD_ORE: + case DEEPSLATE_EMERALD_ORE: + autoSmelt( isAll || isBoolean( AutoFeatures.smeltEmeraldOre ), source, XMaterial.EMERALD, p ); + results = XMaterial.EMERALD; + break; + + case LAPIS_ORE: + case DEEPSLATE_LAPIS_ORE: + autoSmelt( isAll || isBoolean( AutoFeatures.smeltLapisOre ), source, XMaterial.LAPIS_LAZULI, p ); + results = XMaterial.LAPIS_LAZULI; + break; + + case REDSTONE_ORE: + case DEEPSLATE_REDSTONE_ORE: + autoSmelt( isAll || isBoolean( AutoFeatures.smeltRedstoneOre ), source, XMaterial.REDSTONE, p ); + results = XMaterial.REDSTONE; + break; + + case NETHER_QUARTZ_ORE: + autoSmelt( isAll || isBoolean( AutoFeatures.smeltNetherQuartzOre ), source, XMaterial.QUARTZ, p ); + results = XMaterial.QUARTZ; + break; + + case ANCIENT_DEBRIS: + autoSmelt( isAll || isBoolean( AutoFeatures.smeltAncientDebris ), source, XMaterial.NETHERITE_SCRAP, p ); + results = XMaterial.NETHERITE_SCRAP; + break; + + // v1.17 !! + case COPPER_ORE: + case DEEPSLATE_COPPER_ORE: + case RAW_COPPER: + autoSmelt( isAll || isBoolean( AutoFeatures.smeltCopperOre ), source, XMaterial.COPPER_INGOT, p ); + results = XMaterial.COPPER_INGOT; + break; + + default: + break; + } + } + + + return results; + } + + protected void autoFeatureBlock( Player p, XMaterial source ) { + + boolean isAll = isBoolean( AutoFeatures.smeltAllBlocks ); + + if ( source != null ) { + + // Any autoBlock target could be enabled, and could have multiples of 9, so perform the + // checks within each block type's function call. So in one pass, could hit on more + // than one of these for multiple times too. + switch ( source ) + { + case GOLD_INGOT: + autoBlock( isAll || isBoolean( AutoFeatures.blockGoldBlock ), source, XMaterial.GOLD_BLOCK, p ); + + break; + + case IRON_INGOT: + autoBlock( isAll || isBoolean( AutoFeatures.blockIronBlock ), source, XMaterial.IRON_BLOCK, p ); + + break; + + case COAL: + autoBlock( isAll || isBoolean( AutoFeatures.blockCoalBlock ), source, XMaterial.COAL_BLOCK, p ); + + break; + + case DIAMOND: + autoBlock( isAll || isBoolean( AutoFeatures.blockDiamondBlock ), source, XMaterial.DIAMOND_BLOCK, p ); + + break; + + case REDSTONE: + autoBlock( isAll || isBoolean( AutoFeatures.blockRedstoneBlock ), source,XMaterial.REDSTONE_BLOCK, p ); + + break; + + case EMERALD: + autoBlock( isAll || isBoolean( AutoFeatures.blockEmeraldBlock ), source, XMaterial.EMERALD_BLOCK, p ); + + break; + + case QUARTZ: + autoBlock( isAll || isBoolean( AutoFeatures.blockQuartzBlock ), source, XMaterial.QUARTZ_BLOCK, 4, p ); + + break; + + case PRISMARINE_SHARD: + autoBlock( isAll || isBoolean( AutoFeatures.blockPrismarineBlock ), source, XMaterial.PRISMARINE, 4, p ); + + break; + + case SNOWBALL: + autoBlock( isAll || isBoolean( AutoFeatures.blockSnowBlock ), source, XMaterial.SNOW_BLOCK, 4, p ); + + break; + + case GLOWSTONE_DUST: + autoBlock( isAll || isBoolean( AutoFeatures.blockGlowstone ), source, XMaterial.GLOWSTONE, 4, p ); + + break; + + case LAPIS_LAZULI: + autoBlock( isAll || isBoolean( AutoFeatures.blockLapisBlock ), source, XMaterial.LAPIS_BLOCK, p ); + + break; + + case COPPER_INGOT: + autoBlock( isAll || isBoolean( AutoFeatures.blockCopperBlock ), source, XMaterial.COPPER_BLOCK, p ); + + break; + + default: + break; + } + } + + } + + + + protected void autoSmelt( boolean autoSmelt, XMaterial source, XMaterial target, Player p ) { + + if ( autoSmelt && source != null && target != null ) { + + HashMap overflow = SpigotUtil.itemStackReplaceItems( p, source, target, 1 ); + dropExtra( overflow, p ); + + } + } + + + protected void autoBlock( boolean autoBlock, XMaterial source, XMaterial target, Player p ) { + autoBlock(autoBlock, source, target, 9, p ); + } + + + protected void autoBlock( boolean autoBlock, XMaterial source, XMaterial target, int ratio, Player p ) { + + if ( autoBlock && source != null && target != null ) { + HashMap overflow = SpigotUtil.itemStackReplaceItems( p, source, target, ratio ); + dropExtra( overflow, p ); + + } + } +} diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMining.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMining.java index 42763f32a..139b61bd2 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMining.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMining.java @@ -4,7 +4,7 @@ import tech.mcprison.prison.commands.Command; import tech.mcprison.prison.internal.CommandSender; import tech.mcprison.prison.output.Output; -import tech.mcprison.prison.spigot.SpigotPrison; +import tech.mcprison.prison.spigot.block.OnBlockBreakPlayerManualCore; import tech.mcprison.prison.spigot.game.SpigotPlayer; public class PrisonUtilsMining @@ -57,7 +57,10 @@ public void utilMiningSmelt(CommandSender sender, // Player cannot be null. If it is null, then there was a failure. if ( player != null && player.isOnline() ) { - SpigotPrison.getInstance().getAutoFeatures().playerSmelt( player ); + OnBlockBreakPlayerManualCore manualHandler = new OnBlockBreakPlayerManualCore(); + manualHandler.playerSmelt( player ); + +// SpigotPrison.getInstance().getAutoFeatures().playerSmelt( player ); } } } @@ -83,7 +86,12 @@ public void utilMiningBlock(CommandSender sender, // Player cannot be null. If it is null, then there was a failure. if ( player != null && player.isOnline() ) { - SpigotPrison.getInstance().getAutoFeatures().playerBlock( player ); + + OnBlockBreakPlayerManualCore manualHandler = new OnBlockBreakPlayerManualCore(); + manualHandler.playerBlock( player ); + + +// SpigotPrison.getInstance().getAutoFeatures().playerBlock( player ); } } } From c0cbd5a76e4693f4801abbfa7111fc364ef92209 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 28 Nov 2021 17:19:10 -0500 Subject: [PATCH 161/283] Fix a rare condition where the wrapper of the PrisonBlock is null (the actual bukkit block). This may not fix everything related to this issue, but it will prevent a NPE at this location. --- docs/changelog_v3.3.x.md | 4 ++++ .../java/tech/mcprison/prison/spigot/block/SpigotBlock.java | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index df49dd2d7..db2318d7e 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.7 2021-11-28 +* **Fix a rare condition where the wrapper of the PrisonBlock is null (the actual bukkit block).** +This may not fix everything related to this issue, but it will prevent a NPE at this location. + + * **Minor changes to clean up auto features a bit:** move functions that are no longer used in the normal block break code to OnBlockBreakPlayerManualCore so it's not confused with the main-core functions and accidentally used. Also clean up the messaging and sellall usage to eliminate duplication. diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java index 92b898e59..9b21d95ae 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java @@ -110,7 +110,7 @@ public PrisonBlock getPrisonBlock() { } } - if ( results == null ) { + if ( results == null && getWrapper() != null ) { results = SpigotCompatibility.getInstance().getPrisonBlock( getWrapper() ); } From 65857b15fabc37b85ccb5daecf43c7ffdd254956 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 28 Nov 2021 17:23:15 -0500 Subject: [PATCH 162/283] Add a listSeenDate to the player's cache data. This will be used to track when the player was last on, and more importantly, determine if the player's cache data should be updated for stats reporting for top-n functions. --- docs/changelog_v3.3.x.md | 4 ++ .../prison/cache/PlayerCachePlayerData.java | 18 ++++++++ .../cache/PlayerCacheSaveAllPlayersTask.java | 42 +++++++++++++------ .../prison/ranks/commands/RanksCommands.java | 27 ++++++++---- 4 files changed, 71 insertions(+), 20 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index db2318d7e..34a3284b9 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.7 2021-11-28 +* **Add a listSeenDate to the player's cache data.** +This will be used to track when the player was last on, and more importantly, determine if the player's cache data should be updated for stats reporting for top-n functions. + + * **Fix a rare condition where the wrapper of the PrisonBlock is null (the actual bukkit block).** This may not fix everything related to this issue, but it will prevent a NPE at this location. diff --git a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java index 91c28e4b4..e59563c04 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java @@ -33,6 +33,11 @@ public class PlayerCachePlayerData { private transient Player player; + // lastSeenDate tries to track when the player was last on the server. + // This is important to know for refreshing player stats. + private long lastSeenDate; + + private String playerUuid; private String playerName; @@ -150,6 +155,12 @@ public PlayerCachePlayerData( Player player, File playerFile ) { this.player = player; + if ( isOnline() ) { + + this.lastSeenDate = System.currentTimeMillis(); + this.dirty = true; + } + this.playerUuid = player.getUUID().toString(); this.playerName = player.getName(); @@ -628,6 +639,13 @@ protected void setPlayer( Player player ) { this.player = player; } + public long getLastSeenDate() { + return lastSeenDate; + } + public void setLastSeenDate( long lastSeenDate ) { + this.lastSeenDate = lastSeenDate; + } + public File getPlayerFile() { return playerFile; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheSaveAllPlayersTask.java b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheSaveAllPlayersTask.java index e4802a3d6..a3f0d3234 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheSaveAllPlayersTask.java +++ b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheSaveAllPlayersTask.java @@ -44,6 +44,7 @@ public class PlayerCacheSaveAllPlayersTask extends PlayerCacheRunnable { + public static long LAST_SEEN_INTERVAL_30_MINUTES = 30 * 60 * 1000; @Override public void run() @@ -59,23 +60,40 @@ public void run() { PlayerCachePlayerData playerData = pCache.getPlayers().get( key ); - if ( playerData != null && playerData.isDirty() ) { + if ( playerData != null ) { - try - { - playerData.setDirty( false ); - pCache.getCacheFiles().toJsonFile( playerData ); + // If the player is online plus.. if dirty, or never last seen, or + // it's been more than 30 minutes since update of last seen field: + if ( playerData.isOnline() && + (playerData.isDirty() || + playerData.getLastSeenDate() == 0 || + (System.currentTimeMillis() - playerData.getLastSeenDate()) + > LAST_SEEN_INTERVAL_30_MINUTES ) ) { + // Update the player's last seen date only when dirty and they + // are online: + playerData.setLastSeenDate( System.currentTimeMillis() ); + playerData.setDirty( true ); } - catch ( Exception e ) - { - String message = String.format( - "PlayerCache: Error trying to save a player's " + - "cache data. Will try again later. " + - "%s", e.getMessage() ); - Output.get().logError( message, e ); + + if ( playerData.isDirty() ) { + + try + { + playerData.setDirty( false ); + pCache.getCacheFiles().toJsonFile( playerData ); + } + catch ( Exception e ) + { + String message = String.format( + "PlayerCache: Error trying to save a player's " + + "cache data. Will try again later. " + + "%s", e.getMessage() ); + Output.get().logError( message, e ); + } } } + // If a cached item is found with the player being offline, then // purge them from the cache. They were usually added only because // some process had to inspect their stats, so they are safe to remove. diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java index fddf3ad31..08910c71d 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java @@ -1,8 +1,10 @@ package tech.mcprison.prison.ranks.commands; import java.text.DecimalFormat; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; +import java.util.Date; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -12,8 +14,8 @@ import tech.mcprison.prison.Prison; import tech.mcprison.prison.PrisonAPI; import tech.mcprison.prison.PrisonCommand; -import tech.mcprison.prison.autofeatures.AutoFeaturesWrapper; import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; +import tech.mcprison.prison.autofeatures.AutoFeaturesWrapper; import tech.mcprison.prison.cache.PlayerCache; import tech.mcprison.prison.cache.PlayerCachePlayerData; import tech.mcprison.prison.chat.FancyMessage; @@ -1423,16 +1425,29 @@ public void rankPlayer(CommandSender sender, } List msgs = new ArrayList<>(); + + DecimalFormat dFmt = new DecimalFormat("#,##0.00"); + DecimalFormat fFmt = new DecimalFormat("0.0000"); + DecimalFormat pFmt = new DecimalFormat("#,##0.0000"); + SimpleDateFormat sdFmt = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" ); PlayerManager pm = PrisonRanks.getInstance().getPlayerManager(); RankPlayer rankPlayer = pm.getPlayer(player.getUUID(), player.getName()); + + // Get the cachedPlayer: + PlayerCachePlayerData cPlayer = PlayerCache.getInstance().getOnlinePlayer( rankPlayer ); - String msg1 = String.format( "&7Player Stats for&8: &c%s: ", rankPlayer.getName() ); + + String lastSeen = cPlayer == null || cPlayer.getLastSeenDate() == 0 ? + "-- never -- " : + sdFmt.format( new Date( cPlayer.getLastSeenDate() ) ); + + String msg1 = String.format( "&7Player Stats for&8: &c%s: &7Last Seen: &3%s", + rankPlayer.getName(), lastSeen ); msgs.add( msg1 ); // sendToPlayerAndConsole( sender, msg1 ); - DecimalFormat fFmt = new DecimalFormat("0.0000"); String msg2 = String.format( " &7Rank Cost Multiplier: &f", fFmt.format( rankPlayer.getSellAllMultiplier() )); msgs.add( msg2 ); @@ -1441,7 +1456,6 @@ public void rankPlayer(CommandSender sender, if ( rankPlayer != null ) { - DecimalFormat dFmt = new DecimalFormat("#,##0.00"); // DecimalFormat iFmt = new DecimalFormat("#,##0"); // // SimpleDateFormat sdFmt = new SimpleDateFormat( "HH:mm:ss" ); @@ -1524,7 +1538,6 @@ public void rankPlayer(CommandSender sender, } double sellallMultiplier = player.getSellAllMultiplier(); - DecimalFormat pFmt = new DecimalFormat("#,##0.0000"); String messageNotAccurrate = ranksPlayerNotAccurateMsg(); String messageSellallMultiplier = ranksPlayerSellallMultiplierMsg( pFmt.format( sellallMultiplier ), @@ -1536,9 +1549,7 @@ public void rankPlayer(CommandSender sender, msgs.add( "" ); - // Get the cachedPlayer: - PlayerCachePlayerData cPlayer = PlayerCache.getInstance().getOnlinePlayer( rankPlayer ); - + if ( cPlayer != null ) { msgs.add( "PlayerCache Information:" ); From a9104450de961f96e395000ba861b87a64d97452 Mon Sep 17 00:00:00 2001 From: AnonymousGCA Date: Sun, 28 Nov 2021 23:41:40 +0100 Subject: [PATCH 163/283] Changelogs: - Non-definitive fix for playerMinesGUI NPE. --- .../spigot/gui/ListenersPrisonManager.java | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java index 320662a3c..fcb10bf7f 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java @@ -2008,10 +2008,22 @@ private void playerMinesGUI(Player p, InventoryClickEvent e) { // Confirm the player has access to the mine before trying to TP them there: Mine mine = PrisonMines.getInstance().getMine( mineName ); SpigotPlayer spigotPlayer = new SpigotPlayer(p); - if (mine.hasMiningAccess(spigotPlayer) || p.hasPermission(permission + mineName) || - p.hasPermission(permission.substring(0, permission.length() - 1))) { - Bukkit.dispatchCommand(p, SpigotPrison.format(guiConfig.getString("Options.Mines.CommandWarpPlugin") + " " + mineName)); - } + boolean errorHasMiningPermission = false; + boolean hasMiningPermission = false; + + try { + hasMiningPermission = mine.hasMiningAccess(spigotPlayer); + } catch (NullPointerException ex){ + errorHasMiningPermission = true; + } + + if (errorHasMiningPermission && (p.hasPermission(permission + mineName) || + p.hasPermission(permission.substring(0, permission.length() - 1)))){ + Bukkit.dispatchCommand(p, SpigotPrison.format(guiConfig.getString("Options.Mines.CommandWarpPlugin") + " " + mineName)); + } else if (hasMiningPermission || p.hasPermission(permission + mineName) || + p.hasPermission(permission.substring(0, permission.length() - 1))){ + Bukkit.dispatchCommand(p, SpigotPrison.format(guiConfig.getString("Options.Mines.CommandWarpPlugin") + " " + mineName)); + } } } From 726e111dee0630fcf14ad4e803dabd0ebcb5afae Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 28 Nov 2021 17:54:42 -0500 Subject: [PATCH 164/283] Expand the last seen information on the command /ranks player, which now includes how long ago instead of just a date and time. --- docs/changelog_v3.3.x.md | 3 +++ .../prison/ranks/commands/RanksCommands.java | 27 ++++++++++++++----- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 34a3284b9..7732a889a 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.7 2021-11-28 +* **Expand the last seen information on the command /ranks player, which now includes how long ago instead of just a date and time.** + + * **Add a listSeenDate to the player's cache data.** This will be used to track when the player was last on, and more importantly, determine if the player's cache data should be updated for stats reporting for top-n functions. diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java index 08910c71d..aadf9d1ec 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java @@ -1439,19 +1439,34 @@ public void rankPlayer(CommandSender sender, PlayerCachePlayerData cPlayer = PlayerCache.getInstance().getOnlinePlayer( rankPlayer ); + + String msg1 = String.format( "&7Player Stats for&8: &c%s", + rankPlayer.getName() ); + msgs.add( msg1 ); + + + String lastSeen = cPlayer == null || cPlayer.getLastSeenDate() == 0 ? "-- never -- " : - sdFmt.format( new Date( cPlayer.getLastSeenDate() ) ); + sdFmt.format( new Date( cPlayer.getLastSeenDate() ) ); + long lastSeenElapsedMs = cPlayer == null || cPlayer.getLastSeenDate() == 0 ? + 0 : System.currentTimeMillis() - cPlayer.getLastSeenDate(); + String lastSeenElapsed = lastSeenElapsedMs == 0 ? + "" : + // less than 5 mins just show recently since its not too accurate + lastSeenElapsedMs < (5 * 60 * 1000) ? "-- recently --" : + Text.formatTimeDaysHhMmSs( System.currentTimeMillis() - cPlayer.getLastSeenDate() ) + " ago"; + + String msgLs = String.format( " &7Last Seen: &3%s %s", + lastSeen, lastSeenElapsed ); + msgs.add( msgLs ); + + - String msg1 = String.format( "&7Player Stats for&8: &c%s: &7Last Seen: &3%s", - rankPlayer.getName(), lastSeen ); - msgs.add( msg1 ); -// sendToPlayerAndConsole( sender, msg1 ); String msg2 = String.format( " &7Rank Cost Multiplier: &f", fFmt.format( rankPlayer.getSellAllMultiplier() )); msgs.add( msg2 ); -// sendToPlayerAndConsole( sender, msg2 ); From 7449dbf9e5f734c2313d403d33138ad3d9e56075 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 28 Nov 2021 19:11:26 -0500 Subject: [PATCH 165/283] Update the last seen time. But will not set dirty. If player is not active, then it will not be recorded. --- docs/changelog_v3.3.x.md | 4 ++++ .../java/tech/mcprison/prison/cache/PlayerCache.java | 12 +++++++++--- .../mcprison/prison/cache/PlayerCachePlayerData.java | 8 +++++++- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 7732a889a..3f1f95cf3 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.7 2021-11-28 +* **Update the last seen time.** +But will not set dirty. If player is not active, then it will not be recorded. + + * **Expand the last seen information on the command /ranks player, which now includes how long ago instead of just a date and time.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCache.java b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCache.java index 61a9369e2..5589c7390 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCache.java +++ b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCache.java @@ -271,10 +271,16 @@ private PlayerCachePlayerData getPlayer( Player player ) { playerData = getPlayers().get( playerUuid ); } - if ( playerData != null && - (playerData.getPlayer() == null || !playerData.getPlayer().equals( player ) ) ) { - playerData.setPlayer( player ); + if ( playerData != null ) { + + if ( playerData.getPlayer() == null || !playerData.getPlayer().equals( player ) ) { + + playerData.setPlayer( player ); + } + + playerData.updateLastSeen(); } + return playerData; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java index e59563c04..e9ed9c7ea 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java @@ -630,7 +630,13 @@ public String toString() { return sb.toString(); } - + + public void updateLastSeen() { + + if ( getPlayer() != null && getPlayer().isOnline() ) { + lastSeenDate = System.currentTimeMillis(); + } + } protected Player getPlayer() { return player; From ceeeefec32a2829edd0e4321928c2be123e22570 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Mon, 29 Nov 2021 09:26:27 -0500 Subject: [PATCH 166/283] Release v3.2.11-alpha.8 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index eb99efda2..9d3c6a288 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ ## # This is actually the "correct" place to define the version for the project. ## # Used within build.gradle with ${project.version}. ## # Can be overridden on the command line: gradle -Pversion=3.2.1-alpha.3 -version=3.2.11-alpha.7 +version=3.2.11-alpha.8 #version=3.2.8.2 #version=3.3.0-alpha.6 From 58426038c83261e426d3e0ae0e43c54d87d01b12 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Mon, 29 Nov 2021 09:27:55 -0500 Subject: [PATCH 167/283] Fixed issue with getMine not striping color codes, but in the function before this one is called, it strips them to check to see if the mine name is valid. --- docs/changelog_v3.3.x.md | 12 +++++++++++- .../java/tech/mcprison/prison/mines/PrisonMines.java | 3 ++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 3f1f95cf3..b2c0831e5 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,17 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.7 2021-11-28 +# 3.2.11-alpha.8 2021-11-29 + + +* **Fixed issue with getMine not striping color codes, but in the function before this one is called, it strips them to check to see if the mine name is valid.** + + + + +**3.2.11-alpha.8 2021-11-28** +Release v3.2.11-alpha.8. + * **Update the last seen time.** diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/PrisonMines.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/PrisonMines.java index 525e46a92..da33a9961 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/PrisonMines.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/PrisonMines.java @@ -41,6 +41,7 @@ import tech.mcprison.prison.output.Output; import tech.mcprison.prison.store.Database; import tech.mcprison.prison.util.Location; +import tech.mcprison.prison.util.Text; /** * The Prison 3 Mines Module @@ -334,7 +335,7 @@ public PrisonSortableResults getMines( MineSortOrder sortOrder ) { } public Mine getMine(String mineName) { - return getMineManager().getMine(mineName); + return getMineManager().getMine( Text.stripColor( mineName ) ); } public LocaleManager getMinesMessages() { From a0a776a2c7903bb3f66448b2c95522c7e523a608 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Mon, 29 Nov 2021 09:29:41 -0500 Subject: [PATCH 168/283] Fixed issue with a block break event happening outside of a mine, which will result in mine being null. --- docs/changelog_v3.3.x.md | 4 +++ .../spigot/block/OnBlockBreakMines.java | 31 ++++++++++--------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index b2c0831e5..0a67548c9 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.8 2021-11-29 +* **Fixed issue with a block break event happening outside of a mine, which will result in mine being null.** + + + * **Fixed issue with getMine not striping color codes, but in the function before this one is called, it strips them to check to see if the mine name is valid.** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakMines.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakMines.java index f82bf468e..c686b1d5e 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakMines.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakMines.java @@ -97,23 +97,24 @@ protected boolean ignoreMinesBlockBreakEvent( Cancellable event, Player player, // Prison is unable to process blocks outside of mines right now, so exit: ignoreEvent = true; } - - // If not minable, then display message and exit. - if ( !mine.getMineStateMutex().isMinable() ) { + else { - SpigotPlayer sPlayer = new SpigotPlayer( player ); - sPlayer.setActionBar( "Mine " + mine.getTag() + " is being reset... please wait." ); - event.setCancelled( true ); - ignoreEvent = true; - } - MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); - - // If ignore all block events, then exit this function without logging anything: - if ( targetBlock.isIgnoreAllBlockEvents() ) { - event.setCancelled( true ); - ignoreEvent = true; + // If not minable, then display message and exit. + if ( !mine.getMineStateMutex().isMinable() ) { + + SpigotPlayer sPlayer = new SpigotPlayer( player ); + sPlayer.setActionBar( "Mine " + mine.getTag() + " is being reset... please wait." ); + event.setCancelled( true ); + ignoreEvent = true; + } + MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); + + // If ignore all block events, then exit this function without logging anything: + if ( targetBlock.isIgnoreAllBlockEvents() ) { + event.setCancelled( true ); + ignoreEvent = true; + } } - return ignoreEvent; } From 4c4b5036c5b618a8c3b80777db6388c546ecc2b0 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Mon, 29 Nov 2021 09:41:10 -0500 Subject: [PATCH 169/283] Fixed the auto sell command within the auto features to include the ability to use autosell based upon the auto features settings. --- docs/changelog_v3.3.x.md | 3 +++ .../prison/spigot/autofeatures/AutoManagerFeatures.java | 7 ++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 0a67548c9..0a5e9fdeb 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.8 2021-11-29 +* **Fixed the auto sell command within the auto features to include the ability to use autosell based upon the auto features settings.** + + * **Fixed issue with a block break event happening outside of a mine, which will result in mine being null.** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java index 4883bd1e6..c4745e6e9 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/AutoManagerFeatures.java @@ -918,7 +918,12 @@ protected void dropExtra( HashMap extra, Player player SellAllUtil sellAllUtil = SellAllUtil.get(); - if (sellAllUtil != null && sellAllUtil.isAutoSellEnabled) { + + // On inventory is full, will auto sell if auto sell is enabled in either + // the sellall configs, or the auto feature configs. + if (sellAllUtil != null && ( + sellAllUtil.isAutoSellEnabled || + isBoolean(AutoFeatures.isAutoSellIfInventoryIsFull) )) { if ( !sellAllUtil.isAutoSellPerUserToggleable || From 4f25b690f2de72619447e1408249206e5cc3087a Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Tue, 30 Nov 2021 00:31:49 -0500 Subject: [PATCH 170/283] Major refactoring of Rank Player data objects. This is to transition to easier use of player objects in prison. Some of the key classes have been moved from Ranks module to Core module, with the removal of rank functions being moved back to the ranks module. This is a work in progress and does not yet work. The player's ladders and ranks have not been linked together yet. --- .../prison/cache/PlayerCachePlayerData.java | 11 +- .../prison/commands/RegisteredCommand.java | 5 +- .../prison/ranks/data/PlayerRank.java | 184 ++++++++ .../tech/mcprison/prison/ranks/data/Rank.java | 233 ++++----- .../prison/ranks/data/RankLadder.java | 243 +++++----- .../prison/ranks/data/RankPlayer.java | 445 +++++++++--------- .../prison/ranks/data}/RankPlayerBalance.java | 2 +- .../prison/ranks/data/RankPlayerName.java | 0 .../ranks/data/StatsRankPlayerBalance.java | 0 .../data/StatsRankPlayerBalanceData.java | 5 +- .../mcprison/prison/util/ConversionUtil.java | 14 + .../prison/ranks/FirstJoinHandler.java | 4 +- .../mcprison/prison/ranks/PrisonRanks.java | 20 +- .../tech/mcprison/prison/ranks/RankUtil.java | 25 +- .../mcprison/prison/ranks/RankupResults.java | 13 +- .../prison/ranks/commands/RankUpCommand.java | 34 +- .../prison/ranks/commands/RanksCommands.java | 46 +- .../prison/ranks/data/PlayerRank.java | 114 ----- .../prison/ranks/data/RankFactory.java | 139 ++++++ .../prison/ranks/data/RankLadderFactory.java | 145 ++++++ .../prison/ranks/data/RankPlayerFactory.java | 293 ++++++++++++ .../RankPlayerSortableLadderRankBalance.java | 25 +- .../prison/ranks/managers/LadderManager.java | 21 +- .../prison/ranks/managers/PlayerManager.java | 77 ++- .../prison/ranks/managers/RankManager.java | 37 +- .../prison/spigot/SpigotPlatform.java | 7 +- .../spigot/gui/ListenersPrisonManager.java | 6 +- .../gui/rank/SpigotPlayerPrestigesGUI.java | 7 +- .../spigot/gui/rank/SpigotPlayerRanksGUI.java | 6 +- .../spigot/gui/rank/SpigotRankManagerGUI.java | 5 +- .../spigot/gui/rank/SpigotRanksGUI.java | 3 +- .../prison/spigot/sellall/SellAllUtil.java | 6 +- 32 files changed, 1507 insertions(+), 668 deletions(-) create mode 100644 prison-core/src/main/java/tech/mcprison/prison/ranks/data/PlayerRank.java rename {prison-ranks => prison-core}/src/main/java/tech/mcprison/prison/ranks/data/Rank.java (72%) rename {prison-ranks => prison-core}/src/main/java/tech/mcprison/prison/ranks/data/RankLadder.java (71%) rename {prison-ranks => prison-core}/src/main/java/tech/mcprison/prison/ranks/data/RankPlayer.java (73%) rename {prison-ranks/src/main/java/tech/mcprison/prison/ranks/top => prison-core/src/main/java/tech/mcprison/prison/ranks/data}/RankPlayerBalance.java (98%) rename {prison-ranks => prison-core}/src/main/java/tech/mcprison/prison/ranks/data/RankPlayerName.java (100%) rename {prison-ranks => prison-core}/src/main/java/tech/mcprison/prison/ranks/data/StatsRankPlayerBalance.java (100%) rename {prison-ranks => prison-core}/src/main/java/tech/mcprison/prison/ranks/data/StatsRankPlayerBalanceData.java (94%) create mode 100644 prison-core/src/main/java/tech/mcprison/prison/util/ConversionUtil.java delete mode 100644 prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/PlayerRank.java create mode 100644 prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankFactory.java create mode 100644 prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankLadderFactory.java create mode 100644 prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankPlayerFactory.java rename prison-ranks/src/main/java/tech/mcprison/prison/ranks/{top => data}/RankPlayerSortableLadderRankBalance.java (90%) diff --git a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java index e9ed9c7ea..4c9a94104 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java @@ -33,10 +33,6 @@ public class PlayerCachePlayerData { private transient Player player; - // lastSeenDate tries to track when the player was last on the server. - // This is important to know for refreshing player stats. - private long lastSeenDate; - private String playerUuid; private String playerName; @@ -58,6 +54,11 @@ public class PlayerCachePlayerData { private transient PlayerCacheRunnable task = null; + // lastSeenDate tries to track when the player was last on the server. + // This is important to know for refreshing player stats. + private long lastSeenDate; + private double lastSeenBalance; + private long onlineTimeTotal = 0L; // "active" time is not needed. It's the total onlineTimeTotal minus @@ -158,6 +159,8 @@ public PlayerCachePlayerData( Player player, File playerFile ) { if ( isOnline() ) { this.lastSeenDate = System.currentTimeMillis(); +// this.lastSeenBalance = player.get + this.dirty = true; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/commands/RegisteredCommand.java b/prison-core/src/main/java/tech/mcprison/prison/commands/RegisteredCommand.java index ba3627088..f26a6cd30 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/commands/RegisteredCommand.java +++ b/prison-core/src/main/java/tech/mcprison/prison/commands/RegisteredCommand.java @@ -260,7 +260,10 @@ private void executeMethod(CommandSender sender, String[] args) { // to prevent this failure, escape all % with a double % such as %%. message = message.replace( "%", "%%" ); - Output.get().sendError( sender, message ); + Output.get().logError( message ); + + Output.get().sendError( sender, "An exception has occurred. Details have been " + + "logged to the server's console." ); // Generally these errors are major and require program fixes, so throw // the exception so the stacklist is logged. diff --git a/prison-core/src/main/java/tech/mcprison/prison/ranks/data/PlayerRank.java b/prison-core/src/main/java/tech/mcprison/prison/ranks/data/PlayerRank.java new file mode 100644 index 000000000..c579a1212 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/ranks/data/PlayerRank.java @@ -0,0 +1,184 @@ +package tech.mcprison.prison.ranks.data; + +/** + *

PlayerRank is a container for holding a players rank, along with their + * rankMultiplier and the calculated rankCost. + *

+ * + */ +public class PlayerRank +{ + + private final Rank rank; + + private Double rankMultiplier = null; + private Double rankCost = null; + + protected PlayerRank( Rank rank ) { + super(); + + this.rank = rank; + +// double rankMultiplier = getLadderBasedRankMultiplier( rank ); +// +// setRankCost( rankMultiplier ); +//// this.rankCost = rank.getCost() * (1.0 + rankMultiplier); + } + + protected PlayerRank( Rank rank, double rankMultiplier ) { + this( rank ); + + this.rankMultiplier = rankMultiplier; + + setRankCost( rankMultiplier ); +// this.rankCost = rank.getCost() * (1.0 + rankMultiplier); + } + + public void applyMultiplier( double rankMultiplier ) { + + this.rankMultiplier = rankMultiplier; + + setRankCost( rankMultiplier ); +// this.rankCost = rank.getCost() * (1.0 + rankMultiplier); + } + + protected void setRankCost( double rankMultiplier ) { + + this.rankCost = rank.getCost() * (1.0 + rankMultiplier); + } + + public double getLadderBasedRankMultiplier() { + return getLadderBasedRankMultiplier( getRank() ); + } + + public double getLadderBasedRankMultiplier( Rank rank ) { + double rankMultiplier = 0; + + if ( rank != null && rank.getLadder() != null ) { + double ladderMultiplier = rank.getLadder().getRankCostMultiplierPerRank(); + + // Because it's zero based... so add a 1 + rankMultiplier = ladderMultiplier * (1 + rank.getPosition()); + } + + return rankMultiplier; + } + + +// public static double getRawRankCost( Rank rank ) { +// return rank.getCost(); +// } +// public static void setRawRankCost( Rank rank, double rawCost ) { +// rank.setCost( rawCost ); +// } + +// public static PlayerRank getTargetPlayerRankForPlayer( RankPlayer player, Rank targetRank ) { +// PlayerRank targetPlayerRank = null; +// +// if ( targetRank != null ) { +// +// double targetRankMultiplier = getLadderBaseRankdMultiplier( targetRank ); +// +// PlayerRank pRankForPLayer = player.getRank( targetRank.getLadder() ); +// double existingRankMultiplier = pRankForPLayer == null ? 0 : +// getLadderBaseRankdMultiplier( pRankForPLayer.getRank() ); +// +// // Get the player's total rankMultiplier from the default ladder +// // because they will always have a rank there: +// PlayerRank pRank = player.getRank( "default" ); +// double playerMultipler = pRank == null ? 0 : pRank.getRankMultiplier(); +// +// // So the actual rank multiplier that needs to be used, is based upon the +// // Player's current multiplier PLUS the multiplier for the target rank +// // AND MINUS the multiplier for the current rank the player has within the +// // target rank's ladder. +// double rankMultiplier = playerMultipler + targetRankMultiplier - existingRankMultiplier; +// +// targetPlayerRank = new PlayerRank( targetRank, rankMultiplier ); +// } +// +// return targetPlayerRank; +// } + + + public PlayerRank getTargetPlayerRankForPlayer( RankPlayer player, Rank targetRank ) { + return getTargetPlayerRankForPlayer( this, player, targetRank ); + } + + public PlayerRank getTargetPlayerRankForPlayer( PlayerRank playerRank, RankPlayer player, Rank targetRank ) + { + PlayerRank targetPlayerRank = null; + + if ( targetRank != null ) + { + + double targetRankMultiplier = playerRank.getLadderBasedRankMultiplier( targetRank ); + + + PlayerRank pRankForPLayer = player.getLadderRanks().get( targetRank.getLadder() ); + + // PlayerRank pRankForPLayer = getRank( player, targetRank.getLadder() ); + double existingRankMultiplier = pRankForPLayer == null ? 0 + : playerRank.getLadderBasedRankMultiplier( pRankForPLayer.getRank() ); + + // Get the player's total rankMultiplier from the default ladder + // because they will always have a rank there: + RankLadder defaultLadder = getDefaultLadder( player ); + + PlayerRank pRank = player.getLadderRanks().get( defaultLadder ); +// PlayerRank pRank = getRank( player, "default" ); + double playerMultipler = pRank == null ? 0 : pRank.getRankMultiplier(); + + // So the actual rank multiplier that needs to be used, is based upon + // the + // Player's current multiplier PLUS the multiplier for the target rank + // AND MINUS the multiplier for the current rank the player has within + // the + // target rank's ladder. + double rankMultiplier = playerMultipler + targetRankMultiplier - existingRankMultiplier; + + targetPlayerRank = createPlayerRank( targetRank, rankMultiplier ); + } + + return targetPlayerRank; + } + + private RankLadder getDefaultLadder( RankPlayer player ) + { + RankLadder defaultLadder = null; + + for ( RankLadder ladder : player.getLadderRanks().keySet() ) + { + if ( ladder.getName().equalsIgnoreCase( "default" ) ) { + defaultLadder = ladder; + } + } + + return defaultLadder; + } + + private PlayerRank createPlayerRank( Rank rank, double rankMultiplier ) { + PlayerRank results = new PlayerRank( rank, rankMultiplier ); + + return results; + } + + public Rank getRank() { + return rank; + } + + public Double getRankMultiplier() { + return rankMultiplier; + } +// public void setRankMultiplier( Double rankMultiplier ) { +// this.rankMultiplier = rankMultiplier; +// } + + public Double getRankCost() { + return rankCost; + } +// public void setRankCost( Double rankCost ) { +// this.rankCost = rankCost; +// } + +} diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/Rank.java b/prison-core/src/main/java/tech/mcprison/prison/ranks/data/Rank.java similarity index 72% rename from prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/Rank.java rename to prison-core/src/main/java/tech/mcprison/prison/ranks/data/Rank.java index a21e0d7c6..06ba0a34c 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/Rank.java +++ b/prison-core/src/main/java/tech/mcprison/prison/ranks/data/Rank.java @@ -22,11 +22,7 @@ import tech.mcprison.prison.modules.ModuleElement; import tech.mcprison.prison.modules.ModuleElementType; -import tech.mcprison.prison.output.Output; -import tech.mcprison.prison.ranks.PrisonRanks; -import tech.mcprison.prison.ranks.RankUtil; import tech.mcprison.prison.sorting.PrisonSortable; -import tech.mcprison.prison.store.Document; /** * Represents a single rank. @@ -34,7 +30,7 @@ * @author Faizaan A. Datoo */ public class Rank - extends RankMessages + //extends RankMessages implements PrisonSortable, ModuleElement { @@ -131,112 +127,112 @@ protected Rank( String name ) { this.name = name; } - @SuppressWarnings( "unchecked" ) - public Rank(Document document) { - this(); - - try - { -// Object pos = document.get("position"); -// this.position = RankUtil.doubleToInt( pos == null ? 0.0d : pos ); - - this.id = RankUtil.doubleToInt(document.get("id")); - this.name = (String) document.get("name"); - this.tag = (String) document.get("tag"); - this.cost = (double) document.get("cost"); - - String currency = (String) document.get("currency"); - this.currency = (currency == null || - "null".equalsIgnoreCase( currency ) ? null : currency); - - getRankUpCommands().clear(); - Object cmds = document.get("commands"); - if ( cmds != null ) { - - List commands = (List) cmds; - for ( String cmd : commands ) { - if ( cmd != null ) { - getRankUpCommands().add( cmd ); - } - } - - // This was allowing nulls to be added to the live commands... -// this.rankUpCommands = (List) cmds; - } - - getMines().clear(); - getMineStrings().clear(); - Object minesObj = document.get("mines"); - if ( minesObj != null ) { - List mineStrings = (List) minesObj; - setMineStrings( mineStrings ); - } - - -// getPermissions().clear(); -// Object perms = document.get( "permissions" ); -// if ( perms != null ) { -// List permissions = (List) perms; -// for ( String permission : permissions ) { -// getPermissions().add( permission ); +// @SuppressWarnings( "unchecked" ) +// public Rank(Document document) { +// this(); +// +// try +// { +//// Object pos = document.get("position"); +//// this.position = RankUtil.doubleToInt( pos == null ? 0.0d : pos ); +// +// this.id = RankUtil.doubleToInt(document.get("id")); +// this.name = (String) document.get("name"); +// this.tag = (String) document.get("tag"); +// this.cost = (double) document.get("cost"); +// +// String currency = (String) document.get("currency"); +// this.currency = (currency == null || +// "null".equalsIgnoreCase( currency ) ? null : currency); +// +// getRankUpCommands().clear(); +// Object cmds = document.get("commands"); +// if ( cmds != null ) { +// +// List commands = (List) cmds; +// for ( String cmd : commands ) { +// if ( cmd != null ) { +// getRankUpCommands().add( cmd ); +// } // } +// +// // This was allowing nulls to be added to the live commands... +//// this.rankUpCommands = (List) cmds; // } -// // -// getPermissionGroups().clear(); -// Object permsGroups = document.get( "permissionGroups" ); -// if ( perms != null ) { -// List permissionGroups = (List) permsGroups; -// for ( String permissionGroup : permissionGroups ) { -// getPermissionGroups().add( permissionGroup ); -// } +// getMines().clear(); +// getMineStrings().clear(); +// Object minesObj = document.get("mines"); +// if ( minesObj != null ) { +// List mineStrings = (List) minesObj; +// setMineStrings( mineStrings ); // } - - } - catch ( Exception e ) - { - String message = rankFailureLoadingRanksMsg( Integer.toString( this.id ), - (this.name == null ? "null" : this.name ), - e.getMessage() ); - - Output.get().logError( message ); - } - } - - public Document toDocument() { - Document ret = new Document(); -// ret.put("position", this.position ); - ret.put("id", this.id); - ret.put("name", this.name); - ret.put("tag", this.tag); - ret.put("cost", this.cost); - ret.put("currency", this.currency); - - List cmds = new ArrayList<>(); - for ( String cmd : getRankUpCommands() ) { - // Filters out possible nulls: - if ( cmd != null ) { - cmds.add( cmd ); - } - } - ret.put("commands", cmds); - - List mineStrings = new ArrayList<>(); - if ( getMines() != null ) { - for ( ModuleElement mine : getMines() ) { - String mineString = mine.getModuleElementType() + "," + mine.getName() + "," + - mine.getId() + "," + mine.getTag(); - mineStrings.add( mineString ); - } - } - ret.put("mines", mineStrings); - -// ret.put( "permissions", getPermissions() ); -// ret.put( "permissionGroups", getPermissionGroups() ); - - return ret; - } - +// +// +//// getPermissions().clear(); +//// Object perms = document.get( "permissions" ); +//// if ( perms != null ) { +//// List permissions = (List) perms; +//// for ( String permission : permissions ) { +//// getPermissions().add( permission ); +//// } +//// } +//// +//// +//// getPermissionGroups().clear(); +//// Object permsGroups = document.get( "permissionGroups" ); +//// if ( perms != null ) { +//// List permissionGroups = (List) permsGroups; +//// for ( String permissionGroup : permissionGroups ) { +//// getPermissionGroups().add( permissionGroup ); +//// } +//// } +// +// } +// catch ( Exception e ) +// { +// String message = rankFailureLoadingRanksMsg( Integer.toString( this.id ), +// (this.name == null ? "null" : this.name ), +// e.getMessage() ); +// +// Output.get().logError( message ); +// } +// } + +// public Document toDocument() { +// Document ret = new Document(); +//// ret.put("position", this.position ); +// ret.put("id", this.id); +// ret.put("name", this.name); +// ret.put("tag", this.tag); +// ret.put("cost", this.cost); +// ret.put("currency", this.currency); +// +// List cmds = new ArrayList<>(); +// for ( String cmd : getRankUpCommands() ) { +// // Filters out possible nulls: +// if ( cmd != null ) { +// cmds.add( cmd ); +// } +// } +// ret.put("commands", cmds); +// +// List mineStrings = new ArrayList<>(); +// if ( getMines() != null ) { +// for ( ModuleElement mine : getMines() ) { +// String mineString = mine.getModuleElementType() + "," + mine.getName() + "," + +// mine.getId() + "," + mine.getTag(); +// mineStrings.add( mineString ); +// } +// } +// ret.put("mines", mineStrings); +// +//// ret.put( "permissions", getPermissions() ); +//// ret.put( "permissionGroups", getPermissionGroups() ); +// +// return ret; +// } +// // /** @@ -320,10 +316,10 @@ public String filename() { public RankLadder getLadder() { - if ( ladder == null ) { - - ladder = PrisonRanks.getInstance().getLadderManager().getLadder( this ); - } +// if ( ladder == null ) { +// +// ladder = PrisonRanks.getInstance().getLadderManager().getLadder( this ); +// } return ladder; } @@ -442,6 +438,21 @@ public void setTag( String tag ) { this.tag = tag; } + /** + *

This is publicly available as "raw" to underscore that it is not an + * adjusted cost value. + *

+ * + * @param rank + * @return + */ + public double getRawRankCost() { + return cost; + } + public void setRawRankCost( double cost ) { + this.cost = cost; + } + protected double getCost() { return cost; } diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankLadder.java b/prison-core/src/main/java/tech/mcprison/prison/ranks/data/RankLadder.java similarity index 71% rename from prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankLadder.java rename to prison-core/src/main/java/tech/mcprison/prison/ranks/data/RankLadder.java index 8864a5a0c..47c899f2a 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankLadder.java +++ b/prison-core/src/main/java/tech/mcprison/prison/ranks/data/RankLadder.java @@ -23,9 +23,6 @@ import com.google.gson.internal.LinkedTreeMap; -import tech.mcprison.prison.ranks.PrisonRanks; -import tech.mcprison.prison.ranks.RankUtil; -import tech.mcprison.prison.ranks.managers.RankManager; import tech.mcprison.prison.sorting.PrisonSortable; import tech.mcprison.prison.store.Document; @@ -82,131 +79,131 @@ public RankLadder( int id, String name ) { this.name = name; } - @SuppressWarnings( "unchecked" ) - public RankLadder(Document document, PrisonRanks prisonRanks) { - this(); - - boolean isDirty = false; - - this.id = RankUtil.doubleToInt(document.get("id")); - this.name = (String) document.get("name"); - - RankManager rankManager = prisonRanks.getRankManager(); - - if ( rankManager == null ) { - - RankMessages rMessages = new RankMessages(); - rMessages.rankFailureLoadingRankManagerMsg( getName(), getId() ); - - return; - } - - List> ranksLocal = - (List>) document.get("ranks"); - - getRankUpCommands().clear(); - Object cmds = document.get("commands"); - if ( cmds != null ) { - - List commands = (List) cmds; - for ( String cmd : commands ) { - if ( cmd != null ) { - getRankUpCommands().add( cmd ); - } - } - - // This was allowing nulls to be added to the live commands... -// this.rankUpCommands = (List) cmds; - } - - - this.ranks = new ArrayList<>(); - for (LinkedTreeMap rank : ranksLocal) { - - - // The only real field that is important here is rankId to tie the - // rank back to this ladder. Name helps clarify the contents of the - // Ladder file. - int rRankId = RankUtil.doubleToInt((rank.get("rankId"))); - String rRankName = (String) rank.get( "rankName" ); - - Rank rankPrison = rankManager.getRank( rRankId ); - - if ( rankPrison != null && rankPrison.getLadder() != null ) { - - RankMessages rMessages = new RankMessages(); - rMessages.rankFailureLoadingDuplicateRankMsg( - rankPrison.getName(), rankPrison.getLadder().getName(), - getName() ); - - isDirty = true; - } - else if ( rankPrison != null) { - - addRank( rankPrison ); - -// Output.get().logInfo( "RankLadder load : " + getName() + -// " rank= " + rankPrison.getName() + " " + rankPrison.getId() + -// ); - -// // if null look it up from loaded ranks: -// if ( rRankName == null ) { -// rRankName = rankPrison.getName(); -// dirty = true; -// } - } - else { - // Rank not found. Try to create it? The name maybe wrong. - String rankName = rRankName != null && !rRankName.trim().isEmpty() ? - rRankName : "Rank " + rRankId; - - // NOTE: The following is valid use of getCost(): - double cost = getRanks().size() == 0 ? 0 : - getRanks().get( getRanks().size() - 1 ).getCost() * 3; - Rank newRank = new Rank( rRankId, rankName, null, cost ); - - addRank( newRank ); - -// String message = String.format( -// "Loading RankLadder Error: A rank for %s was not found so it was " + -// "fabricated: %s id=%d tag=%s cost=%d", getName(), newRank.getName(), newRank.getId(), -// newRank.getTag(), newRank.getCost() ); -// Output.get().logError( message ); - } - - } - -// this.maxPrestige = RankUtil.doubleToInt(document.get("maxPrestige")); - - - Double rankCostMultiplier = (Double) document.get( "rankCostMultiplierPerRank" ); - setRankCostMultiplierPerRank( rankCostMultiplier == null ? 0 : rankCostMultiplier ); - - -// getPermissions().clear(); -// Object perms = document.get( "permissions" ); -// if ( perms != null ) { -// List permissions = (List) perms; -// for ( String permission : permissions ) { -// getPermissions().add( permission ); +// @SuppressWarnings( "unchecked" ) +// public RankLadder(Document document, PrisonRanks prisonRanks) { +// this(); +// +// boolean isDirty = false; +// +// this.id = ConversionUtil.doubleToInt(document.get("id")); +// this.name = (String) document.get("name"); +// +// RankManager rankManager = prisonRanks.getRankManager(); +// +// if ( rankManager == null ) { +// +// RankMessages rMessages = new RankMessages(); +// rMessages.rankFailureLoadingRankManagerMsg( getName(), getId() ); +// +// return; +// } +// +// List> ranksLocal = +// (List>) document.get("ranks"); +// +// getRankUpCommands().clear(); +// Object cmds = document.get("commands"); +// if ( cmds != null ) { +// +// List commands = (List) cmds; +// for ( String cmd : commands ) { +// if ( cmd != null ) { +// getRankUpCommands().add( cmd ); +// } // } +// +// // This was allowing nulls to be added to the live commands... +//// this.rankUpCommands = (List) cmds; // } +// +// +// this.ranks = new ArrayList<>(); +// for (LinkedTreeMap rank : ranksLocal) { +// +// +// // The only real field that is important here is rankId to tie the +// // rank back to this ladder. Name helps clarify the contents of the +// // Ladder file. +// int rRankId = ConversionUtil.doubleToInt((rank.get("rankId"))); +// String rRankName = (String) rank.get( "rankName" ); +// +// Rank rankPrison = rankManager.getRank( rRankId ); +// +// if ( rankPrison != null && rankPrison.getLadder() != null ) { +// +// RankMessages rMessages = new RankMessages(); +// rMessages.rankFailureLoadingDuplicateRankMsg( +// rankPrison.getName(), rankPrison.getLadder().getName(), +// getName() ); +// +// isDirty = true; +// } +// else if ( rankPrison != null) { +// +// addRank( rankPrison ); +// +//// Output.get().logInfo( "RankLadder load : " + getName() + +//// " rank= " + rankPrison.getName() + " " + rankPrison.getId() + +//// ); +// +//// // if null look it up from loaded ranks: +//// if ( rRankName == null ) { +//// rRankName = rankPrison.getName(); +//// dirty = true; +//// } +// } +// else { +// // Rank not found. Try to create it? The name maybe wrong. +// String rankName = rRankName != null && !rRankName.trim().isEmpty() ? +// rRankName : "Rank " + rRankId; +// +// // NOTE: The following is valid use of getCost(): +// double cost = getRanks().size() == 0 ? 0 : +// getRanks().get( getRanks().size() - 1 ).getCost() * 3; +// Rank newRank = new Rank( rRankId, rankName, null, cost ); +// +// addRank( newRank ); +// +//// String message = String.format( +//// "Loading RankLadder Error: A rank for %s was not found so it was " + +//// "fabricated: %s id=%d tag=%s cost=%d", getName(), newRank.getName(), newRank.getId(), +//// newRank.getTag(), newRank.getCost() ); +//// Output.get().logError( message ); +// } +// +// } +// +//// this.maxPrestige = RankUtil.doubleToInt(document.get("maxPrestige")); +// +// +// Double rankCostMultiplier = (Double) document.get( "rankCostMultiplierPerRank" ); +// setRankCostMultiplierPerRank( rankCostMultiplier == null ? 0 : rankCostMultiplier ); // // -// getPermissionGroups().clear(); -// Object permsGroups = document.get( "permissionGroups" ); -// if ( perms != null ) { -// List permissionGroups = (List) permsGroups; -// for ( String permissionGroup : permissionGroups ) { -// getPermissionGroups().add( permissionGroup ); -// } +//// getPermissions().clear(); +//// Object perms = document.get( "permissions" ); +//// if ( perms != null ) { +//// List permissions = (List) perms; +//// for ( String permission : permissions ) { +//// getPermissions().add( permission ); +//// } +//// } +//// +//// +//// getPermissionGroups().clear(); +//// Object permsGroups = document.get( "permissionGroups" ); +//// if ( perms != null ) { +//// List permissionGroups = (List) permsGroups; +//// for ( String permissionGroup : permissionGroups ) { +//// getPermissionGroups().add( permissionGroup ); +//// } +//// } +// +// if ( isDirty ) { +// PrisonRanks.getInstance().getLadderManager().save( this ); // } - - if ( isDirty ) { - PrisonRanks.getInstance().getLadderManager().save( this ); - } - - } +// +// } public Document toDocument() { Document ret = new Document(); diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankPlayer.java b/prison-core/src/main/java/tech/mcprison/prison/ranks/data/RankPlayer.java similarity index 73% rename from prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankPlayer.java rename to prison-core/src/main/java/tech/mcprison/prison/ranks/data/RankPlayer.java index a4b44bfc8..7934ea2c6 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankPlayer.java +++ b/prison-core/src/main/java/tech/mcprison/prison/ranks/data/RankPlayer.java @@ -20,14 +20,11 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.TreeMap; import java.util.UUID; -import com.google.gson.internal.LinkedTreeMap; - import tech.mcprison.prison.Prison; import tech.mcprison.prison.PrisonAPI; import tech.mcprison.prison.integration.EconomyCurrencyIntegration; @@ -38,12 +35,6 @@ import tech.mcprison.prison.internal.inventory.Inventory; import tech.mcprison.prison.internal.scoreboard.Scoreboard; import tech.mcprison.prison.output.Output; -import tech.mcprison.prison.ranks.FirstJoinHandlerMessages; -import tech.mcprison.prison.ranks.PrisonRanks; -import tech.mcprison.prison.ranks.RankUtil; -import tech.mcprison.prison.ranks.events.FirstJoinEvent; -import tech.mcprison.prison.ranks.top.RankPlayerBalance; -import tech.mcprison.prison.store.Document; import tech.mcprison.prison.util.Gamemode; import tech.mcprison.prison.util.Location; @@ -72,8 +63,8 @@ public class RankPlayer private List names; - // Block name, count - private HashMap blocksMined; +// // Block name, count +// private HashMap blocksMined; // For tops processing. Need current balance. @@ -93,6 +84,8 @@ public RankPlayer() { this.ranksRefs = new HashMap<>(); //this.prestige = new HashMap<>(); +// this.blocksMined = new HashMap<>(); + this.playerBalances = new TreeMap<>(); } @@ -108,68 +101,68 @@ public RankPlayer( UUID uid, String playerName ) { checkName( playerName ); } - @SuppressWarnings( "unchecked" ) - public RankPlayer(Document document) { - this(); - - this.uid = UUID.fromString((String) document.get("uid")); - LinkedTreeMap ranksLocal = - (LinkedTreeMap) document.get("ranks"); -// LinkedTreeMap prestigeLocal = -// (LinkedTreeMap) document.get("prestige"); - - LinkedTreeMap blocksMinedLocal = - (LinkedTreeMap) document.get("blocksMined"); - - Object namesListObject = document.get( "names" ); - - - for (String key : ranksLocal.keySet()) { - ranksRefs.put(key, RankUtil.doubleToInt(ranksLocal.get(key))); - } - -// for (String key : prestigeLocal.keySet()) { -// prestige.put(key, RankUtil.doubleToInt(prestigeLocal.get(key))); +// @SuppressWarnings( "unchecked" ) +// public RankPlayer(Document document) { +// this(); +// +// this.uid = UUID.fromString((String) document.get("uid")); +// LinkedTreeMap ranksLocal = +// (LinkedTreeMap) document.get("ranks"); +//// LinkedTreeMap prestigeLocal = +//// (LinkedTreeMap) document.get("prestige"); +// +// LinkedTreeMap blocksMinedLocal = +// (LinkedTreeMap) document.get("blocksMined"); +// +// Object namesListObject = document.get( "names" ); +// +// +// for (String key : ranksLocal.keySet()) { +// ranksRefs.put(key, ConversionUtil.doubleToInt(ranksLocal.get(key))); // } - - this.blocksMined = new HashMap<>(); - if ( blocksMinedLocal != null ) { - for (String key : blocksMinedLocal.keySet()) { - blocksMined.put(key, RankUtil.doubleToInt(blocksMinedLocal.get(key))); - } - } - - if ( namesListObject != null ) { - - for ( Object rankPlayerNameMap : (ArrayList) namesListObject ) { - LinkedTreeMap rpnMap = (LinkedTreeMap) rankPlayerNameMap; - - if ( rpnMap.size() > 0 ) { - String name = (String) rpnMap.get( "name" ); - long date = RankUtil.doubleToLong( rpnMap.get( "date" ) ); - - RankPlayerName rankPlayerName = new RankPlayerName( name, date ); - getNames().add( rankPlayerName ); -// Output.get().logInfo( "RankPlayer: uuid: " + uid + " RankPlayerName: " + rankPlayerName.toString() ); - } - - } - } - - } - - public Document toDocument() { - Document ret = new Document(); - ret.put("uid", this.uid); - ret.put("ranks", this.ranksRefs); -// ret.put("prestige", this.prestige); - - ret.put("names", this.names); - - ret.put("blocksMined", this.blocksMined); - return ret; - } - +// +//// for (String key : prestigeLocal.keySet()) { +//// prestige.put(key, RankUtil.doubleToInt(prestigeLocal.get(key))); +//// } +// +// this.blocksMined = new HashMap<>(); +// if ( blocksMinedLocal != null ) { +// for (String key : blocksMinedLocal.keySet()) { +// blocksMined.put(key, ConversionUtil.doubleToInt(blocksMinedLocal.get(key))); +// } +// } +// +// if ( namesListObject != null ) { +// +// for ( Object rankPlayerNameMap : (ArrayList) namesListObject ) { +// LinkedTreeMap rpnMap = (LinkedTreeMap) rankPlayerNameMap; +// +// if ( rpnMap.size() > 0 ) { +// String name = (String) rpnMap.get( "name" ); +// long date = ConversionUtil.doubleToLong( rpnMap.get( "date" ) ); +// +// RankPlayerName rankPlayerName = new RankPlayerName( name, date ); +// getNames().add( rankPlayerName ); +//// Output.get().logInfo( "RankPlayer: uuid: " + uid + " RankPlayerName: " + rankPlayerName.toString() ); +// } +// +// } +// } +// +// } +// +// public Document toDocument() { +// Document ret = new Document(); +// ret.put("uid", this.uid); +// ret.put("ranks", this.ranksRefs); +//// ret.put("prestige", this.prestige); +// +// ret.put("names", this.names); +// +// ret.put("blocksMined", this.blocksMined); +// return ret; +// } +// @Override public String toString() { @@ -261,12 +254,12 @@ public void setNames( List names ) { this.names = names; } - public HashMap getBlocksMined() { - return blocksMined; - } - public void setBlocksMined( HashMap blocksMined ) { - this.blocksMined = blocksMined; - } +// public HashMap getBlocksMined() { +// return blocksMined; +// } +// public void setBlocksMined( HashMap blocksMined ) { +// this.blocksMined = blocksMined; +// } /** *

This is a helper function to ensure that the given file name is @@ -281,44 +274,44 @@ public String filename() } - /** - *

This function will check to see if the player is on the default rank on - * the default ladder. If not, then it will add them. - *

- * - *

This is safe to run on anyone, even if they already are on the default ladder. - *

- * - *

Note, this will not save the player's new rank. The save function must be - * managed and called outside of this. - *

- */ - public void firstJoin() { - - RankLadder defaultLadder = PrisonRanks.getInstance().getDefaultLadder(); - - if ( !getLadderRanks().containsKey( defaultLadder ) ) { - - Optional firstRank = defaultLadder.getLowestRank(); - - if ( firstRank.isPresent() ) { - Rank rank = firstRank.get(); - - addRank( rank ); - - Prison.get().getEventBus().post(new FirstJoinEvent( this )); - - FirstJoinHandlerMessages messages = new FirstJoinHandlerMessages(); - Output.get().logWarn( messages.firstJoinSuccess( getName() ) ); - - } else { - - FirstJoinHandlerMessages messages = new FirstJoinHandlerMessages(); - Output.get().logWarn( messages.firstJoinWarningNoRanksOnServer() ); - } - } - - } +// /** +// *

This function will check to see if the player is on the default rank on +// * the default ladder. If not, then it will add them. +// *

+// * +// *

This is safe to run on anyone, even if they already are on the default ladder. +// *

+// * +// *

Note, this will not save the player's new rank. The save function must be +// * managed and called outside of this. +// *

+// */ +// public void firstJoin() { +// +// RankLadder defaultLadder = PrisonRanks.getInstance().getDefaultLadder(); +// +// if ( !getLadderRanks().containsKey( defaultLadder ) ) { +// +// Optional firstRank = defaultLadder.getLowestRank(); +// +// if ( firstRank.isPresent() ) { +// Rank rank = firstRank.get(); +// +// addRank( rank ); +// +// Prison.get().getEventBus().post(new FirstJoinEvent( this )); +// +// FirstJoinHandlerMessages messages = new FirstJoinHandlerMessages(); +// Output.get().logWarn( messages.firstJoinSuccess( getName() ) ); +// +// } else { +// +// FirstJoinHandlerMessages messages = new FirstJoinHandlerMessages(); +// Output.get().logWarn( messages.firstJoinWarningNoRanksOnServer() ); +// } +// } +// +// } /** * Add a rank to this player. @@ -411,78 +404,74 @@ public boolean hasLadder( String ladderName ) { return ranksRefs.containsKey( ladderName ); } - /** - * Removes a ladder from this player, including whichever rank this player had in it. - * Cannot remove the default ladder. - * - * @param ladderName The ladder's name. - */ - public boolean removeLadder(String ladderName) { - boolean results = false; - if ( !ladderName.equalsIgnoreCase("default") ) { - Integer id = ranksRefs.remove(ladderName); - results = (id != null); - - RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder( ladderName ); - if ( ladder != null && !ladder.getName().equalsIgnoreCase( "default" ) ) { - ladderRanks.remove( ladder ); - } - } - - return results; - } - - /* - * Getters & Setters - */ - - /** - * Retrieves the rank that this player has in a certain ladder, if any. - * - * @param ladder The ladder to check. - * @return An optional containing the {@link Rank} if found, or empty if there isn't a rank by that ladder for this player. - */ - public PlayerRank getRank(RankLadder ladder) { - PlayerRank results = null; - - if ( ladder != null ) { - - Set keys = ladderRanks.keySet(); - for ( RankLadder key : keys ) - { - if ( key != null && key.getName().equalsIgnoreCase( ladder.getName() ) ) { - results = ladderRanks.get( key ); - } - } - } - - return results; - -// if (!ranksRefs.containsKey(ladder.getName())) { -// return null; +// /** +// * Removes a ladder from this player, including whichever rank this player had in it. +// * Cannot remove the default ladder. +// * +// * @param ladderName The ladder's name. +// */ +// public boolean removeLadder(String ladderName) { +// boolean results = false; +// if ( !ladderName.equalsIgnoreCase("default") ) { +// Integer id = ranksRefs.remove(ladderName); +// results = (id != null); +// +// RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder( ladderName ); +// if ( ladder != null && !ladder.getName().equalsIgnoreCase( "default" ) ) { +// ladderRanks.remove( ladder ); +// } // } -// int id = ranksRefs.get(ladder.getName()); -// return PrisonRanks.getInstance().getRankManager().getRank(id); - } - - /** - * Retrieves the rank that this player has the specified ladder. - * - * @param ladder The ladder name to check. - * @return The {@link Rank} if found, otherwise null; - */ - public PlayerRank getRank( String ladderName ) { - - RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder( ladderName ); - return getRank( ladder ); - -// Rank results = null; -// if (ladder != null && ranksRefs.containsKey(ladder)) { -// int id = ranksRefs.get(ladder); -// results = PrisonRanks.getInstance().getRankManager().getRank(id); +// +// return results; +// } + +// /** +// * Retrieves the rank that this player has in a certain ladder, if any. +// * +// * @param ladder The ladder to check. +// * @return An optional containing the {@link Rank} if found, or empty if there isn't a rank by that ladder for this player. +// */ +// public PlayerRank getRank(RankLadder ladder) { +// PlayerRank results = null; +// +// if ( ladder != null ) { +// +// Set keys = ladderRanks.keySet(); +// for ( RankLadder key : keys ) +// { +// if ( key != null && key.getName().equalsIgnoreCase( ladder.getName() ) ) { +// results = ladderRanks.get( key ); +// } +// } // } +// // return results; - } +// +//// if (!ranksRefs.containsKey(ladder.getName())) { +//// return null; +//// } +//// int id = ranksRefs.get(ladder.getName()); +//// return PrisonRanks.getInstance().getRankManager().getRank(id); +// } +// +// /** +// * Retrieves the rank that this player has the specified ladder. +// * +// * @param ladder The ladder name to check. +// * @return The {@link Rank} if found, otherwise null; +// */ +// public PlayerRank getRank( String ladderName ) { +// +// RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder( ladderName ); +// return getRank( ladder ); +// +//// Rank results = null; +//// if (ladder != null && ranksRefs.containsKey(ladder)) { +//// int id = ranksRefs.get(ladder); +//// results = PrisonRanks.getInstance().getRankManager().getRank(id); +//// } +//// return results; +// } @@ -497,42 +486,56 @@ public void setRanks( HashMap ranks ) { this.ranksRefs = ranks; } - /** - * Returns all ladders this player is a part of, along with each rank the player has in that ladder. - * - * @return The map containing this data. - */ - public Map getLadderRanks() { - - if ( ladderRanks.isEmpty() && !ranksRefs.isEmpty() ) { - - //Map ret = new HashMap<>(); - for (Map.Entry entry : ranksRefs.entrySet()) { - RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder(entry.getKey()); - - if ( ladder == null ) { - continue; // Skip it - } - - Rank rank = PrisonRanks.getInstance().getRankManager().getRank(entry.getValue()); - if ( rank == null ) { - continue; // Skip it - } - - PlayerRank pRank = new PlayerRank( rank ); - - ladderRanks.put(ladder, pRank); - } - - // Need to recalculate all rank multipliers: - recalculateRankMultipliers(); - } - - return ladderRanks; - } +// /** +// * Returns all ladders this player is a part of, along with each rank the player has in that ladder. +// * +// * @return The map containing this data. +// */ +// public Map getLadderRanks( RankPlayer rankPlay) { +// +// if ( ladderRanks.isEmpty() && !ranksRefs.isEmpty() ) { +// +// //Map ret = new HashMap<>(); +// +// for (Map.Entry entry : rankPlay.getRanksRefs().entrySet()) { +// RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder(entry.getKey()); +// +// if ( ladder == null ) { +// continue; // Skip it +// } +// +// Rank rank = PrisonRanks.getInstance().getRankManager().getRank(entry.getValue()); +// if ( rank == null ) { +// continue; // Skip it +// } +// +// PlayerRank pRank = new PlayerRank( rank ); +// +// ladderRanks.put(ladder, pRank); +// } +// +// // Need to recalculate all rank multipliers: +// recalculateRankMultipliers(); +// } +// +// return ladderRanks; +// } + public TreeMap getLadderRanks() { + return ladderRanks; + } +// public void setLadderRanks( TreeMap ladderRanks ) { +// this.ladderRanks = ladderRanks; +// } - /** + public HashMap getRanksRefs(){ + return ranksRefs ; + } + public void setRanksRefs( HashMap ranksRefs ) { + this.ranksRefs = ranksRefs; + } + + /** *

This function will check to see if the player has the same rank as the * targetRank, or if the target rank is lower on the ladder than where their * current rank is located. This confirms that the two ranks are on the same @@ -548,7 +551,9 @@ public boolean hasAccessToRank( Rank targetRank ) { if ( targetRank != null && targetRank.getLadder() != null ) { - PlayerRank pRank = getRank( targetRank.getLadder() ); + PlayerRank pRank = getLadderRanks().get( targetRank.getLadder() ); + +// PlayerRank pRank = getRank( targetRank.getLadder() ); if ( pRank != null ) { Rank rank = pRank.getRank(); diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/top/RankPlayerBalance.java b/prison-core/src/main/java/tech/mcprison/prison/ranks/data/RankPlayerBalance.java similarity index 98% rename from prison-ranks/src/main/java/tech/mcprison/prison/ranks/top/RankPlayerBalance.java rename to prison-core/src/main/java/tech/mcprison/prison/ranks/data/RankPlayerBalance.java index 0aa4440cf..bd139d3c4 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/top/RankPlayerBalance.java +++ b/prison-core/src/main/java/tech/mcprison/prison/ranks/data/RankPlayerBalance.java @@ -1,4 +1,4 @@ -package tech.mcprison.prison.ranks.top; +package tech.mcprison.prison.ranks.data; public class RankPlayerBalance { diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankPlayerName.java b/prison-core/src/main/java/tech/mcprison/prison/ranks/data/RankPlayerName.java similarity index 100% rename from prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankPlayerName.java rename to prison-core/src/main/java/tech/mcprison/prison/ranks/data/RankPlayerName.java diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/StatsRankPlayerBalance.java b/prison-core/src/main/java/tech/mcprison/prison/ranks/data/StatsRankPlayerBalance.java similarity index 100% rename from prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/StatsRankPlayerBalance.java rename to prison-core/src/main/java/tech/mcprison/prison/ranks/data/StatsRankPlayerBalance.java diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/StatsRankPlayerBalanceData.java b/prison-core/src/main/java/tech/mcprison/prison/ranks/data/StatsRankPlayerBalanceData.java similarity index 94% rename from prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/StatsRankPlayerBalanceData.java rename to prison-core/src/main/java/tech/mcprison/prison/ranks/data/StatsRankPlayerBalanceData.java index fa09e0030..bc85ab78f 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/StatsRankPlayerBalanceData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/ranks/data/StatsRankPlayerBalanceData.java @@ -31,7 +31,8 @@ public void recalc( boolean isPenaltyEnabled ) { // The "cost" should be the cost of the next rank. If the next rank does not exist, // then it should be the current rank. - PlayerRank pRank = player.getRank( rank.getLadder() ); + PlayerRank pRank = player.getLadderRanks().get( rank.getLadder() ); + if ( pRank != null ) { double cost = pRank.getRankCost(); // This is the fallback value if nextRank doesn't exist. @@ -39,7 +40,7 @@ public void recalc( boolean isPenaltyEnabled ) { if ( rank.getRankNext() != null ) { // This calculates the target rank, and takes in to consideration the player's existing rank: - PlayerRank pRankNext = PlayerRank.getTargetPlayerRankForPlayer( player, rank.getRankNext() ); + PlayerRank pRankNext = pRank.getTargetPlayerRankForPlayer( player, rank.getRankNext() ); //PlayerRank pRankNext = new PlayerRank( rank.getRankNext(), pRank.getRankMultiplier() ); cost = pRankNext.getRankCost(); diff --git a/prison-core/src/main/java/tech/mcprison/prison/util/ConversionUtil.java b/prison-core/src/main/java/tech/mcprison/prison/util/ConversionUtil.java new file mode 100644 index 000000000..b70e97444 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/util/ConversionUtil.java @@ -0,0 +1,14 @@ +package tech.mcprison.prison.util; + +public class ConversionUtil +{ + + public static int doubleToInt(Object d) { + return Math.toIntExact(Math.round((double) d)); + } + + public static long doubleToLong(Object d) { + return Math.round((double) d); + } + +} diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/FirstJoinHandler.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/FirstJoinHandler.java index ca57dd184..7d546d044 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/FirstJoinHandler.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/FirstJoinHandler.java @@ -21,6 +21,7 @@ import tech.mcprison.prison.Prison; import tech.mcprison.prison.ranks.data.RankPlayer; +import tech.mcprison.prison.ranks.data.RankPlayerFactory; import tech.mcprison.prison.ranks.events.FirstJoinEvent; /** @@ -47,7 +48,8 @@ public FirstJoinHandler() { RankPlayer player = event.getPlayer(); // Try to perform the first join processing to give them the default rank: - player.firstJoin(); + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + rankPlayerFactory.firstJoin( player ); PrisonRanks.getInstance().getPlayerManager().savePlayer(player); // try { diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/PrisonRanks.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/PrisonRanks.java index a1ee9fb89..bcb2b810b 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/PrisonRanks.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/PrisonRanks.java @@ -38,6 +38,7 @@ import tech.mcprison.prison.ranks.data.Rank; import tech.mcprison.prison.ranks.data.RankLadder; import tech.mcprison.prison.ranks.data.RankPlayer; +import tech.mcprison.prison.ranks.data.RankPlayerFactory; import tech.mcprison.prison.ranks.managers.LadderManager; import tech.mcprison.prison.ranks.managers.PlayerManager; import tech.mcprison.prison.ranks.managers.RankManager; @@ -152,6 +153,17 @@ public void enable() { // rankManager.connectRanks(); + for ( Rank rank : rankManager.getRanks() ) { + + if ( rank.getLadder() == null ) { + // Hook up the ladder if it has not been setup yet: + RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder( rank ); + + rank.setLadder( ladder ); + } + } + + // Verify that all ranks that use currencies have valid currencies: rankManager.identifyAllRankCurrencies( getPrisonStartupDetails() ); @@ -253,6 +265,8 @@ public void checkAllPlayersForJoin() } + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + // If any player does not have a rank on the default ladder, then add the default // ladder and rank: Rank defaultRank = defaultLadder.getLowestRank().get(); @@ -263,9 +277,9 @@ public void checkAllPlayersForJoin() Rank rankOnDefault = null; - if ( rPlayer.getRank( defaultLadder ) != null ) { + if ( rankPlayerFactory.getRank( rPlayer, defaultLadder ) != null ) { - rankOnDefault = rPlayer.getRank( defaultLadder ).getRank(); + rankOnDefault = rankPlayerFactory.getRank( rPlayer, defaultLadder ).getRank(); // Output.get().logInfo( "#### %s ladder = %s isRankNull= %s rank= %s %s [%s]" , // rPlayer.getName(), @@ -279,7 +293,7 @@ public void checkAllPlayersForJoin() rankupCommands.setPlayerRank( rPlayer, defaultRank ); - if ( rPlayer.getRank( defaultLadder ) != null ) { + if ( rankPlayerFactory.getRank( rPlayer, defaultLadder ) != null ) { String message = prisonRankAddedNewPlayer( rPlayer.getName() ); diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/RankUtil.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/RankUtil.java index c857d320b..b0a2fc19b 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/RankUtil.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/RankUtil.java @@ -32,6 +32,7 @@ import tech.mcprison.prison.ranks.data.Rank; import tech.mcprison.prison.ranks.data.RankLadder; import tech.mcprison.prison.ranks.data.RankPlayer; +import tech.mcprison.prison.ranks.data.RankPlayerFactory; import tech.mcprison.prison.ranks.events.RankUpEvent; import tech.mcprison.prison.tasks.PrisonCommandTask; import tech.mcprison.prison.tasks.PrisonCommandTask.CustomPlaceholders; @@ -338,7 +339,9 @@ private void rankupPlayerInternal(RankupResults results, // should never make it this far in to this code: // Um... not true when performing a prestige for the first time.... lol - PlayerRank originalRank = rankPlayer.getRank(ladder); + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + + PlayerRank originalRank = rankPlayerFactory.getRank( rankPlayer, ladder ); // if ( originalRank == null && ladder.getName().equals( "default" ) ) { // @@ -376,7 +379,7 @@ private void rankupPlayerInternal(RankupResults results, results.addTransaction(RankupTransactions.cannot_delete_default_ladder); } else { - boolean success = rankPlayer.removeLadder( ladder.getName() ); + boolean success = rankPlayerFactory.removeLadder( rankPlayer, ladder.getName() ); if ( success ) { if ( savePlayerRank( results, rankPlayer ) ) { @@ -406,13 +409,13 @@ private void rankupPlayerInternal(RankupResults results, // This calculates the target rank, and takes in to consideration the player's existing rank: - PlayerRank pRankNext = PlayerRank.getTargetPlayerRankForPlayer( rankPlayer, targetRank ); + PlayerRank pRankNext = originalRank.getTargetPlayerRankForPlayer( rankPlayer, targetRank ); // new PlayerRank( targetRank, originalRank.getRankMultiplier() ); // If player does not have a rank on this ladder, then grab the first rank on the ladder since they need // to be added to the ladder. if ( pRankNext == null ) { - pRankNext = PlayerRank.getTargetPlayerRankForPlayer( rankPlayer, ladder.getLowestRank().get() ); + pRankNext = originalRank.getTargetPlayerRankForPlayer( rankPlayer, ladder.getLowestRank().get() ); } @@ -738,13 +741,13 @@ else if ("default".equalsIgnoreCase( results.getLadder().getName() ) && rankName } - public static int doubleToInt(Object d) { - return Math.toIntExact(Math.round((double) d)); - } - - public static long doubleToLong(Object d) { - return Math.round((double) d); - } +// public static int doubleToInt(Object d) { +// return Math.toIntExact(Math.round((double) d)); +// } +// +// public static long doubleToLong(Object d) { +// return Math.round((double) d); +// } diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/RankupResults.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/RankupResults.java index d703c213b..92cc3a811 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/RankupResults.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/RankupResults.java @@ -10,6 +10,7 @@ import tech.mcprison.prison.ranks.data.Rank; import tech.mcprison.prison.ranks.data.RankLadder; import tech.mcprison.prison.ranks.data.RankPlayer; +import tech.mcprison.prison.ranks.data.RankPlayerFactory; public class RankupResults { @@ -144,7 +145,10 @@ public void setStatus( RankupStatus status ) { public PlayerRank getPlayerRankOriginal() { if ( playerRankOriginal == null && originalRank != null && rankPlayer != null ) { - PlayerRank pRank = rankPlayer.getRank( originalRank.getLadder() ); + + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + + PlayerRank pRank = rankPlayerFactory.getRank( rankPlayer, originalRank.getLadder() ); playerRankOriginal = pRank; } return playerRankOriginal; @@ -158,8 +162,13 @@ public PlayerRank getPlayerRankTarget() { getOriginalRank() != null && getOriginalRank().getRankNext() != null && targetRank != null ) { + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + + PlayerRank pRank = rankPlayerFactory.createPlayerRank( getOriginalRank() ); + // This calculates the target rank, and takes in to consideration the player's existing rank: - playerRankTarget = PlayerRank.getTargetPlayerRankForPlayer( rankPlayer, targetRank ); + playerRankTarget = pRank.getTargetPlayerRankForPlayer( rankPlayer, targetRank ); +// playerRankTarget = PlayerRank.getTargetPlayerRankForPlayer( rankPlayer, targetRank ); // PlayerRank pRank = rankPlayer.getRank( originalRank.getLadder() ); // PlayerRank pRankNext = new PlayerRank( targetRank, pRank.getRankMultiplier() ); diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RankUpCommand.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RankUpCommand.java index eb9babf7c..52babb1d5 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RankUpCommand.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RankUpCommand.java @@ -37,6 +37,7 @@ import tech.mcprison.prison.ranks.data.Rank; import tech.mcprison.prison.ranks.data.RankLadder; import tech.mcprison.prison.ranks.data.RankPlayer; +import tech.mcprison.prison.ranks.data.RankPlayerFactory; import tech.mcprison.prison.ranks.managers.LadderManager; import tech.mcprison.prison.ranks.managers.PlayerManager; @@ -158,13 +159,16 @@ private void rankUpPrivate(CommandSender sender, String ladder, RankupModes mode } + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + RankPlayer rankPlayer = getRankPlayer( sender, player.getUUID(), player.getName() ); - PlayerRank playerRankCurrent = rankPlayer.getRank( ladder ); + PlayerRank playerRankCurrent = rankPlayerFactory.getRank( rankPlayer, ladder ); + + Rank targetRank = playerRankCurrent == null ? targetLadder.getLowestRank().get() : + playerRankCurrent.getRank(); + PlayerRank playerRankTarget = - PlayerRank.getTargetPlayerRankForPlayer( rankPlayer, - playerRankCurrent == null ? targetLadder.getLowestRank().get() : - playerRankCurrent.getRank() - ); + playerRankCurrent.getTargetPlayerRankForPlayer( rankPlayer, targetRank ); Output.get().logDebug( DebugTarget.rankup, @@ -194,7 +198,7 @@ private void rankUpPrivate(CommandSender sender, String ladder, RankupModes mode } // gets the rank on the default ladder. Used if ladder is not default. - PlayerRank pRankDefaultLadder = rankPlayer.getRank("default"); + PlayerRank pRankDefaultLadder = rankPlayerFactory.getRank( rankPlayer, "default"); if ( pRankDefaultLadder == null ) { rankupErrorPlayerNotOnDefaultLadder( sender, rankPlayer ); } @@ -236,7 +240,7 @@ private void rankUpPrivate(CommandSender sender, String ladder, RankupModes mode // Get the player rank after - PlayerRank playerRankAfter = rankPlayer.getRank( ladder ); + PlayerRank playerRankAfter = rankPlayerFactory.getRank( rankPlayer, ladder ); if ( playerRankAfter != null ) { @@ -302,7 +306,9 @@ private void prestigePlayer(CommandSender sender, Player player, RankPlayer rank // lm.getLadder("default").getLowestRank().get().getName() + " default"); // Get that rank - PlayerRank playerRankSecond = rankPlayer.getRank("default"); + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + + PlayerRank playerRankSecond = rankPlayerFactory.getRank( rankPlayer, "default"); if ( playerRankSecond != null ) { Rank pRankSecond = playerRankSecond.getRank(); @@ -368,8 +374,10 @@ public void promotePlayer(CommandSender sender, ladder = confirmLadder( sender, ladder ); + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + RankPlayer rankPlayer = getRankPlayer( sender, playerUuid, player.getName() ); - PlayerRank playerRank = rankPlayer.getRank( ladder ); + PlayerRank playerRank = rankPlayerFactory.getRank( rankPlayer, ladder ); if ( playerRank != null ) { @@ -423,8 +431,10 @@ public void demotePlayer(CommandSender sender, return; } + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + RankPlayer rankPlayer = getRankPlayer( sender, playerUuid, player.getName() ); - PlayerRank playerRank = rankPlayer.getRank( ladder ); + PlayerRank playerRank = rankPlayerFactory.getRank( rankPlayer, ladder ); if ( playerRank != null ) { @@ -470,7 +480,9 @@ public void setRank(CommandSender sender, boolean isSameRank = rank.equalsIgnoreCase("*same*"); - PlayerRank pRank = player.getRank( ladder ); + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + + PlayerRank pRank = rankPlayerFactory.getRank( player, ladder ); String rankNameCurrent = isSameRank && pRank != null && pRank.getRank() != null ? diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java index aadf9d1ec..26061d313 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java @@ -44,6 +44,7 @@ import tech.mcprison.prison.ranks.data.Rank; import tech.mcprison.prison.ranks.data.RankLadder; import tech.mcprison.prison.ranks.data.RankPlayer; +import tech.mcprison.prison.ranks.data.RankPlayerFactory; import tech.mcprison.prison.ranks.data.RankPlayerName; import tech.mcprison.prison.ranks.managers.LadderManager; import tech.mcprison.prison.ranks.managers.PlayerManager; @@ -866,6 +867,8 @@ private ChatDisplay listRanksOnLadder( RankLadder ladder, boolean hasPerm, RankP } } + + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); boolean first = true; for (Rank rank : ladder.getRanks()) { @@ -890,6 +893,7 @@ private ChatDisplay listRanksOnLadder( RankLadder ladder, boolean hasPerm, RankP // String tagNoColor = Text.stripColor( tag ); + // If rank list is being generated for a console or op'd player, then show the ladder's rank multiplier, // but if generating for a player, then show total multiplier accross all ladders. PlayerRank pRank = null; @@ -898,12 +902,17 @@ private ChatDisplay listRanksOnLadder( RankLadder ladder, boolean hasPerm, RankP if ( hasPerm || rPlayer == null ) { - rankCost = PlayerRank.getRawRankCost( rank ); - rMulti = PlayerRank.getLadderBaseRankdMultiplier( rank ); + rankCost = rank.getRawRankCost(); + + pRank = rankPlayerFactory.createPlayerRank( rank ); + + rMulti = pRank.getLadderBasedRankMultiplier(); } else { - pRank = PlayerRank.getTargetPlayerRankForPlayer( rPlayer, rank ); + pRank = rankPlayerFactory.createPlayerRank( rank ); + + pRank = pRank.getTargetPlayerRankForPlayer( pRank, rPlayer, rank ); rankCost = pRank.getRankCost(); rMulti = pRank.getRankMultiplier(); @@ -1004,8 +1013,14 @@ private ChatDisplay listRanksOnLadder( RankLadder ladder, boolean hasPerm, RankP } if ( rPlayer != null && !"No Ladder".equals( ladder.getName() ) ) { + +// RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + double ladderMultiplier = ladder.getRankCostMultiplierPerRank(); - double playerMultiplier = rPlayer.getRank( ladder ) != null ? rPlayer.getRank( ladder ).getRankMultiplier() : 0; + + PlayerRank pRank = rankPlayerFactory.getRank( rPlayer, ladder ); + double playerMultiplier = pRank != null ? + pRank.getRankMultiplier() : 0; if ( playerMultiplier == 0 ) { display.addText( "&3You have no Ladder Rank Multipliers enabled. The rank costs are not adjusted." ); @@ -1028,9 +1043,12 @@ private ChatDisplay listRanksOnLadder( RankLadder ladder, boolean hasPerm, RankP if ( rLadder.getRankCostMultiplierPerRank() != 0d ) { Rank r = rPlayer.getLadderRanks().get( rLadder ).getRank(); + + PlayerRank rpRank = rankPlayerFactory.createPlayerRank( r ); + display.addText( "&3 BaseMult: &7%7s &3CurrMult: &7%7s &7%s &7%s ", fFmt.format( rLadder.getRankCostMultiplierPerRank() ), - fFmt.format( PlayerRank.getLadderBaseRankdMultiplier( r )), + fFmt.format( rpRank.getLadderBasedRankMultiplier() ), rLadder.getName(), r.getTag() ); @@ -1168,10 +1186,11 @@ private ChatDisplay rankInfoDetails( CommandSender sender, Rank rank, String opt + // NOTE: Since rank info is NOT tied to a PlayerRank we cannot figure out the // the actual cost, but we can calculate the ladder's multiplier. This // will not be the player's total multiplier. - display.addText( ranksInfoCostMsg( PlayerRank.getRawRankCost( rank ) )); + display.addText( ranksInfoCostMsg( rank.getRawRankCost() )); @@ -1179,7 +1198,11 @@ private ChatDisplay rankInfoDetails( CommandSender sender, Rank rank, String opt DecimalFormat fFmt = new DecimalFormat("#,##0.0000"); // The following is the rank adjusted rank multiplier - double rankCostMultiplier = PlayerRank.getLadderBaseRankdMultiplier( rank ); + + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + PlayerRank pRank = rankPlayerFactory.createPlayerRank( rank ); + + double rankCostMultiplier = pRank.getLadderBasedRankMultiplier(); double ladderBaseMultiplier = rank.getLadder() == null ? 0 : rank.getLadder().getRankCostMultiplierPerRank(); String cmdLadderRankCostMult = "/ranks ladder rankMultiplier " + rank.getName() + " " + ladderBaseMultiplier; @@ -1243,7 +1266,8 @@ public void setCost(CommandSender sender, } - PlayerRank.setRawRankCost( rank, rawCost ); + rank.setRawRankCost( rawCost ); +// PlayerRank.setRawRankCost( rank, rawCost ); PrisonRanks.getInstance().getRankManager().saveRank(rank); @@ -1486,6 +1510,9 @@ public void rankPlayer(CommandSender sender, } + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + + Map rankLadders = rankPlayer.getLadderRanks(); for ( RankLadder rankLadder : rankLadders.keySet() ) @@ -1495,7 +1522,8 @@ public void rankPlayer(CommandSender sender, Rank nextRank = rank.getRankNext(); // This calculates the target rank, and takes in to consideration the player's existing rank: - PlayerRank nextPRank = PlayerRank.getTargetPlayerRankForPlayer( rankPlayer, nextRank ); + PlayerRank nextPRank = pRank.getTargetPlayerRankForPlayer( rankPlayer, nextRank ); +// PlayerRank nextPRank = PlayerRank.getTargetPlayerRankForPlayer( rankPlayer, nextRank ); // PlayerRank nextPRank = nextRank == null ? null : // new PlayerRank( nextRank, pRank.getRankMultiplier() ); diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/PlayerRank.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/PlayerRank.java deleted file mode 100644 index a095bc354..000000000 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/PlayerRank.java +++ /dev/null @@ -1,114 +0,0 @@ -package tech.mcprison.prison.ranks.data; - -public class PlayerRank -{ - - private final Rank rank; - - private Double rankMultiplier = null; - private Double rankCost = null; - - public PlayerRank( Rank rank ) { - super(); - - this.rank = rank; - - double rankMultiplier = getLadderBasedRankMultiplier(); - - setRankCost( rankMultiplier ); -// this.rankCost = rank.getCost() * (1.0 + rankMultiplier); - } - - private PlayerRank( Rank rank, double rankMultiplier ) { - this( rank ); - - this.rankMultiplier = rankMultiplier; - - setRankCost( rankMultiplier ); -// this.rankCost = rank.getCost() * (1.0 + rankMultiplier); - } - - public void applyMultiplier( double rankMultiplier ) { - - this.rankMultiplier = rankMultiplier; - - setRankCost( rankMultiplier ); -// this.rankCost = rank.getCost() * (1.0 + rankMultiplier); - } - - private void setRankCost( double rankMultiplier ) { - - this.rankCost = rank.getCost() * (1.0 + rankMultiplier); - } - - public double getLadderBasedRankMultiplier() { - - return getLadderBaseRankdMultiplier( getRank() ); - } - - public static double getLadderBaseRankdMultiplier( Rank rank ) { - double rankMultiplier = 0; - - if ( rank != null && rank.getLadder() != null ) { - double ladderMultiplier = rank.getLadder().getRankCostMultiplierPerRank(); - - // Because it's zero based... so add a 1 - rankMultiplier = ladderMultiplier * (1 + rank.getPosition()); - } - - return rankMultiplier; - } - public static double getRawRankCost( Rank rank ) { - return rank.getCost(); - } - public static void setRawRankCost( Rank rank, double rawCost ) { - rank.setCost( rawCost ); - } - - public static PlayerRank getTargetPlayerRankForPlayer( RankPlayer player, Rank targetRank ) { - PlayerRank targetPlayerRank = null; - - if ( targetRank != null ) { - - double targetRankMultiplier = getLadderBaseRankdMultiplier( targetRank ); - - PlayerRank pRankForPLayer = player.getRank( targetRank.getLadder() ); - double existingRankMultiplier = pRankForPLayer == null ? 0 : - getLadderBaseRankdMultiplier( pRankForPLayer.getRank() ); - - // Get the player's total rankMultiplier from the default ladder - // because they will always have a rank there: - PlayerRank pRank = player.getRank( "default" ); - double playerMultipler = pRank == null ? 0 : pRank.getRankMultiplier(); - - // So the actual rank multiplier that needs to be used, is based upon the - // Player's current multiplier PLUS the multiplier for the target rank - // AND MINUS the multiplier for the current rank the player has within the - // target rank's ladder. - double rankMultiplier = playerMultipler + targetRankMultiplier - existingRankMultiplier; - - targetPlayerRank = new PlayerRank( targetRank, rankMultiplier ); - } - - return targetPlayerRank; - } - - public Rank getRank() { - return rank; - } - - public Double getRankMultiplier() { - return rankMultiplier; - } -// public void setRankMultiplier( Double rankMultiplier ) { -// this.rankMultiplier = rankMultiplier; -// } - - public Double getRankCost() { - return rankCost; - } -// public void setRankCost( Double rankCost ) { -// this.rankCost = rankCost; -// } - -} diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankFactory.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankFactory.java new file mode 100644 index 000000000..fc2c1769d --- /dev/null +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankFactory.java @@ -0,0 +1,139 @@ +package tech.mcprison.prison.ranks.data; + +import java.util.ArrayList; +import java.util.List; + +import tech.mcprison.prison.modules.ModuleElement; +import tech.mcprison.prison.output.Output; +import tech.mcprison.prison.store.Document; +import tech.mcprison.prison.util.ConversionUtil; + +public class RankFactory + extends RankMessages +{ + + @SuppressWarnings( "unchecked" ) + public Rank createRank( Document document ) + { + Rank rank = null; + + try + { + // Object pos = document.get("position"); + // this.position = RankUtil.doubleToInt( pos == null ? 0.0d : pos ); + + int id = ConversionUtil.doubleToInt( document.get( "id" ) ); + String name = (String) document.get( "name" ); + String tag = (String) document.get( "tag" ); + double cost = (double) document.get( "cost" ); + + rank = new Rank( id, name, tag, cost ); + + String currency = (String) document.get( "currency" ); + rank.setCurrency( (currency == null || "null".equalsIgnoreCase( currency ) ? null : currency) ); + + rank.getRankUpCommands().clear(); + Object cmds = document.get( "commands" ); + if ( cmds != null ) + { + + List commands = (List) cmds; + for ( String cmd : commands ) + { + if ( cmd != null ) + { + rank.getRankUpCommands().add( cmd ); + } + } + + // This was allowing nulls to be added to the live commands... + // this.rankUpCommands = (List) cmds; + } + + rank.getMines().clear(); + rank.getMineStrings().clear(); + Object minesObj = document.get( "mines" ); + if ( minesObj != null ) + { + List mineStrings = (List) minesObj; + rank.setMineStrings( mineStrings ); + } + + // getPermissions().clear(); + // Object perms = document.get( "permissions" ); + // if ( perms != null ) { + // List permissions = (List) perms; + // for ( String permission : permissions ) { + // getPermissions().add( permission ); + // } + // } + // + // + // getPermissionGroups().clear(); + // Object permsGroups = document.get( "permissionGroups" ); + // if ( perms != null ) { + // List permissionGroups = (List) permsGroups; + // for ( String permissionGroup : permissionGroups ) { + // getPermissionGroups().add( permissionGroup ); + // } + // } + + +// // Hook up the ladder if it has not been setup yet: +// if ( rank.getLadder() == null ) { +// +// RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder( rank ); +// +// rank.setLadder( ladder ); +// } + } + catch ( Exception e ) + { + String id = rank == null ? "(null rank)" : Integer.toString( rank.getId() ); + String rankName = rank.getName() == null ? "null" : rank.getName(); + String message = rankFailureLoadingRanksMsg( id, + rankName, e.getMessage() ); + + Output.get().logError( message ); + } + + return rank; + } + + public Document toDocument( Rank rank ) { + Document ret = new Document(); +// ret.put("position", this.position ); + ret.put("id", rank.getId()); + ret.put("name", rank.getName() ); + ret.put("tag", rank.getTag() ); + ret.put("cost", rank.getCost() ); + ret.put("currency", rank.getCurrency() ); + + List cmds = new ArrayList<>(); + for ( String cmd : rank.getRankUpCommands() ) { + // Filters out possible nulls: + if ( cmd != null ) { + cmds.add( cmd ); + } + } + ret.put("commands", cmds); + + List mineStrings = new ArrayList<>(); + if ( rank.getMines() != null ) { + for ( ModuleElement mine : rank.getMines() ) { + String mineString = mine.getModuleElementType() + "," + mine.getName() + "," + + mine.getId() + "," + mine.getTag(); + mineStrings.add( mineString ); + } + } + ret.put("mines", mineStrings); + +// ret.put( "permissions", getPermissions() ); +// ret.put( "permissionGroups", getPermissionGroups() ); + + return ret; + } + + + +} diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankLadderFactory.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankLadderFactory.java new file mode 100644 index 000000000..370e82f2e --- /dev/null +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankLadderFactory.java @@ -0,0 +1,145 @@ +package tech.mcprison.prison.ranks.data; + +import java.util.List; + +import com.google.gson.internal.LinkedTreeMap; + +import tech.mcprison.prison.ranks.PrisonRanks; +import tech.mcprison.prison.ranks.managers.RankManager; +import tech.mcprison.prison.store.Document; +import tech.mcprison.prison.util.ConversionUtil; + +public class RankLadderFactory +{ + + @SuppressWarnings( "unchecked" ) + public RankLadder createRankLadder(Document document, PrisonRanks prisonRanks) { + RankLadder rankLadder = null; + + boolean isDirty = false; + + int id = ConversionUtil.doubleToInt(document.get("id")); + String name = (String) document.get("name"); + + rankLadder = new RankLadder( id, name ); + + RankManager rankManager = prisonRanks.getRankManager(); + + if ( rankManager == null ) { + + RankMessages rMessages = new RankMessages(); + rMessages.rankFailureLoadingRankManagerMsg( name, id ); + + return null; + } + + List> ranksLocal = + (List>) document.get("ranks"); + + rankLadder.getRankUpCommands().clear(); + Object cmds = document.get("commands"); + if ( cmds != null ) { + + List commands = (List) cmds; + for ( String cmd : commands ) { + if ( cmd != null ) { + rankLadder.getRankUpCommands().add( cmd ); + } + } + + // This was allowing nulls to be added to the live commands... +// this.rankUpCommands = (List) cmds; + } + + +// rankLadder.ranks = new ArrayList<>(); // already initialized + for (LinkedTreeMap rank : ranksLocal) { + + + // The only real field that is important here is rankId to tie the + // rank back to this ladder. Name helps clarify the contents of the + // Ladder file. + int rRankId = ConversionUtil.doubleToInt((rank.get("rankId"))); + String rRankName = (String) rank.get( "rankName" ); + + Rank rankPrison = rankManager.getRank( rRankId ); + + if ( rankPrison != null && rankPrison.getLadder() != null ) { + + RankMessages rMessages = new RankMessages(); + rMessages.rankFailureLoadingDuplicateRankMsg( + rankPrison.getName(), rankPrison.getLadder().getName(), + rankLadder.getName() ); + + isDirty = true; + } + else if ( rankPrison != null) { + + rankLadder.addRank( rankPrison ); + +// Output.get().logInfo( "RankLadder load : " + getName() + +// " rank= " + rankPrison.getName() + " " + rankPrison.getId() + +// ); + +// // if null look it up from loaded ranks: +// if ( rRankName == null ) { +// rRankName = rankPrison.getName(); +// dirty = true; +// } + } + else { + // Rank not found. Try to create it? The name maybe wrong. + String rankName = rRankName != null && !rRankName.trim().isEmpty() ? + rRankName : "Rank " + rRankId; + + // NOTE: The following is valid use of getCost(): + double cost = rankLadder.getRanks().size() == 0 ? 0 : + rankLadder.getRanks().get( rankLadder.getRanks().size() - 1 ).getCost() * 3; + Rank newRank = new Rank( rRankId, rankName, null, cost ); + + rankLadder.addRank( newRank ); + +// String message = String.format( +// "Loading RankLadder Error: A rank for %s was not found so it was " + +// "fabricated: %s id=%d tag=%s cost=%d", getName(), newRank.getName(), newRank.getId(), +// newRank.getTag(), newRank.getCost() ); +// Output.get().logError( message ); + } + + } + +// this.maxPrestige = RankUtil.doubleToInt(document.get("maxPrestige")); + + + Double rankCostMultiplier = (Double) document.get( "rankCostMultiplierPerRank" ); + rankLadder.setRankCostMultiplierPerRank( rankCostMultiplier == null ? 0 : rankCostMultiplier ); + + +// getPermissions().clear(); +// Object perms = document.get( "permissions" ); +// if ( perms != null ) { +// List permissions = (List) perms; +// for ( String permission : permissions ) { +// getPermissions().add( permission ); +// } +// } +// +// +// getPermissionGroups().clear(); +// Object permsGroups = document.get( "permissionGroups" ); +// if ( perms != null ) { +// List permissionGroups = (List) permsGroups; +// for ( String permissionGroup : permissionGroups ) { +// getPermissionGroups().add( permissionGroup ); +// } +// } + + if ( isDirty ) { + PrisonRanks.getInstance().getLadderManager().save( rankLadder ); + } + + return rankLadder; + } + + +} diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankPlayerFactory.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankPlayerFactory.java new file mode 100644 index 000000000..65599df4c --- /dev/null +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankPlayerFactory.java @@ -0,0 +1,293 @@ +package tech.mcprison.prison.ranks.data; + +import java.util.ArrayList; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.UUID; + +import com.google.gson.internal.LinkedTreeMap; + +import tech.mcprison.prison.Prison; +import tech.mcprison.prison.output.Output; +import tech.mcprison.prison.ranks.FirstJoinHandlerMessages; +import tech.mcprison.prison.ranks.PrisonRanks; +import tech.mcprison.prison.ranks.events.FirstJoinEvent; +import tech.mcprison.prison.store.Document; +import tech.mcprison.prison.util.ConversionUtil; + +public class RankPlayerFactory +{ + + @SuppressWarnings( "unchecked" ) + public RankPlayer createRankPlayer(Document document) { + RankPlayer rankPlayer = null; + + + UUID uuid = UUID.fromString((String) document.get("uid")); + + rankPlayer = new RankPlayer( uuid ); + + LinkedTreeMap ranksLocal = + (LinkedTreeMap) document.get("ranks"); +// LinkedTreeMap prestigeLocal = +// (LinkedTreeMap) document.get("prestige"); + +// LinkedTreeMap blocksMinedLocal = +// (LinkedTreeMap) document.get("blocksMined"); + + Object namesListObject = document.get( "names" ); + + + for (String key : ranksLocal.keySet()) { + rankPlayer.getRanksRefs().put(key, ConversionUtil.doubleToInt(ranksLocal.get(key))); + } + +// for (String key : prestigeLocal.keySet()) { +// prestige.put(key, RankUtil.doubleToInt(prestigeLocal.get(key))); +// } + +//// rankPlayer.setBlocksMined( new HashMap<>() ); +// if ( blocksMinedLocal != null ) { +// for (String key : blocksMinedLocal.keySet()) { +// rankPlayer.getBlocksMined().put(key, ConversionUtil.doubleToInt(blocksMinedLocal.get(key))); +// } +// } + + if ( namesListObject != null ) { + + for ( Object rankPlayerNameMap : (ArrayList) namesListObject ) { + LinkedTreeMap rpnMap = (LinkedTreeMap) rankPlayerNameMap; + + if ( rpnMap.size() > 0 ) { + String name = (String) rpnMap.get( "name" ); + long date = ConversionUtil.doubleToLong( rpnMap.get( "date" ) ); + + RankPlayerName rankPlayerName = new RankPlayerName( name, date ); + rankPlayer.getNames().add( rankPlayerName ); +// Output.get().logInfo( "RankPlayer: uuid: " + uid + " RankPlayerName: " + rankPlayerName.toString() ); + } + + } + } + + return rankPlayer; + } + + public Document toDocument( RankPlayer rankPlayer ) { + Document ret = new Document(); + ret.put("uid", rankPlayer.getUUID()); + ret.put("ranks", rankPlayer.getRanksRefs() ); +// ret.put("prestige", this.prestige); + + ret.put("names", rankPlayer.getNames()); + +// ret.put("blocksMined", rankPlayer.getBlocksMined() ); + return ret; + } + + + + /** + *

This function will check to see if the player is on the default rank on + * the default ladder. If not, then it will add them. + *

+ * + *

This is safe to run on anyone, even if they already are on the default ladder. + *

+ * + *

Note, this will not save the player's new rank. The save function must be + * managed and called outside of this. + *

+ */ + public void firstJoin( RankPlayer rankPlayer) { + + RankLadder defaultLadder = PrisonRanks.getInstance().getDefaultLadder(); + + if ( !rankPlayer.getLadderRanks().containsKey( defaultLadder ) ) { + + Optional firstRank = defaultLadder.getLowestRank(); + + if ( firstRank.isPresent() ) { + Rank rank = firstRank.get(); + + rankPlayer.addRank( rank ); + + Prison.get().getEventBus().post(new FirstJoinEvent( rankPlayer )); + + FirstJoinHandlerMessages messages = new FirstJoinHandlerMessages(); + Output.get().logWarn( messages.firstJoinSuccess( rankPlayer.getName() ) ); + + } else { + + FirstJoinHandlerMessages messages = new FirstJoinHandlerMessages(); + Output.get().logWarn( messages.firstJoinWarningNoRanksOnServer() ); + } + } + + } + + + /** + * Removes a ladder from this player, including whichever rank this player had in it. + * Cannot remove the default ladder. + * + * @param ladderName The ladder's name. + */ + public boolean removeLadder( RankPlayer rankPlayer, String ladderName ) { + boolean results = false; + if ( !ladderName.equalsIgnoreCase("default") ) { + Integer id = rankPlayer.getRanksRefs().remove(ladderName); + results = (id != null); + + RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder( ladderName ); + if ( ladder != null && !ladder.getName().equalsIgnoreCase( "default" ) ) { + rankPlayer.getLadderRanks().remove( ladder ); + } + } + + return results; + } + + /** + * Retrieves the rank that this player has in a certain ladder, if any. + * + * @param ladder The ladder to check. + * @return An optional containing the {@link Rank} if found, or empty if there isn't a rank by that ladder for this player. + */ + public PlayerRank getRank( RankPlayer rankPlayer, RankLadder ladder ) { + PlayerRank results = null; + + if ( ladder != null ) { + + Set keys = rankPlayer.getLadderRanks().keySet(); + for ( RankLadder key : keys ) + { + if ( key != null && key.getName().equalsIgnoreCase( ladder.getName() ) ) { + results = rankPlayer.getLadderRanks().get( key ); + } + } + } + + return results; + +// if (!ranksRefs.containsKey(ladder.getName())) { +// return null; +// } +// int id = ranksRefs.get(ladder.getName()); +// return PrisonRanks.getInstance().getRankManager().getRank(id); + } + + + /** + * Returns all ladders this player is a part of, along with each rank the player has in that ladder. + * + * @return The map containing this data. + */ + public Map getLadderRanks( RankPlayer rankPlayer ) { + + if ( rankPlayer.getLadderRanks().isEmpty() && !rankPlayer.getRanksRefs().isEmpty() ) { + + //Map ret = new HashMap<>(); + + for (Map.Entry entry : rankPlayer.getRanksRefs().entrySet()) { + RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder(entry.getKey()); + + if ( ladder == null ) { + continue; // Skip it + } + + Rank rank = PrisonRanks.getInstance().getRankManager().getRank(entry.getValue()); + if ( rank == null ) { + continue; // Skip it + } + + PlayerRank pRank = new PlayerRank( rank ); + + rankPlayer.getLadderRanks().put(ladder, pRank); + } + + // Need to recalculate all rank multipliers: + rankPlayer.recalculateRankMultipliers(); + } + + return rankPlayer.getLadderRanks(); + } + + + + /** + * Retrieves the rank that this player has the specified ladder. + * + * @param ladder The ladder name to check. + * @return The {@link Rank} if found, otherwise null; + */ + public PlayerRank getRank( RankPlayer rankPlayer, String ladderName ) { + + RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder( ladderName ); + return getRank( rankPlayer, ladder ); + +// Rank results = null; +// if (ladder != null && ranksRefs.containsKey(ladder)) { +// int id = ranksRefs.get(ladder); +// results = PrisonRanks.getInstance().getRankManager().getRank(id); +// } +// return results; + } + + + public PlayerRank createPlayerRank( Rank rank ) { + PlayerRank results = new PlayerRank( rank ); + + double rankMultiplier = results.getLadderBasedRankMultiplier( rank ); + + results.setRankCost( rankMultiplier ); + + return results; + } + + private PlayerRank createPlayerRank( Rank rank, double rankMultiplier ) { + PlayerRank results = new PlayerRank( rank, rankMultiplier ); + + return results; + } + + public PlayerRank getTargetPlayerRankForPlayer( PlayerRank playerRank, + RankPlayer player, Rank targetRank ) { + PlayerRank targetPlayerRank = null; + + if ( targetRank != null ) { + + double targetRankMultiplier = playerRank.getLadderBasedRankMultiplier( targetRank ); + + PlayerRank pRankForPLayer = getRank( player, targetRank.getLadder() ); + double existingRankMultiplier = pRankForPLayer == null ? 0 : + playerRank.getLadderBasedRankMultiplier( pRankForPLayer.getRank() ); + + // Get the player's total rankMultiplier from the default ladder + // because they will always have a rank there: + PlayerRank pRank = getRank( player, "default" ); + double playerMultipler = pRank == null ? 0 : pRank.getRankMultiplier(); + + // So the actual rank multiplier that needs to be used, is based upon the + // Player's current multiplier PLUS the multiplier for the target rank + // AND MINUS the multiplier for the current rank the player has within the + // target rank's ladder. + double rankMultiplier = playerMultipler + targetRankMultiplier - existingRankMultiplier; + + targetPlayerRank = createPlayerRank( targetRank, rankMultiplier ); + } + + return targetPlayerRank; + } + + + public double getRawRankCost( Rank rank ) { + return rank.getCost(); + } + public void setRawRankCost( Rank rank, double rawCost ) { + rank.setCost( rawCost ); + } + + +} diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/top/RankPlayerSortableLadderRankBalance.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankPlayerSortableLadderRankBalance.java similarity index 90% rename from prison-ranks/src/main/java/tech/mcprison/prison/ranks/top/RankPlayerSortableLadderRankBalance.java rename to prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankPlayerSortableLadderRankBalance.java index 78e8858d1..a0505eb78 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/top/RankPlayerSortableLadderRankBalance.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankPlayerSortableLadderRankBalance.java @@ -1,12 +1,8 @@ -package tech.mcprison.prison.ranks.top; +package tech.mcprison.prison.ranks.data; import java.util.Comparator; import tech.mcprison.prison.ranks.PrisonRanks; -import tech.mcprison.prison.ranks.data.PlayerRank; -import tech.mcprison.prison.ranks.data.Rank; -import tech.mcprison.prison.ranks.data.RankLadder; -import tech.mcprison.prison.ranks.data.RankPlayer; public class RankPlayerSortableLadderRankBalance implements Comparator @@ -85,10 +81,16 @@ else if ( rp2 == null ) { results = 1; } else { - Rank r1 = rp1.getRank( getLadder() ) == null ? - null : rp1.getRank( getLadder() ).getRank(); - Rank r2 = rp2.getRank( getLadder() ) == null ? - null : rp2.getRank( getLadder() ).getRank(); + + RankLadder targetLadder = getLadder(); + + PlayerRank pr1 = rp1.getLadderRanks().get( targetLadder ); + PlayerRank pr2 = rp2.getLadderRanks().get( targetLadder ); + + Rank r1 = pr1 == null ? + null : pr1.getRank(); + Rank r2 = pr2 == null ? + null : pr2.getRank(); if ( r1 == null ) { results = -1; @@ -159,10 +161,11 @@ private double calculateTopScore( RankPlayer rp1, Rank rank, double balance ) { if ( balance != 0 ) { Rank nextRank = rank.getRankNext(); - PlayerRank pRank = rp1.getRank( rank.getLadder() ); + PlayerRank pRank = rp1.getLadderRanks().get( rank.getLadder() ); +// PlayerRank pRank = rp1.getRank( rank.getLadder() ); // This calculates the target rank, and takes in to consideration the player's existing rank: - PlayerRank pRankNext = PlayerRank.getTargetPlayerRankForPlayer( rp1, nextRank ); + PlayerRank pRankNext = pRank.getTargetPlayerRankForPlayer( rp1, nextRank ); // PlayerRank pRankNext = nextRank == null ? null : // new PlayerRank( nextRank, pRank.getRankMultiplier() ); diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/LadderManager.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/LadderManager.java index dced2b207..821d34951 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/LadderManager.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/LadderManager.java @@ -26,7 +26,9 @@ import tech.mcprison.prison.ranks.PrisonRanks; import tech.mcprison.prison.ranks.data.Rank; import tech.mcprison.prison.ranks.data.RankLadder; +import tech.mcprison.prison.ranks.data.RankLadderFactory; import tech.mcprison.prison.ranks.data.RankPlayer; +import tech.mcprison.prison.ranks.data.RankPlayerFactory; import tech.mcprison.prison.store.Collection; import tech.mcprison.prison.store.Document; @@ -74,8 +76,12 @@ public LadderManager(Collection collection, PrisonRanks prisonRanks) { * @throws IOException If the file could not be read or does not exist. */ public void loadLadder(String fileKey) throws IOException { - Document doc = collection.get(fileKey).orElseThrow(IOException::new); - RankLadder ladder = new RankLadder(doc, prisonRanks); + + Document doc = collection.get(fileKey).orElseThrow(IOException::new); + + RankLadderFactory rlFactory = new RankLadderFactory(); + + RankLadder ladder = rlFactory.createRankLadder(doc, prisonRanks); loadedLadders.add(ladder); // Will be dirty if load a ladder and the rank name does not exist and it adds them: @@ -91,7 +97,11 @@ public void loadLadder(String fileKey) throws IOException { */ public void loadLadders() throws IOException { List documents = collection.getAll(); - documents.forEach(document -> loadedLadders.add(new RankLadder(document, prisonRanks))); + + final RankLadderFactory rlFactory = new RankLadderFactory(); + + documents.forEach(document -> loadedLadders.add( + rlFactory.createRankLadder(document, prisonRanks)) ); for ( RankLadder ladder : loadedLadders ) { // Will be dirty if load a ladder and the rank name does not exist and it adds them: @@ -220,8 +230,11 @@ public boolean removeLadder(RankLadder ladder) { .stream() .filter(rankPlayer -> rankPlayer.hasLadder(ladder.getName())) .collect(Collectors.toList()); + + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + for (RankPlayer player : playersWithLadder) { - player.removeLadder(ladder.getName()); + rankPlayerFactory.removeLadder( player, ladder.getName() ); } // Remove it from the list... diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/PlayerManager.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/PlayerManager.java index 9412847e4..14f70a27a 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/PlayerManager.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/PlayerManager.java @@ -50,6 +50,7 @@ import tech.mcprison.prison.ranks.data.Rank; import tech.mcprison.prison.ranks.data.RankLadder; import tech.mcprison.prison.ranks.data.RankPlayer; +import tech.mcprison.prison.ranks.data.RankPlayerFactory; import tech.mcprison.prison.store.Collection; import tech.mcprison.prison.store.Document; import tech.mcprison.prison.tasks.PrisonTaskSubmitter; @@ -98,7 +99,10 @@ public PlayerManager(Collection collection) { */ public void loadPlayer(String playerFile) throws IOException { Document document = collection.get(playerFile).orElseThrow(IOException::new); - RankPlayer rankPlayer = new RankPlayer(document); + + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + + RankPlayer rankPlayer = rankPlayerFactory.createRankPlayer(document); players.add( rankPlayer ); @@ -119,10 +123,13 @@ public void loadPlayer(String playerFile) throws IOException { */ public void loadPlayers() throws IOException { List players = collection.getAll(); + + final RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + players.forEach( document -> this.players.add( - new RankPlayer(document))); + rankPlayerFactory.createRankPlayer(document) )); } /** @@ -134,7 +141,10 @@ public void loadPlayers() throws IOException { * @see #savePlayer(RankPlayer) To save with the default conventional filename. */ public void savePlayer(RankPlayer player, String playerFile) throws IOException { - collection.save(playerFile, player.toDocument()); + + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + + collection.save(playerFile, rankPlayerFactory.toDocument( player ) ); // collection.insert(playerFile, player.toDocument()); } @@ -327,11 +337,13 @@ protected RankPlayer addPlayerSyncTask( UUID uid, String playerName ) { if ( !getPlayersByName().containsKey( playerName ) ) { + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + // We need to create a new player data file. newPlayer = new RankPlayer( uid, playerName ); newPlayer.checkName( playerName ); - newPlayer.firstJoin(); + rankPlayerFactory.firstJoin( newPlayer ); players.add(newPlayer); getPlayersByName().put( playerName, newPlayer ); @@ -479,9 +491,12 @@ public List getPlayerNextRanks( RankPlayer rankPlayer ) { List results = new ArrayList<>(); if ( !rankPlayer.getLadderRanks().isEmpty()) { + + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + for ( RankLadder ladder : rankPlayer.getLadderRanks().keySet() ) { - Rank rank = rankPlayer.getRank( ladder ).getRank(); + Rank rank = rankPlayerFactory.getRank( rankPlayer, ladder ).getRank(); if ( rank != null && rank.getRankNext() != null ) { Rank nextRank = rank.getRankNext(); @@ -500,17 +515,19 @@ public String getPlayerNextRankCost( RankPlayer rankPlayer, String ladderName, if ( !rankPlayer.getLadderRanks().isEmpty()) { DecimalFormat dFmt = new DecimalFormat("#,##0"); + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + for ( RankLadder ladder : rankPlayer.getLadderRanks().keySet() ) { if ( ladderName == null || ladderName != null && ladder.getName().equalsIgnoreCase( ladderName )) { - PlayerRank pRank = rankPlayer.getRank( ladder ); + PlayerRank pRank = rankPlayerFactory.getRank( rankPlayer, ladder ); if ( pRank != null && pRank.getRank().getRankNext() != null ) { Rank nextRank = pRank.getRank().getRankNext(); // This calculates the target rank, and takes in to consideration the player's existing rank: - PlayerRank nextPRank = PlayerRank.getTargetPlayerRankForPlayer( rankPlayer, nextRank ); + PlayerRank nextPRank = pRank.getTargetPlayerRankForPlayer( rankPlayer, nextRank ); //PlayerRank nextPRank = new PlayerRank( nextRank, pRank.getRankMultiplier() ); @@ -560,17 +577,19 @@ public String getPlayerNextRankCostPercent( RankPlayer rankPlayer, String ladder if ( !rankPlayer.getLadderRanks().isEmpty()) { DecimalFormat dFmt = new DecimalFormat("#,##0"); + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + for ( RankLadder ladder : rankPlayer.getLadderRanks().keySet() ) { if ( ladderName == null || ladderName != null && ladder.getName().equalsIgnoreCase( ladderName )) { - PlayerRank pRank = rankPlayer.getRank( ladder ); + PlayerRank pRank = rankPlayerFactory.getRank( rankPlayer, ladder ); if ( pRank != null && pRank.getRank().getRankNext() != null ) { Rank nextRank = pRank.getRank().getRankNext(); // This calculates the target rank, and takes in to consideration the player's existing rank: - PlayerRank nextPRank = PlayerRank.getTargetPlayerRankForPlayer( rankPlayer, nextRank ); + PlayerRank nextPRank = pRank.getTargetPlayerRankForPlayer( rankPlayer, nextRank ); // PlayerRank nextPRank = new PlayerRank( nextRank, pRank.getRankMultiplier() ); @@ -618,19 +637,21 @@ public String getPlayerNextRankCostBar( RankPlayer rankPlayer, String ladderName if ( !rankPlayer.getLadderRanks().isEmpty()) { // DecimalFormat dFmt = new DecimalFormat("#,##0.00"); + + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); for ( RankLadder ladder : rankPlayer.getLadderRanks().keySet() ) { if ( ladderName == null || ladderName != null && ladder.getName().equalsIgnoreCase( ladderName )) { - PlayerRank pRank = rankPlayer.getRank( ladder ); + PlayerRank pRank = rankPlayerFactory.getRank( rankPlayer, ladder ); Rank rank = pRank.getRank(); if ( rank != null && rank.getRankNext() != null ) { Rank nextRank = rank.getRankNext(); // This calculates the target rank, and takes in to consideration the player's existing rank: - PlayerRank nextPRank = PlayerRank.getTargetPlayerRankForPlayer( rankPlayer, nextRank ); + PlayerRank nextPRank = pRank.getTargetPlayerRankForPlayer( rankPlayer, nextRank ); // PlayerRank nextPRank = new PlayerRank( nextRank, pRank.getRankMultiplier() ); @@ -687,19 +708,21 @@ public String getPlayerNextRankCostRemaining( RankPlayer rankPlayer, String ladd if ( !rankPlayer.getLadderRanks().isEmpty()) { DecimalFormat dFmt = new DecimalFormat("#,##0"); + + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); for ( RankLadder ladder : rankPlayer.getLadderRanks().keySet() ) { if ( ladderName == null || ladderName != null && ladder.getName().equalsIgnoreCase( ladderName )) { - PlayerRank pRank = rankPlayer.getRank( ladder ); + PlayerRank pRank = rankPlayerFactory.getRank( rankPlayer, ladder ); Rank rank = pRank.getRank(); if ( rank != null && rank.getRankNext() != null ) { Rank nextRank = rank.getRankNext(); // This calculates the target rank, and takes in to consideration the player's existing rank: - PlayerRank nextPRank = PlayerRank.getTargetPlayerRankForPlayer( rankPlayer, nextRank ); + PlayerRank nextPRank = pRank.getTargetPlayerRankForPlayer( rankPlayer, nextRank ); // PlayerRank nextPRank = new PlayerRank( nextRank, pRank.getRankMultiplier() ); @@ -762,18 +785,20 @@ public String getPlayerNextRankCostRemainingPercent( RankPlayer rankPlayer, Stri if ( !rankPlayer.getLadderRanks().isEmpty()) { DecimalFormat dFmt = new DecimalFormat("#,##0"); + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + for ( RankLadder ladder : rankPlayer.getLadderRanks().keySet() ) { if ( ladderName == null || ladderName != null && ladder.getName().equalsIgnoreCase( ladderName )) { - PlayerRank pRank = rankPlayer.getRank( ladder ); + PlayerRank pRank = rankPlayerFactory.getRank( rankPlayer, ladder ); Rank rank = pRank.getRank(); if ( rank != null && rank.getRankNext() != null ) { Rank nextRank = rank.getRankNext(); // This calculates the target rank, and takes in to consideration the player's existing rank: - PlayerRank nextPRank = PlayerRank.getTargetPlayerRankForPlayer( rankPlayer, nextRank ); + PlayerRank nextPRank = pRank.getTargetPlayerRankForPlayer( rankPlayer, nextRank ); // PlayerRank nextPRank = new PlayerRank( nextRank, pRank.getRankMultiplier() ); @@ -828,19 +853,21 @@ public String getPlayerNextRankCostRemainingBar( RankPlayer rankPlayer, String l if ( !rankPlayer.getLadderRanks().isEmpty()) { // DecimalFormat dFmt = new DecimalFormat("#,##0"); + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + for ( RankLadder ladder : rankPlayer.getLadderRanks().keySet() ) { if ( ladderName == null || ladderName != null && ladder.getName().equalsIgnoreCase( ladderName )) { - PlayerRank pRank = rankPlayer.getRank( ladder ); + PlayerRank pRank = rankPlayerFactory.getRank( rankPlayer, ladder ); Rank rank = pRank.getRank(); if ( rank != null && rank.getRankNext() != null ) { Rank nextRank = rank.getRankNext(); // This calculates the target rank, and takes in to consideration the player's existing rank: - PlayerRank nextPRank = PlayerRank.getTargetPlayerRankForPlayer( rankPlayer, nextRank ); + PlayerRank nextPRank = pRank.getTargetPlayerRankForPlayer( rankPlayer, nextRank ); // PlayerRank nextPRank = new PlayerRank( nextRank, pRank.getRankMultiplier() ); @@ -913,12 +940,14 @@ private String getPlayerBalance( RankPlayer rankPlayer, String ladderName, if ( !rankPlayer.getLadderRanks().isEmpty()) { DecimalFormat dFmt = new DecimalFormat("#,##0"); + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + for ( RankLadder ladder : rankPlayer.getLadderRanks().keySet() ) { if ( ladderName == null || ladderName != null && ladder.getName().equalsIgnoreCase( ladderName )) { - PlayerRank pRank = rankPlayer.getRank( ladder ); + PlayerRank pRank = rankPlayerFactory.getRank( rankPlayer, ladder ); Rank rank = pRank.getRank(); if ( rank != null ) { if ( sb.length() > 0 ) { @@ -1036,12 +1065,15 @@ public String getPlayerNextRankName( RankPlayer rankPlayer, String ladderName ) StringBuilder sb = new StringBuilder(); if ( !rankPlayer.getLadderRanks().isEmpty()) { + + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + for ( RankLadder ladder : rankPlayer.getLadderRanks().keySet() ) { if ( ladderName == null || ladderName != null && ladder.getName().equalsIgnoreCase( ladderName )) { - PlayerRank pRank = rankPlayer.getRank( ladder ); + PlayerRank pRank = rankPlayerFactory.getRank( rankPlayer, ladder ); Rank rank = pRank.getRank(); if ( rank != null && rank.getRankNext() != null ) { @@ -1064,12 +1096,14 @@ public String getPlayerNextRankTag( RankPlayer rankPlayer, String ladderName ) { if ( !rankPlayer.getLadderRanks().isEmpty()) { + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + for ( RankLadder ladder : rankPlayer.getLadderRanks().keySet() ) { if ( ladderName == null || ladderName != null && ladder.getName().equalsIgnoreCase( ladderName )) { - PlayerRank pRank = rankPlayer.getRank( ladder ); + PlayerRank pRank = rankPlayerFactory.getRank( rankPlayer, ladder ); Rank rank = pRank.getRank(); if ( rank != null && rank.getRankNext() != null ) { Rank nextRank = rank.getRankNext(); @@ -1233,7 +1267,8 @@ public String getTranslatePlayerPlaceHolder( UUID playerUuid, String playerName, case prison_rlp_laddername: { // rank may be null: - PlayerRank pRank = rankPlayer.getRank( ladderName ); + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + PlayerRank pRank = rankPlayerFactory.getRank( rankPlayer, ladderName ); if ( pRank != null ) { Rank rank = pRank.getRank(); diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/RankManager.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/RankManager.java index c2d93b33c..3f8d7ccdf 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/RankManager.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/RankManager.java @@ -48,8 +48,10 @@ import tech.mcprison.prison.ranks.commands.RanksCommands; import tech.mcprison.prison.ranks.data.PlayerRank; import tech.mcprison.prison.ranks.data.Rank; +import tech.mcprison.prison.ranks.data.RankFactory; import tech.mcprison.prison.ranks.data.RankLadder; import tech.mcprison.prison.ranks.data.RankPlayer; +import tech.mcprison.prison.ranks.data.RankPlayerFactory; import tech.mcprison.prison.ranks.data.StatsRankPlayerBalanceData; import tech.mcprison.prison.store.Collection; import tech.mcprison.prison.store.Document; @@ -179,7 +181,9 @@ private void resetRankPositions( Rank rank ) { public void loadRank(String rankFile) throws IOException { Document document = collection.get(rankFile).orElseThrow(IOException::new); - addRank( new Rank(document) ); + RankFactory rankFactory = new RankFactory(); + + addRank( rankFactory.createRank( document ) ); // loadedRanks.add(new Rank(document)); } @@ -191,9 +195,12 @@ public void loadRank(String rankFile) throws IOException { */ public void loadRanks() throws IOException { List ranks = collection.getAll(); + + RankFactory rankFactory = new RankFactory(); for ( Document rankDocument : ranks ) { - Rank rank = new Rank( rankDocument ); + + Rank rank = rankFactory.createRank( rankDocument ); addRank( rank ); } @@ -208,7 +215,10 @@ public void loadRanks() throws IOException { * @param saveFile The key to write the rank as. Case sensitive. */ public void saveRank(Rank rank, String saveFile) { - collection.save(saveFile, rank.toDocument()); + + RankFactory rankFactory = new RankFactory(); + + collection.save(saveFile, rankFactory.toDocument( rank ) ); } /** @@ -348,9 +358,11 @@ public boolean removeRank(Rank rank) { // for (RankLadder ladder : PrisonRanks.getInstance().getLadderManager() .getLadder( rank )) { + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + // Move each player in this ladder to the new rank PrisonRanks.getInstance().getPlayerManager().getPlayers().forEach(rankPlayer -> { - PlayerRank pRank = rankPlayer.getRank(ladder); + PlayerRank pRank = rankPlayerFactory.getRank( rankPlayer, ladder ); if ( pRank != null && pRank.getRank() != null ) { Rank curRank = pRank.getRank(); @@ -640,7 +652,7 @@ private void rankByLadderOutput( CommandSender sender, String ranksByLadder ) { private String getRankCost( Rank rank, PlaceholderAttribute attribute, boolean formatted ) { - double cost = PlayerRank.getRawRankCost( rank ); + double cost = rank.getRawRankCost(); String resultsx = null; DecimalFormat dFmt = new DecimalFormat("#,##0"); @@ -788,7 +800,11 @@ public String getTranslateRanksPlaceHolder( PlaceHolderKey placeHolderKey, case prison_rank__cost_multiplier_rankname: case prison_r_cm_rankname: - results = Double.toString( PlayerRank.getLadderBaseRankdMultiplier( rank ) ); + + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + PlayerRank pRank = rankPlayerFactory.createPlayerRank( rank ); + + results = Double.toString( pRank.getLadderBasedRankMultiplier() ); break; @@ -1044,7 +1060,10 @@ private double calculateRankCost( RankPlayer rankPlayer, Rank rank ) { double cost = 0; // Get player's rank: - PlayerRank playerRank = rankPlayer.getRank( rank.getLadder() ); + + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + + PlayerRank playerRank = rankPlayerFactory.getRank( rankPlayer, rank.getLadder() ); if ( playerRank != null ) { @@ -1062,7 +1081,9 @@ private double calculateRankCost( RankPlayer rankPlayer, Rank rank ) nextRank.getPosition() < rank.getPosition() ) { // Need to calculate the next PlayerRank value for the next rank: - playerRank = new PlayerRank(nextRank); + + playerRank = rankPlayerFactory.createPlayerRank( nextRank ); +// playerRank = new PlayerRank(nextRank); cost += playerRank.getRankCost(); nextRank = nextRank.getRankNext(); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java index b5169cb00..0b248d0f0 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java @@ -86,6 +86,7 @@ import tech.mcprison.prison.ranks.data.PlayerRank; import tech.mcprison.prison.ranks.data.Rank; import tech.mcprison.prison.ranks.data.RankPlayer; +import tech.mcprison.prison.ranks.data.RankPlayerFactory; import tech.mcprison.prison.ranks.managers.PlayerManager; import tech.mcprison.prison.ranks.managers.RankManager; import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerBlockBreakEvents; @@ -1260,8 +1261,10 @@ public ModuleElement getPlayerDefaultMine( tech.mcprison.prison.internal.Command Player player = pm.getPlayer( sender ); RankPlayer rankPlayer = pm.getPlayer( player ); - if ( rankPlayer != null && rankPlayer.getRank( "default" ) != null ) { - PlayerRank pRank = rankPlayer.getRank( "default" ); + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + + if ( rankPlayer != null && rankPlayerFactory.getRank( rankPlayer, "default" ) != null ) { + PlayerRank pRank = rankPlayerFactory.getRank( rankPlayer, "default" ); Rank rank = pRank.getRank(); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java index fcb10bf7f..aead713c0 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java @@ -39,6 +39,7 @@ import tech.mcprison.prison.ranks.data.Rank; import tech.mcprison.prison.ranks.data.RankLadder; import tech.mcprison.prison.ranks.data.RankPlayer; +import tech.mcprison.prison.ranks.data.RankPlayerFactory; import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.SpigotUtil; import tech.mcprison.prison.spigot.backpacks.BackpacksUtil; @@ -1799,7 +1800,10 @@ private void rankManagerGUI(InventoryClickEvent e, Player p, String[] parts) { // Check and open a GUI. if(rank != null) { RankPlayer rankPlayer = PrisonRanks.getInstance().getPlayerManager().getPlayer( new SpigotPlayer(p) ); - PlayerRank pRank = rankPlayer.getRank( rank.getLadder() ); + + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + + PlayerRank pRank = rankPlayerFactory.getRank( rankPlayer, rank.getLadder() ); SpigotRankPriceGUI gui = new SpigotRankPriceGUI(p, pRank.getRankCost().intValue(), rank.getName()); gui.open(); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerPrestigesGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerPrestigesGUI.java index 7efb64069..44f2b34b0 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerPrestigesGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerPrestigesGUI.java @@ -18,6 +18,7 @@ import tech.mcprison.prison.ranks.data.Rank; import tech.mcprison.prison.ranks.data.RankLadder; import tech.mcprison.prison.ranks.data.RankPlayer; +import tech.mcprison.prison.ranks.data.RankPlayerFactory; import tech.mcprison.prison.ranks.managers.LadderManager; import tech.mcprison.prison.ranks.managers.PlayerManager; import tech.mcprison.prison.spigot.SpigotPrison; @@ -132,7 +133,8 @@ public void open() { } Rank rank = ladder.getLowestRank().get(); - PlayerRank prestigePlayerRank = getRankPlayer().getRank("prestiges"); + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + PlayerRank prestigePlayerRank = rankPlayerFactory.getRank( getRankPlayer(), "prestiges"); Rank playerRank = prestigePlayerRank == null ? null : prestigePlayerRank.getRank(); XMaterial materialHas; XMaterial materialHasNot; @@ -165,7 +167,8 @@ public void open() { // Need to create a new PlayerRank specifically for the player which takes in to consideration // all of their multipliers. - PlayerRank targetPlayerRank = PlayerRank.getTargetPlayerRankForPlayer( rankPlayer, rank ); + PlayerRank pRank = rankPlayerFactory.createPlayerRank( rank ); + PlayerRank targetPlayerRank = pRank.getTargetPlayerRankForPlayer( rankPlayer, rank ); double cost = targetPlayerRank == null ? -1 : targetPlayerRank.getRankCost(); ButtonLore ranksLore = new ButtonLore(loreInfo, lorePrice3 + cost ); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerRanksGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerRanksGUI.java index 4b7b320fa..63d481874 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerRanksGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerRanksGUI.java @@ -22,6 +22,7 @@ import tech.mcprison.prison.ranks.data.Rank; import tech.mcprison.prison.ranks.data.RankLadder; import tech.mcprison.prison.ranks.data.RankPlayer; +import tech.mcprison.prison.ranks.data.RankPlayerFactory; import tech.mcprison.prison.ranks.managers.LadderManager; import tech.mcprison.prison.ranks.managers.PlayerManager; import tech.mcprison.prison.spigot.SpigotPrison; @@ -125,8 +126,9 @@ public void open() { int dimension = (int) (Math.ceil(ladder.getRanks().size() / 9D) * 9) + 9; // Get many parameters + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); Rank rank = ladder.getLowestRank().get(); - PlayerRank playerRankRank = getRankPlayer().getRank(guiConfig.getString("Options.Ranks.Ladder")); + PlayerRank playerRankRank = rankPlayerFactory.getRank( getRankPlayer(), guiConfig.getString("Options.Ranks.Ladder")); Rank playerRank = playerRankRank == null ? null : playerRankRank.getRank(); @@ -152,7 +154,7 @@ public void open() { ButtonLore ranksLore = new ButtonLore(); for (String stringValue : configCustomLore) { - PlayerRank pRank = getRankPlayer().getRank( rank.getLadder() ); + PlayerRank pRank = rankPlayerFactory.getRank( getRankPlayer(), rank.getLadder() ); stringValue = stringValue.replace("{rankPrice}", PlaceholdersUtil.formattedKmbtSISize(pRank.getRankCost(), formatDecimal, "")); stringValue = stringValue.replace("{rankName}", rank.getName()); stringValue = stringValue.replace("{rankTag}", SpigotPrison.format(rank.getTag())); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankManagerGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankManagerGUI.java index c8a1a034d..0225ab274 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankManagerGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRankManagerGUI.java @@ -11,6 +11,7 @@ import tech.mcprison.prison.ranks.data.PlayerRank; import tech.mcprison.prison.ranks.data.Rank; import tech.mcprison.prison.ranks.data.RankPlayer; +import tech.mcprison.prison.ranks.data.RankPlayerFactory; import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; @@ -47,8 +48,10 @@ public void open() { // Decimal Rank cost format. DecimalFormat formatDecimal = new DecimalFormat("###,##0.00"); + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + RankPlayer rankPlayer = PrisonRanks.getInstance().getPlayerManager().getPlayer( new SpigotPlayer(p) ); - PlayerRank pRank = rankPlayer.getRank( rank.getLadder() ); + PlayerRank pRank = rankPlayerFactory.getRank( rankPlayer, rank.getLadder() ); String rankCost; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRanksGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRanksGUI.java index d9fff77be..dc651c09d 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRanksGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotRanksGUI.java @@ -10,7 +10,6 @@ import tech.mcprison.prison.output.Output; import tech.mcprison.prison.placeholders.PlaceholdersUtil; -import tech.mcprison.prison.ranks.data.PlayerRank; import tech.mcprison.prison.ranks.data.Rank; import tech.mcprison.prison.ranks.data.RankLadder; import tech.mcprison.prison.spigot.SpigotPrison; @@ -79,7 +78,7 @@ public void open(){ Rank rank = ladder.get().getRanks().get(i); // Can only use the raw rank costs since this is not tied to a player: - double rawRankCost = PlayerRank.getRawRankCost( rank ); + double rawRankCost = rank.getRawRankCost(); // NOTE: The following ladderBaseRankMultiplier is just for the current ladder, but the player's // adjusted rank cost is the sum of all ladder's multipliers applied to each raw rank cost. // double ladderBaseRankMultiplier = PlayerRank.getLadderBaseRankdMultiplier( rank ); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java index 3d7cec949..b955e6102 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/sellall/SellAllUtil.java @@ -22,6 +22,7 @@ import tech.mcprison.prison.ranks.data.PlayerRank; import tech.mcprison.prison.ranks.data.Rank; import tech.mcprison.prison.ranks.data.RankPlayer; +import tech.mcprison.prison.ranks.data.RankPlayerFactory; import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.backpacks.BackpacksUtil; import tech.mcprison.prison.spigot.block.SpigotItemStack; @@ -262,8 +263,11 @@ public double getPlayerMultiplier(Player p){ if (rankPlugin.getPlayerManager().getPlayer(sPlayer) != null) { String playerRankName; try { + + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + RankPlayer rankPlayer = rankPlugin.getPlayerManager().getPlayer(sPlayer); - PlayerRank pRank = rankPlayer == null ? null : rankPlayer.getRank("prestiges"); + PlayerRank pRank = rankPlayer == null ? null : rankPlayerFactory.getRank( rankPlayer, "prestiges"); Rank rank = pRank == null ? null : pRank.getRank(); playerRankName = rank == null ? null : rank.getName(); From 5c820aaea0f19f55c4f16b71154ca4e3f4253daf Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Tue, 30 Nov 2021 07:54:05 -0500 Subject: [PATCH 171/283] Rank data refactoring. A few changes to get this working. The ladderRanks collection was not being setup was the main issue. --- docs/changelog_v3.3.x.md | 13 ++- .../prison/ranks/data/PlayerRank.java | 6 ++ .../mcprison/prison/ranks/PrisonRanks.java | 20 ++--- .../prison/ranks/data/RankPlayerFactory.java | 81 ++++++++++++++----- .../prison/ranks/managers/PlayerManager.java | 77 +++++++++++------- 5 files changed, 139 insertions(+), 58 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 0a5e9fdeb..d645c032b 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,18 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.8 2021-11-29 +# 3.2.11-alpha.8 2021-11-30 + + +* **Rank data refactoring. A few changes to get this working. The ladderRanks collection was not being setup was the main issue.** + + +* **Rank data refactoring. A few changes to get this to work well.** + + +* **Major refactoring of Rank Player data objects.** +This is to transition to easier use of player objects in prison. Some of the key classes have been moved from Ranks module to Core module, with the removal of rank functions being moved back to the ranks module. +This is a work in progress and does not yet work. The player's ladders and ranks have not been linked together yet. * **Fixed the auto sell command within the auto features to include the ability to use autosell based upon the auto features settings.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/ranks/data/PlayerRank.java b/prison-core/src/main/java/tech/mcprison/prison/ranks/data/PlayerRank.java index c579a1212..3e814ab36 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/ranks/data/PlayerRank.java +++ b/prison-core/src/main/java/tech/mcprison/prison/ranks/data/PlayerRank.java @@ -34,6 +34,12 @@ protected PlayerRank( Rank rank, double rankMultiplier ) { // this.rankCost = rank.getCost() * (1.0 + rankMultiplier); } + @Override + public String toString() { + return "PlayerRank: " + rank.getName() + " (" + rank.getId() + + " mult: " + rankMultiplier + " cost: " + rankCost + ")"; + } + public void applyMultiplier( double rankMultiplier ) { this.rankMultiplier = rankMultiplier; diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/PrisonRanks.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/PrisonRanks.java index bcb2b810b..14ca5d4c0 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/PrisonRanks.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/PrisonRanks.java @@ -153,15 +153,17 @@ public void enable() { // rankManager.connectRanks(); - for ( Rank rank : rankManager.getRanks() ) { - - if ( rank.getLadder() == null ) { - // Hook up the ladder if it has not been setup yet: - RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder( rank ); - - rank.setLadder( ladder ); - } - } + + // NOTE: The following is not needed since the ladders are already hooked up to the ranks. +// for ( Rank rank : rankManager.getRanks() ) { +// +// if ( rank.getLadder() == null ) { +// // Hook up the ladder if it has not been setup yet: +// RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder( rank ); +// +// rank.setLadder( ladder ); +// } +// } // Verify that all ranks that use currencies have valid currencies: diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankPlayerFactory.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankPlayerFactory.java index 65599df4c..5e425c58f 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankPlayerFactory.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankPlayerFactory.java @@ -40,9 +40,19 @@ public RankPlayer createRankPlayer(Document document) { for (String key : ranksLocal.keySet()) { - rankPlayer.getRanksRefs().put(key, ConversionUtil.doubleToInt(ranksLocal.get(key))); + + int rankId = ConversionUtil.doubleToInt(ranksLocal.get(key)); + rankPlayer.getRanksRefs().put(key, rankId ); + } + + // Sets up the Ladder and Rank objects: + setupLadderRanks( rankPlayer ); + + + + // for (String key : prestigeLocal.keySet()) { // prestige.put(key, RankUtil.doubleToInt(prestigeLocal.get(key))); // } @@ -179,39 +189,72 @@ public PlayerRank getRank( RankPlayer rankPlayer, RankLadder ladder ) { } - /** - * Returns all ladders this player is a part of, along with each rank the player has in that ladder. - * - * @return The map containing this data. - */ - public Map getLadderRanks( RankPlayer rankPlayer ) { +// /** +// * Returns all ladders this player is a part of, along with each rank the player has in that ladder. +// * +// * @return The map containing this data. +// */ +// public Map getLadderRanksx( RankPlayer rankPlayer ) { +// +// if ( rankPlayer.getLadderRanks().isEmpty() && !rankPlayer.getRanksRefs().isEmpty() ) { +// +// //Map ret = new HashMap<>(); +// +// for (Map.Entry entry : rankPlayer.getRanksRefs().entrySet()) { +// RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder(entry.getKey()); +// +// if ( ladder == null ) { +// continue; // Skip it +// } +// +// Rank rank = PrisonRanks.getInstance().getRankManager().getRank(entry.getValue()); +// if ( rank == null ) { +// continue; // Skip it +// } +// +// PlayerRank pRank = new PlayerRank( rank ); +// +// rankPlayer.getLadderRanks().put(ladder, pRank); +// } +// +// // Need to recalculate all rank multipliers: +// rankPlayer.recalculateRankMultipliers(); +// } +// +// return rankPlayer.getLadderRanks(); +// } + + + public void setupLadderRanks( RankPlayer rankPlayer ) { if ( rankPlayer.getLadderRanks().isEmpty() && !rankPlayer.getRanksRefs().isEmpty() ) { //Map ret = new HashMap<>(); for (Map.Entry entry : rankPlayer.getRanksRefs().entrySet()) { - RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder(entry.getKey()); + String ladderName = entry.getKey(); + int rankId = entry.getValue(); - if ( ladder == null ) { - continue; // Skip it - } + RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder( ladderName ); - Rank rank = PrisonRanks.getInstance().getRankManager().getRank(entry.getValue()); - if ( rank == null ) { - continue; // Skip it + if ( ladder != null ) { + + for ( Rank rank : ladder.getRanks() ) { + if ( rank.getId() == rankId ) { + + PlayerRank pRank = createPlayerRank( rank ); + rankPlayer.getLadderRanks().put( ladder, pRank ); + + break; + } + } } - - PlayerRank pRank = new PlayerRank( rank ); - - rankPlayer.getLadderRanks().put(ladder, pRank); } // Need to recalculate all rank multipliers: rankPlayer.recalculateRankMultipliers(); } - return rankPlayer.getLadderRanks(); } diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/PlayerManager.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/PlayerManager.java index 14f70a27a..35313e2cd 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/PlayerManager.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/PlayerManager.java @@ -79,6 +79,7 @@ public PlayerManager(Collection collection) { super("PlayerMangager"); this.collection = collection; + this.players = new ArrayList<>(); this.playersByName = new TreeMap<>(); @@ -91,30 +92,30 @@ public PlayerManager(Collection collection) { * Methods */ - /** - * Loads a player from a file and stores it in the registry for use on the server. - * - * @param playerFile The key that the player data is stored as. Case-sensitive. - * @throws IOException If the file could not be read, or if the file does not exist. - */ - public void loadPlayer(String playerFile) throws IOException { - Document document = collection.get(playerFile).orElseThrow(IOException::new); - - RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); - - RankPlayer rankPlayer = rankPlayerFactory.createRankPlayer(document); - - players.add( rankPlayer ); - - // add by uuid: - playersByName.put( rankPlayer.getUUID().toString(), rankPlayer ); - - // add by name: - if ( rankPlayer.getNames().size() > 0 ) { - playersByName.put( rankPlayer.getDisplayName(), rankPlayer ); - - } - } +// /** +// * Loads a player from a file and stores it in the registry for use on the server. +// * +// * @param playerFile The key that the player data is stored as. Case-sensitive. +// * @throws IOException If the file could not be read, or if the file does not exist. +// */ +// public void loadPlayer(String playerFile) throws IOException { +// Document document = collection.get(playerFile).orElseThrow(IOException::new); +// +// RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); +// +// RankPlayer rankPlayer = rankPlayerFactory.createRankPlayer(document); +// +// players.add( rankPlayer ); +// +// // add by uuid: +// playersByName.put( rankPlayer.getUUID().toString(), rankPlayer ); +// +// // add by name: +// if ( rankPlayer.getNames().size() > 0 ) { +// playersByName.put( rankPlayer.getDisplayName(), rankPlayer ); +// +// } +// } /** * Loads every player in the specified playerFolder. @@ -122,14 +123,32 @@ public void loadPlayer(String playerFile) throws IOException { * @throws IOException If one of the files could not be read, or if the playerFolder does not exist. */ public void loadPlayers() throws IOException { - List players = collection.getAll(); + List playerDocss = collection.getAll(); final RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + + for ( Document playerDocument : playerDocss ) + { + RankPlayer rankPlayer = rankPlayerFactory.createRankPlayer(playerDocument); + + players.add( rankPlayer ); + + // add by uuid: + playersByName.put( rankPlayer.getUUID().toString(), rankPlayer ); + + // add by name: + if ( rankPlayer.getNames().size() > 0 ) { + playersByName.put( rankPlayer.getDisplayName(), rankPlayer ); + + } + } + + - players.forEach( - document -> - this.players.add( - rankPlayerFactory.createRankPlayer(document) )); +// players.forEach( +// document -> +// this.players.add( +// rankPlayerFactory.createRankPlayer(document) )); } /** From 0fe22a01411134f579e2df30a6a417aa4b99940d Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Wed, 1 Dec 2021 21:29:38 -0500 Subject: [PATCH 172/283] Bug fix: The command '/mines reset *all* details' was not working and was only running one mine reset instead of all mines. --- docs/changelog_v3.3.x.md | 5 +++- .../mcprison/prison/mines/data/MineReset.java | 7 +++--- .../prison/mines/data/MineScheduler.java | 9 ++++++-- .../mines/tasks/MinePagedResetAsyncTask.java | 23 +++++++++++++++++-- 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index d645c032b..935156b3e 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,10 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.8 2021-11-30 +# 3.2.11-alpha.8 2021-12-01 + + +* **Bug fix: The command '/mines reset *all* details' was not working and was only running one mine reset instead of all mines.** * **Rank data refactoring. A few changes to get this working. The ladderRanks collection was not being setup was the main issue.** diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java index f6349ea38..174e0ed4a 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineReset.java @@ -761,7 +761,7 @@ protected void resetAsynchonously() { MinePagedResetAsyncTask resetTask = new MinePagedResetAsyncTask( (Mine) this, MineResetType.normal ); resetTask.submitTaskAsync(); - asynchronouslyResetFinalize(); + asynchronouslyResetFinalize( null ); // resetAsynchonouslyUpdate( true ); @@ -874,7 +874,7 @@ public void asynchronouslyResetSetup() { } } - public void asynchronouslyResetFinalize() { + public void asynchronouslyResetFinalize( List jobResetActions ) { // If a player falls back in to the mine before it is fully done being reset, // such as could happen if there is lag or a lot going on within the server, // this will TP anyone out who would otherwise suffocate. I hope! lol @@ -930,7 +930,8 @@ public void asynchronouslyResetFinalize() { } // If part of a chained_resets, then kick off the next reset: - if ( getCurrentJob().getResetActions().contains( MineResetActions.CHAINED_RESETS )) { + if ( jobResetActions != null && jobResetActions.contains( MineResetActions.CHAINED_RESETS ) || + getCurrentJob().getResetActions().contains( MineResetActions.CHAINED_RESETS )) { PrisonMines pMines = PrisonMines.getInstance(); pMines.resetAllMinesNext(); diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineScheduler.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineScheduler.java index 503f70ac2..79c17d3a8 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineScheduler.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineScheduler.java @@ -367,8 +367,10 @@ public void run() case RESET_ASYNC: if ( !skip ) { + List resetActions = getCurrentJob().getResetActions(); + MinePagedResetAsyncTask resetTask = - new MinePagedResetAsyncTask( (Mine) this, MineResetType.paged ); + new MinePagedResetAsyncTask( (Mine) this, MineResetType.paged, resetActions ); resetTask.submitTaskAsync(); // resetAsynchonously(); @@ -382,8 +384,11 @@ public void run() // synchronous reset. Will be phased out in the future? if ( !skip ) { + List resetActions = getCurrentJob().getResetActions(); + MinePagedResetAsyncTask resetTask = - new MinePagedResetAsyncTask( (Mine) this, MineResetType.normal ); + new MinePagedResetAsyncTask( (Mine) this, MineResetType.normal, resetActions ); + resetTask.submitTaskAsync(); // resetSynchonously(); diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java index 58a451fd5..466935390 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java @@ -8,6 +8,7 @@ import tech.mcprison.prison.internal.block.MineTargetPrisonBlock; import tech.mcprison.prison.mines.PrisonMines; import tech.mcprison.prison.mines.data.Mine; +import tech.mcprison.prison.mines.data.MineScheduler.MineResetActions; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.tasks.PrisonRunnable; import tech.mcprison.prison.tasks.PrisonTaskSubmitter; @@ -38,7 +39,11 @@ public class MinePagedResetAsyncTask private int configSyncSubPageSlice = -1; - public MinePagedResetAsyncTask( Mine mine, MineResetType resetType ) { + private List resetActions; + + + + public MinePagedResetAsyncTask( Mine mine, MineResetType resetType, List resetActions ) { super(); this.mine = mine; @@ -52,6 +57,13 @@ public MinePagedResetAsyncTask( Mine mine, MineResetType resetType ) { this.totalPages = (mine.getMineTargetPrisonBlocks().size() / getConfigAsyncResetPageSize()) + 1; + + this.resetActions = resetActions; + } + + + public MinePagedResetAsyncTask( Mine mine, MineResetType resetType ) { + this( mine, resetType, null ); } @@ -205,7 +217,7 @@ private void runShutdown() { // Run items such as post-mine-reset commands: - mine.asynchronouslyResetFinalize(); + mine.asynchronouslyResetFinalize( getResetActions() ); } @@ -218,6 +230,13 @@ public void setNanos( PrisonStatsElapsedTimeNanos nanos ) { this.nanos = nanos; } + public List getResetActions() { + return resetActions; + } + public void setResetActions( List resetActions ) { + this.resetActions = resetActions; + } + public int getConfigAsyncResetPageSize() { if ( configAsyncResetPageSize == -1 ) { From 4176af632e7b601b58d79d61f46ca99756a7b5d7 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Wed, 1 Dec 2021 22:21:54 -0500 Subject: [PATCH 173/283] Bug fix: If a MONITOR event listener, then it should not process the block break event. Monitors were processing the block break events when they shouldn't so monitors are not terminated after validation since their "processing" is handled there. --- docs/changelog_v3.3.x.md | 4 + .../spigot/block/OnBlockBreakEventCore.java | 321 ++---------------- 2 files changed, 28 insertions(+), 297 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 935156b3e..858500c08 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.8 2021-12-01 +* **Bug fix: If a MONITOR event listener, then it should not process the block break event.** +Monitors were processing the block break events when they shouldn't so monitors are not terminated after validation since their "processing" is handled there. + + * **Bug fix: The command '/mines reset *all* details' was not working and was only running one mine reset instead of all mines.** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index b92ae6f91..b59dccc82 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -334,43 +334,6 @@ protected void genericBlockEvent( BlockBreakEvent e, boolean monitor, boolean bl } -// if ( e.isCancelled() && !monitor ) { - // Check to see if the event should be ignored. - -// if ( processMinesBlockBreakEvent( e, e.getPlayer(), e.getBlock()) ) { -// return; -// } -// -// SpigotBlock sBlock = new SpigotBlock( e.getBlock() ); -// if ( BlockUtils.getInstance().isUnbreakable( sBlock ) ) { -// e.setCancelled( true ); -// return; -// } -// -// Mine mine = findMine( e.getPlayer(), sBlock, null, null ); -// -// if ( mine == null ) { -// // Prison is unable to process blocks outside of mines right now, so exit: -// return; -// } -// -// // If not minable, then display message and exit. -// if ( !mine.getMineStateMutex().isMinable() ) { -// -// SpigotPlayer sPlayer = new SpigotPlayer( e.getPlayer() ); -// sPlayer.setActionBar( "Mine " + mine.getTag() + " is being reset... please wait." ); -// e.setCancelled( true ); -// return; -// } -// MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); -// -// // If ignore all block events, then exit this function without logging anything: -// if ( targetBlock.isIgnoreAllBlockEvents() ) { -// e.setCancelled( true ); -// return; -// } - -// } // Register all external events such as mcMMO and EZBlocks: OnBlockBreakExternalEvents.getInstance().registerAllExternalEvents(); @@ -408,6 +371,9 @@ protected void genericBlockEvent( BlockBreakEvent e, boolean monitor, boolean bl } } + else if ( pmEvent.isMonitor() ) { + // Stop here, and prevent additional processing. Monitors should never process the event beyond this. + } // This is where the processing actually happens: else if ( pmEvent.getMine() != null || pmEvent.getMine() == null && @@ -595,38 +561,6 @@ private boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent, StringBuilder Mine mine = findMine( pmEvent.getPlayer(), pmEvent.getSpigotBlock(), pmEvent.getUnprocessedRawBlocks(), pmEvent ); -// Long playerUUIDLSB = Long.valueOf( pmEvent.getPlayer().getUniqueId().getLeastSignificantBits() ); -// -// // Get the cached mine, if it exists: -// Mine mine = getPlayerCache().get( playerUUIDLSB ); -// -// if ( mine == null || -// pmEvent.getSpigotBlock() != null && !mine.isInMineExact( pmEvent.getSpigotBlock().getLocation() ) ) { -// // Look for the correct mine to use. -// // Set mine to null so if cannot find the right one it will return a null: -// mine = findMineLocation( pmEvent.getSpigotBlock() ); -// -// // Thanks to CrazyEnchant, where they do not identify the block the player breaks, we -// // have to go through all of the unprecessedRawBlocks to see if any are within a mine. -// // If we find a block that's in a mine, then use that block as the primary block. -// if ( mine == null ) { -// -// for ( Block bBlock : pmEvent.getUnprocessedRawBlocks() ) -// { -// SpigotBlock sBlock = new SpigotBlock( bBlock ); -// mine = findMineLocation( sBlock ); -// if ( mine != null ) { -// pmEvent.setSpigotBlock( sBlock ); -// break; -// } -// } -// } -// -// // Store the mine in the player cache if not null: -// if ( mine != null ) { -// getPlayerCache().put( playerUUIDLSB, mine ); -// } -// } pmEvent.setMine( mine ); debugInfo.append( "mine=" + (mine == null ? "none" : mine.getName()) + " " ); @@ -840,7 +774,7 @@ else if ( results ) { pmEvent.setBukkitDrops( mergeDrops( pmEvent.getBukkitDrops() ) ); - // If target block aready was mined and there are no exploded blocks, then this whole event + // If target block already was mined and there are no exploded blocks, then this whole event // needs to be canceled since it sounds like a blockevent fired a prison util explosion that // has zero blocks tied to it. if ( targetBlockAlreadyMined && pmEvent.isForceIfAirBlock() && pmEvent.getExplodedBlocks().size() == 0 ) { @@ -1093,43 +1027,6 @@ private void genericBlockExplodeEvent( TEBlockExplodeEvent e, boolean monitor, b return; } -// if ( e.isCancelled() && !monitor ) { - // Check to see if the event should be ignored. - -// if ( processMinesBlockBreakEvent( e, e.getPlayer(), e.getBlock()) ) { -// return; -// } - -// SpigotBlock sBlock = new SpigotBlock( e.getBlock() ); -// if ( BlockUtils.getInstance().isUnbreakable( sBlock ) ) { -// e.setCancelled( true ); -// return; -// } -// -// Mine mine = findMine( e.getPlayer(), sBlock, e.blockList(), null ); -// -// if ( mine == null ) { -// // Prison is unable to process blocks outside of mines right now, so exit: -// return; -// } -// -// // If not minable, then display message and exit. -// if ( !mine.getMineStateMutex().isMinable() ) { -// -// SpigotPlayer sPlayer = new SpigotPlayer( e.getPlayer() ); -// sPlayer.setActionBar( "Mine " + mine.getTag() + " is being reset... please wait." ); -// e.setCancelled( true ); -// return; -// } -// MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); -// -// // If ignore all block events, then exit this function without logging anything: -// if ( targetBlock.isIgnoreAllBlockEvents() ) { -// e.setCancelled( true ); -// return; -// } - -// } // Register all external events such as mcMMO and EZBlocks: OnBlockBreakExternalEvents.getInstance().registerAllExternalEvents(); @@ -1180,42 +1077,17 @@ private void genericBlockExplodeEvent( TEBlockExplodeEvent e, boolean monitor, b } } + else if ( pmEvent.isMonitor() ) { + // Stop here, and prevent additional processing. Monitors should never process the event beyond this. + } + // now process all blocks (non-monitor): else if ( isTEExplosiveEnabled && ( pmEvent.getMine() != null || pmEvent.getMine() == null && !isBoolean( AutoFeatures.pickupLimitToMines )) ) { -// int unbreakable = 0; -// int outsideOfMine = 0; - - // have to go through all blocks since some blocks may be outside the mine. - // but terminate search upon first find: - -// for ( Block blk : e.blockList() ) { -// //boolean isAir = blk.getType() != null && blk.getType() == Material.AIR; -// -// // Need to wrap in a Prison block so it can be used with the mines: -//// SpigotBlock sBlock = new SpigotBlock(blk); -// -// -// if ( BlockUtils.getInstance().isUnbreakable( pmEvent.getSpigotBlock() ) ) { -// -// unbreakable++; -// } -// else if ( pmEvent.getMine().isInMineExact( sBlock.getLocation() ) ) { -// -// pmEvent.getExplodedBlocks().add( sBlock ); -// -// -// // check all external events such as mcMMO and EZBlocks: -// OnBlockBreakExternalEvents.getInstance().checkAllExternalEvents( e.getPlayer(), blk ); -// } -// else { -// outsideOfMine++; -// } -// -// } + if ( pmEvent.getExplodedBlocks().size() > 0 ) { @@ -1257,17 +1129,6 @@ else if ( isTEExplosiveEnabled && } -// if ( unbreakable > 0 ) { -// -// // e.setCancelled( true ); -// debugInfo.append( "UNBREAKABLE_BLOCK_UTILS (" + unbreakable + -// " blocks, event not canceled) " ); -// } -// if ( outsideOfMine > 0 ) { -// -// debugInfo.append( "BLOCKS_OUTSIDE_OF_MINE (" + outsideOfMine + -// " blocks, event not canceled) " ); -// } debugInfo.append( "(normal processing) " ); } @@ -1342,43 +1203,6 @@ protected void genericBlastUseEvent( BlastUseEvent e, boolean monitor, boolean b return; } -// if ( e.isCancelled() && !monitor ) { - // Check to see if the event should be ignored. - -// if ( processMinesBlockBreakEvent( e, e.getPlayer(), e.getBlockList().get( 0 ) ) ) { -// return; -// } - -// SpigotBlock sBlock = new SpigotBlock( e.getBlockList().get( 0 ) ); -// if ( BlockUtils.getInstance().isUnbreakable( sBlock ) ) { -// e.setCancelled( true ); -// return; -// } -// -// Mine mine = findMine( e.getPlayer(), sBlock, e.getBlockList(), null ); -// -// if ( mine == null ) { -// // Prison is unable to process blocks outside of mines right now, so exit: -// return; -// } -// -// // If not minable, then display message and exit. -// if ( !mine.getMineStateMutex().isMinable() ) { -// -// SpigotPlayer sPlayer = new SpigotPlayer( e.getPlayer() ); -// sPlayer.setActionBar( "Mine " + mine.getTag() + " is being reset... please wait." ); -// e.setCancelled( true ); -// return; -// } -// MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); -// -// // If ignore all block events, then exit this function without logging anything: -// if ( targetBlock.isIgnoreAllBlockEvents() ) { -// e.setCancelled( true ); -// return; -// } - -// } // Register all external events such as mcMMO and EZBlocks: OnBlockBreakExternalEvents.getInstance().registerAllExternalEvents(); @@ -1432,38 +1256,17 @@ protected void genericBlastUseEvent( BlastUseEvent e, boolean monitor, boolean b } + else if ( pmEvent.isMonitor() ) { + // Stop here, and prevent additional processing. Monitors should never process the event beyond this. + } + // now process all blocks (non-monitor): else if ( isCEBlockExplodeEnabled && ( pmEvent.getMine() != null || pmEvent.getMine() == null && !isBoolean( AutoFeatures.pickupLimitToMines )) ) { -// int unbreakable = 0; -// int outsideOfMine = 0; - - // have to go through all blocks since some blocks may be outside the mine. - // but terminate search upon first find: - -// for ( Block blk : e.getBlockList() ) { -// -// // Need to wrap in a Prison block so it can be used with the mines: -// SpigotBlock sBlock = new SpigotBlock(blk); -// -// if ( BlockUtils.getInstance().isUnbreakable( new SpigotBlock( blk ) ) ) { -// -// unbreakable++; -// } -// else if ( mine.isInMineExact( sBlock.getLocation() ) ) { -// -// explodedBlocks.add( sBlock ); -// -// // check all external events such as mcMMO and EZBlocks: -// OnBlockBreakExternalEvents.getInstance().checkAllExternalEvents( e.getPlayer(), blk ); -// } -// else { -// outsideOfMine++; -// } -// -// } + + if ( pmEvent.getExplodedBlocks().size() > 0 ) { // String triggered = null; @@ -1507,17 +1310,6 @@ else if ( isCEBlockExplodeEnabled && } } -// if ( unbreakable > 0 ) { -// -// // e.setCancelled( true ); -// debugInfo.append( "UNBREAKABLE_BLOCK_UTILS (" + unbreakable + -// " blocks, event not canceled) " ); -// } -// if ( outsideOfMine > 0 ) { -// -// debugInfo.append( "BLOCKS_OUTSIDE_OF_MINE (" + outsideOfMine + -// " blocks, event not canceled) " ); -// } debugInfo.append( "(normal processing) " ); } @@ -1560,43 +1352,6 @@ protected void genericExplosiveEvent( PEExplosionEvent e, boolean monitor, boole return; } -// if ( e.isCancelled() && !monitor ) { - // Check to see if the event should be ignored. - -// if ( processMinesBlockBreakEvent( e, e.getPlayer(), e.getBlockBroken()) ) { -// return; -// } - -// SpigotBlock sBlock = new SpigotBlock( e.getBlockBroken() ); -// if ( BlockUtils.getInstance().isUnbreakable( sBlock ) ) { -// e.setCancelled( true ); -// return; -// } -// -// Mine mine = findMine( e.getPlayer(), sBlock, e.getExplodedBlocks(), null ); -// -// if ( mine == null ) { -// // Prison is unable to process blocks outside of mines right now, so exit: -// return; -// } -// -// // If not minable, then display message and exit. -// if ( !mine.getMineStateMutex().isMinable() ) { -// -// SpigotPlayer sPlayer = new SpigotPlayer( e.getPlayer() ); -// sPlayer.setActionBar( "Mine " + mine.getTag() + " is being reset... please wait." ); -// e.setCancelled( true ); -// return; -// } -// MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); -// -// // If ignore all block events, then exit this function without logging anything: -// if ( targetBlock.isIgnoreAllBlockEvents() ) { -// e.setCancelled( true ); -// return; -// } - -// } // Register all external events such as mcMMO and EZBlocks: OnBlockBreakExternalEvents.getInstance().registerAllExternalEvents(); @@ -1643,8 +1398,12 @@ protected void genericExplosiveEvent( PEExplosionEvent e, boolean monitor, boole } + else if ( pmEvent.isMonitor() ) { + // Stop here, and prevent additional processing. Monitors should never process the event beyond this. + } + // now process all blocks (non-monitor): else if ( isPEExplosiveEnabled && ( pmEvent.getMine() != null || pmEvent.getMine() == null && !isBoolean( AutoFeatures.pickupLimitToMines )) ) { @@ -1715,43 +1474,6 @@ protected void genericExplosiveEvent( ExplosiveBlockBreakEvent e, boolean monito return; } -// if ( e.isCancelled() && !monitor ) { - // Check to see if the event should be ignored. - -// if ( processMinesBlockBreakEvent( e, e.getPlayer(), e.getBlock()) ) { -// return; -// } - -// SpigotBlock sBlock = new SpigotBlock( e.getBlock() ); -// if ( BlockUtils.getInstance().isUnbreakable( sBlock ) ) { -// e.setCancelled( true ); -// return; -// } -// -// Mine mine = findMine( e.getPlayer(), sBlock, e.getExplodedBlocks(), null ); -// -// if ( mine == null ) { -// // Prison is unable to process blocks outside of mines right now, so exit: -// return; -// } -// -// // If not minable, then display message and exit. -// if ( !mine.getMineStateMutex().isMinable() ) { -// -// SpigotPlayer sPlayer = new SpigotPlayer( e.getPlayer() ); -// sPlayer.setActionBar( "Mine " + mine.getTag() + " is being reset... please wait." ); -// e.setCancelled( true ); -// return; -// } -// MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); -// -// // If ignore all block events, then exit this function without logging anything: -// if ( targetBlock.isIgnoreAllBlockEvents() ) { -// e.setCancelled( true ); -// return; -// } - -// } // Register all external events such as mcMMO and EZBlocks: OnBlockBreakExternalEvents.getInstance().registerAllExternalEvents(); @@ -1813,6 +1535,11 @@ protected void genericExplosiveEvent( ExplosiveBlockBreakEvent e, boolean monito } + else if ( pmEvent.isMonitor() ) { + // Stop here, and prevent additional processing. Monitors should never process the event beyond this. + } + + // now process all blocks (non-monitor): else if ( isPPrisonExplosiveBlockBreakEnabled && From f9ed2275a8c87e62eeac57a2e9e4abc1517ca910 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Thu, 2 Dec 2021 03:10:40 -0500 Subject: [PATCH 174/283] added mine name to reset notifications --- docs/changelog_v3.3.x.md | 7 ++++++- prison-core/src/main/resources/lang/mines/de_DE.properties | 4 ++-- prison-core/src/main/resources/lang/mines/en_US.properties | 4 ++-- prison-core/src/main/resources/lang/mines/es_ES.properties | 4 ++-- prison-core/src/main/resources/lang/mines/hu_HU.properties | 4 ++-- prison-core/src/main/resources/lang/mines/it_IT.properties | 4 ++-- prison-core/src/main/resources/lang/mines/nl_BE.properties | 4 ++-- prison-core/src/main/resources/lang/mines/nl_NL.properties | 4 ++-- prison-core/src/main/resources/lang/mines/zh_TW.properties | 4 ++-- .../tech/mcprison/prison/mines/commands/MinesCommands.java | 4 +++- 10 files changed, 25 insertions(+), 18 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 858500c08..bcefa929a 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,12 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.8 2021-12-01 +# 3.2.11-alpha.8 2021-12-02 + +* ** + + +* **added mine name to reset notifications** * **Bug fix: If a MONITOR event listener, then it should not process the block break event.** diff --git a/prison-core/src/main/resources/lang/mines/de_DE.properties b/prison-core/src/main/resources/lang/mines/de_DE.properties index 4ed2f1679..2fd6c1936 100644 --- a/prison-core/src/main/resources/lang/mines/de_DE.properties +++ b/prison-core/src/main/resources/lang/mines/de_DE.properties @@ -68,8 +68,8 @@ autoblock_disable=&bAutoblock &7wurde deaktiviert. autopickup_enable=&bAutoblock &7wurde aktiviert. autopickup_disable=&bAutoblock &7wurde deaktiviert. teleported=&7Teleportiert zur Mine&3%1&7. -mine_reset=&7Die Mine wurde zurückegetzt. -mine_reset_fail=&7Mine konnte nicht zurückgesetzt werden. &8Prüfe die Konsole nach Details. +mine_reset=&7Die Mine &3%1&7 wurde zurückegetzt. +mine_reset_fail=&7Mine &3%1&7 konnte nicht zurückgesetzt werden. &8Prüfe die Konsole nach Details. mine_created=&7Mine erfolgreich erstellt. mine_deleted=&7Mine erfolgreich gelöscht. select_bounds=&7Du musst zuerst die Minenbegrenzung auswählen. &8Type /mines wand to do so. diff --git a/prison-core/src/main/resources/lang/mines/en_US.properties b/prison-core/src/main/resources/lang/mines/en_US.properties index ae80f0c4b..5bb530070 100644 --- a/prison-core/src/main/resources/lang/mines/en_US.properties +++ b/prison-core/src/main/resources/lang/mines/en_US.properties @@ -68,8 +68,8 @@ autoblock_disable=&bAutoblock &7has been &cdisabled&7. autopickup_enable=&bAutopickup &7has been &aenabled&7. autopickup_disable=&bAutopickup &7has been &cdisabled&7. teleported=&7Teleported to mine &3%1&7. -mine_reset=&7The mine has been reset. -mine_reset_fail=&7Could not reset the mine. &8Check the console for details. +mine_reset=&7The mine &3%1&7 has been reset. +mine_reset_fail=&7Could not reset mine &3%1&7. &8Check the console for details. mine_created=&7Successfully created the mine. mine_deleted=&7Successfully deleted the mine. select_bounds=&7You need to select the mine boundaries first. &8Type /mines wand to do so. diff --git a/prison-core/src/main/resources/lang/mines/es_ES.properties b/prison-core/src/main/resources/lang/mines/es_ES.properties index 4781c4bb3..12f9659fd 100644 --- a/prison-core/src/main/resources/lang/mines/es_ES.properties +++ b/prison-core/src/main/resources/lang/mines/es_ES.properties @@ -68,8 +68,8 @@ autoblock_disable=&7El &bBloque Automático &7ha sido &cdesactivado&7. autopickup_enable=&7La &bRecolección Automática &7ha sido &aactivada&7. autopickup_disable=&7La &bRecolección Automática &7ha sido &cdesactivada&7. teleported=&7Transportado a la mina &3%1&7. -mine_reset=&7La mina ha sido reiniciada. -mine_reset_fail=&7No se ha podido reiniciar la mina. &8Diríjase la consola para más detalles. +mine_reset=&7La mina &3%1&7 ha sido reiniciada. +mine_reset_fail=&7No se ha podido reiniciar la mina &3%1&7. &8Diríjase la consola para más detalles. mine_created=&7Mina creada exitosamente. mine_deleted=&7Mina eliminada exitosamente. select_bounds=&7Necesitas seleccionar los límites de la mina previamente. &8Escribe /mines wand para realizarlo. diff --git a/prison-core/src/main/resources/lang/mines/hu_HU.properties b/prison-core/src/main/resources/lang/mines/hu_HU.properties index d5d8ab858..842a9a2ef 100644 --- a/prison-core/src/main/resources/lang/mines/hu_HU.properties +++ b/prison-core/src/main/resources/lang/mines/hu_HU.properties @@ -68,8 +68,8 @@ autoblock_disable=&bAz auto. blokk &7letiltva. autopickup_enable=&bAz auto. felvétel &7engedélyezve. autopickup_disable=&bAz auto. felvétel &7letiltva. teleported=&7Teleportálás a(z) &3%1&7 bányához. -mine_reset=&7A bánya újratöltve. -mine_reset_fail=&7Nem lehet újratölteni a bányát. &8A részletekért nézd meg a konzolt. +mine_reset=&7A bánya újratöltve. &3%1&7 +mine_reset_fail=&7Nem lehet újratölteni a bányát. &3%1&7. &8A részletekért nézd meg a konzolt. mine_created=&7A bánya sikeresen létrehozva. mine_deleted=&7A bánya sikeresen törölve. select_bounds=&7Először ki kell választani a bánya határait. &8Típus /mines wand. diff --git a/prison-core/src/main/resources/lang/mines/it_IT.properties b/prison-core/src/main/resources/lang/mines/it_IT.properties index 2116e07d5..2a8d984cd 100644 --- a/prison-core/src/main/resources/lang/mines/it_IT.properties +++ b/prison-core/src/main/resources/lang/mines/it_IT.properties @@ -68,8 +68,8 @@ autoblock_disable=&bAutoBlocco &7è stato &cdisabilitato&7. autopickup_enable=&bAutoRaccoglitore &7è stato &aabilitato&7. autopickup_disable=&bAutoRaccoglitore &7è stato &cdisabilitato&7. teleported=&7Teletrasportato alla miniera &3%1&7. -mine_reset=&7La miniera è stata resettata. -mine_reset_fail=&7Non è possibile resettare la miniera. &8Controllare la console per dettagli. +mine_reset=&7La miniera &3%1&7 è stata resettata. +mine_reset_fail=&7Non è possibile resettare la miniera &3%1&7. &8Controllare la console per dettagli. mine_created=&7Miniera creata con successo. mine_deleted=&7Miniera cancellata con successo. select_bounds=&7Prima hai bisogno di selezionare gli estremi (angoli) della miniera. &8Il quale solo /mines wand può farlo. diff --git a/prison-core/src/main/resources/lang/mines/nl_BE.properties b/prison-core/src/main/resources/lang/mines/nl_BE.properties index 7c3a5bfaf..c977e7f5b 100644 --- a/prison-core/src/main/resources/lang/mines/nl_BE.properties +++ b/prison-core/src/main/resources/lang/mines/nl_BE.properties @@ -66,8 +66,8 @@ autosmelt_disable=&bAutosmelt &7is afgezet. autoblock_enable=&bAutoblock &7is aangezet. autoblock_disable=&bAutoblock &7is afgezet. teleported=&7Geteleporteerd naar mijn &3%1&7. -mine_reset=&7De mijn is hersteld. -mine_reset_fail=&7Kon mijn niet herstellen. &8Kijk in de console voor meer info. +mine_reset=&7De mijn &3%1&7 is hersteld. +mine_reset_fail=&7Kon mijn &3%1&7 niet herstellen. &8Kijk in de console voor meer info. mine_created=&7Mijn succesvol gecreëerd. mine_deleted=&7Mijn succesvol verwijderd. select_bounds=&7Je moet de mijn dimensies eerst selecteren. &8Type /mines wand om dat te doen. diff --git a/prison-core/src/main/resources/lang/mines/nl_NL.properties b/prison-core/src/main/resources/lang/mines/nl_NL.properties index 7c3a5bfaf..c977e7f5b 100644 --- a/prison-core/src/main/resources/lang/mines/nl_NL.properties +++ b/prison-core/src/main/resources/lang/mines/nl_NL.properties @@ -66,8 +66,8 @@ autosmelt_disable=&bAutosmelt &7is afgezet. autoblock_enable=&bAutoblock &7is aangezet. autoblock_disable=&bAutoblock &7is afgezet. teleported=&7Geteleporteerd naar mijn &3%1&7. -mine_reset=&7De mijn is hersteld. -mine_reset_fail=&7Kon mijn niet herstellen. &8Kijk in de console voor meer info. +mine_reset=&7De mijn &3%1&7 is hersteld. +mine_reset_fail=&7Kon mijn &3%1&7 niet herstellen. &8Kijk in de console voor meer info. mine_created=&7Mijn succesvol gecreëerd. mine_deleted=&7Mijn succesvol verwijderd. select_bounds=&7Je moet de mijn dimensies eerst selecteren. &8Type /mines wand om dat te doen. diff --git a/prison-core/src/main/resources/lang/mines/zh_TW.properties b/prison-core/src/main/resources/lang/mines/zh_TW.properties index 90bc197d6..617beeefd 100644 --- a/prison-core/src/main/resources/lang/mines/zh_TW.properties +++ b/prison-core/src/main/resources/lang/mines/zh_TW.properties @@ -68,8 +68,8 @@ autoblock_disable=&b自動合成方塊 &7已被 &c停用&7 autopickup_enable=&b自動拾取 &7已被 &a啟用&7 autopickup_disable=&b自動拾取 &7已被 &c停用&7 teleported=&7正在傳送到 礦場 &3%1&7 -mine_reset=&7礦場已經被重置 -mine_reset_fail=&7礦場重置錯誤。 &8請打開 Console 查看細節 +mine_reset=&7礦場已經被重置。 &3%1&7 +mine_reset_fail=&7礦場重置錯誤。 &3%1&7。 &8請打開 Console 查看細節 mine_created=&7礦場 已成功 建立 mine_deleted=&7礦場 已成功 刪除 select_bounds=&7您必須要先選擇 礦場 的 界線。 &8如果想要 請輸入 /mines diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java index 1d06053f0..bbe6b7d74 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java @@ -1293,11 +1293,13 @@ public void resetCommand(CommandSender sender, m.manualReset( resetType, resetActions ); } catch (Exception e) { pMines.getMinesMessages().getLocalizable("mine_reset_fail") + .withReplacements( m.getName() ) .sendTo(sender); Output.get().logError("Couldn't reset mine " + mineName, e); } - pMines.getMinesMessages().getLocalizable("mine_reset").sendTo(sender); + pMines.getMinesMessages().getLocalizable("mine_reset") + .withReplacements( m.getName() ).sendTo(sender); } From 714f81859813dd85bd2f2ecf9f21a1698a293000 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Thu, 2 Dec 2021 03:15:04 -0500 Subject: [PATCH 175/283] Added a new feature to back up a mine and to provide a way to convert a mine to a virutal mine. When converting to a virtual, with the command '/mines set area virtual', a back up is made first. The new backup command is '/mines back help'. --- docs/changelog_v3.3.x.md | 5 +- .../mcprison/prison/file/FileCollection.java | 9 ++ .../prison/file/FileVirtualDelete.java | 40 +++++++- .../mcprison/prison/store/Collection.java | 3 + .../prison/mines/commands/MinesCommands.java | 92 ++++++++++++++++++- .../prison/mines/managers/MineManager.java | 18 +++- 6 files changed, 162 insertions(+), 5 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index bcefa929a..a81e486fa 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -15,7 +15,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.8 2021-12-02 -* ** + +* **Added a new feature to back up a mine and to provide a way to convert a mine to a virtual mine.** +When converting to a virtual, with the command '/mines set area virtual', a back up is made first. +The new backup command is '/mines back help'. * **added mine name to reset notifications** diff --git a/prison-core/src/main/java/tech/mcprison/prison/file/FileCollection.java b/prison-core/src/main/java/tech/mcprison/prison/file/FileCollection.java index d7785aad5..a94d97860 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/file/FileCollection.java +++ b/prison-core/src/main/java/tech/mcprison/prison/file/FileCollection.java @@ -101,5 +101,14 @@ public boolean delete(String name) File dbFile = new File(collDir, name + ".json"); return virtualDelete( dbFile ); } + + @Override + public File backup( String name ) + { + File dbFile = new File(collDir, name + ".json"); + File backupFile = virtualBackup( dbFile ); + + return backupFile; + } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/file/FileVirtualDelete.java b/prison-core/src/main/java/tech/mcprison/prison/file/FileVirtualDelete.java index 5fc29be28..1e985a439 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/file/FileVirtualDelete.java +++ b/prison-core/src/main/java/tech/mcprison/prison/file/FileVirtualDelete.java @@ -4,15 +4,21 @@ package tech.mcprison.prison.file; import java.io.File; +import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; +import com.google.common.io.Files; + +import tech.mcprison.prison.output.Output; + /** * */ public abstract class FileVirtualDelete { public static final String FILE_LOGICAL_DELETE_PREFIX = ".deleted_"; + public static final String FILE_LOGICAL_BACKUP_PREFIX = ".backup"; public FileVirtualDelete() { @@ -38,6 +44,36 @@ protected boolean virtualDelete( File source ) return source.renameTo( newName ); } + /** + *

This function will make a backup of a file source. It's included in this virtual delete + * class since it's very similar and by changing the isDeleted() function, the backups can + * also be ignored. + *

+ * + * @param source + * @return File name of the backup file. + */ + protected File virtualBackup( File source ) + { + SimpleDateFormat sdf = new SimpleDateFormat("_yyyy-MM-dd_HH-mm-ss"); + String name = FILE_LOGICAL_BACKUP_PREFIX + source.getName() + sdf.format( new Date() ) + ".del"; + File backupFile = new File( source.getParentFile(), name); + + try { + Files.copy( source, backupFile ); + } + catch ( IOException e ) + { + Output.get().logError( + String.format( + "Could not create a backup. SourceFile: %s BackupFile: %s Error: [%s]", + source.getAbsolutePath(), backupFile.getAbsolutePath(), e.getMessage() )); + e.printStackTrace(); + } + + return backupFile; + } + /** *

This function will return a boolean value to indicate if it has been logically * deleted. It will ONLY inspect the beginning of the file name which much have @@ -49,7 +85,9 @@ protected boolean virtualDelete( File source ) */ protected boolean isDeleted( File source ) { - return source.getName().toLowerCase().startsWith( FILE_LOGICAL_DELETE_PREFIX ); + return + source.getName().toLowerCase().startsWith( FILE_LOGICAL_DELETE_PREFIX ) || + source.getName().toLowerCase().startsWith( FILE_LOGICAL_BACKUP_PREFIX ); } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/store/Collection.java b/prison-core/src/main/java/tech/mcprison/prison/store/Collection.java index 274fefa25..49b8aee74 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/store/Collection.java +++ b/prison-core/src/main/java/tech/mcprison/prison/store/Collection.java @@ -1,5 +1,6 @@ package tech.mcprison.prison.store; +import java.io.File; import java.util.List; import java.util.Optional; @@ -36,5 +37,7 @@ public interface Collection { public boolean delete(String name); + + public File backup(String name); } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java index bbe6b7d74..2272d1142 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java @@ -18,6 +18,7 @@ package tech.mcprison.prison.mines.commands; +import java.io.File; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Collections; @@ -2212,7 +2213,9 @@ public void redefineCommand(CommandSender sender, @Arg(name = "source", description = "&3The source to use for setting the area. The &7wand&3 " + "uses the area defined by the wand. &7Feet&3 defines a 1x1 mine under your feet" + "which is useful in void worlds or when flying and can be enlarged with " + - "&7/mines set size help&3 . &2[&7wand feet&2]", + "&7/mines set size help&3. " + + "The use of &7virtual&3 will remove the mine's location and spawn points, and " + + "will revert the mine to a virtual mine. &2[&7wand feet virtual&2]", def = "wand") String source, @Wildcard(join=true) @Arg(name = "options", description = " " + @@ -2247,8 +2250,60 @@ public void redefineCommand(CommandSender sender, else if ( source == null || "wand".equalsIgnoreCase( source ) ) { selection = Prison.get().getSelectionManager().getSelection( player ); } + else if ( source == null || "virtual".equalsIgnoreCase( source ) ) { + // do nothing... don't set selection: + } else { - sender.sendMessage( "&3Valid values for &2source &3are &7wand&3 and &7feet&3." ); + sender.sendMessage( "&3Valid values for &2source &3are &7wand&3, " + + "&7feet&3, and &7virtual&3." ); + return; + } + + if ( selection == null ) { + + // Revert the mine to a virtual mine: + + setLastMineReferenced(mineName); + + if ( m.isVirtual() ) { + // Already a virtual mine so exit: + String message = "Mine &7" + m.getName() + " &3is already virtual. No changes have been made."; + sender.sendMessage( message ); + + return; + } + + // Make a backup of the mine save file before making virtual: + File backupFile = pMines.getMineManager().backupMine( m ); + + String messageBu = "Mine &7" + m.getName() + " &3has " + + ( backupFile.exists() ? "been successfully" : "failed to be" ) + + " backed up: " + backupFile.getAbsolutePath(); + sender.sendMessage( messageBu ); + Output.get().logInfo( messageBu ); + + if ( !backupFile.exists() ) { + Output.get().logInfo( "Since the backup Failed, mine " + m.getName() + " cannot be " + + "virtualized." ); + + return; + } + + m.setBounds( null ); + m.setSpawn( null ); + + m.setVirtual( true ); + + m.getJobStack().clear(); + + // TODO Possibly may need to kill existing jobs and/or set a mutex state of VIRTUAL? + m.getMineStateMutex(); + + pMines.getMineManager().saveMine( m ); + + String message = "Mine &7" + m.getName() + " &3has been set to virtual. "; + sender.sendMessage( message ); + return; } @@ -2357,6 +2412,39 @@ else if ( options.toLowerCase().contains( "confirm" ) || + @Command(identifier = "mines backup", permissions = "mines.set", + description = "Creates a backup of the specified mine. Backups are similar to virtually " + + "deleted mines in that a copy is made, but cannot be accessed. To recover from " + + "a backup, it must be done manually outside of the game or console. " + + "Once a backup is created, prison cannot do anything with it; it must be " + + "manually managed.") + public void backupMineCommand(CommandSender sender, + @Arg(name = "mineName", description = "The name of the mine to edit.") String mineName + ) { + + if (!performCheckMineExists(sender, mineName)) { + return; + } + + PrisonMines pMines = PrisonMines.getInstance(); + Mine m = pMines.getMine(mineName); + + + // Make a backup of the mine save file before making virtual: + File backupFile = pMines.getMineManager().backupMine( m ); + + String messageBu = "Mine &7" + m.getName() + " &3has " + + ( backupFile.exists() ? "been successfully" : "failed to be" ) + + " backed up: " + backupFile.getAbsolutePath(); + + if ( sender.isPlayer() ) { + sender.sendMessage( messageBu ); + } + Output.get().logInfo( messageBu ); + + } + + @Command(identifier = "mines set tracer", permissions = "mines.set", description = "Clear the mine and set a tracer around the outside") public void setTracerCommand(CommandSender sender, diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/managers/MineManager.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/managers/MineManager.java index 712f59ec7..2c03605e0 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/managers/MineManager.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/managers/MineManager.java @@ -17,6 +17,7 @@ package tech.mcprison.prison.mines.managers; +import java.io.File; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; @@ -378,6 +379,22 @@ public void saveMinesIfUnsavedBlockCounts() { } + /** + *

Creates a backup of a mine's save file. Similar to a virtual delete + * but is a copy. If used, has to be manually renamed. + *

+ * + * @param mine + */ + public File backupMine( Mine mine ) + { + File backupFile = coll.backup( mine.getName() ); + + return backupFile; + } + + + public void rename( Mine mine, String newName ) { @@ -1613,5 +1630,4 @@ public void reloadPlaceholders() { } - } From 596315cb2ca09af7ba444c75af0bcb12b47c2a43 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Thu, 2 Dec 2021 03:21:07 -0500 Subject: [PATCH 176/283] Versioned v3.2.11-alpha.9 --- docs/changelog_v3.3.x.md | 6 +++++- gradle.properties | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index a81e486fa..b53de25a2 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,11 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.8 2021-12-02 +# 3.2.11-alpha.9 2021-12-02 + + +* **3.2.11-alpha.9 2021-12-02** +Version v3.2.11-alpha.9 * **Added a new feature to back up a mine and to provide a way to convert a mine to a virtual mine.** diff --git a/gradle.properties b/gradle.properties index 9d3c6a288..2498661be 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ ## # This is actually the "correct" place to define the version for the project. ## # Used within build.gradle with ${project.version}. ## # Can be overridden on the command line: gradle -Pversion=3.2.1-alpha.3 -version=3.2.11-alpha.8 +version=3.2.11-alpha.9 #version=3.2.8.2 #version=3.3.0-alpha.6 From 409966839fb99434ee423e524e1bfce6bbfd4628 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sat, 4 Dec 2021 01:50:05 -0500 Subject: [PATCH 177/283] Move the messages for /mines tp to the language files. --- docs/changelog_v3.3.x.md | 5 +- .../resources/lang/mines/de_DE.properties | 10 ++- .../resources/lang/mines/en_US.properties | 10 ++- .../resources/lang/mines/es_ES.properties | 10 ++- .../resources/lang/mines/hu_HU.properties | 10 ++- .../resources/lang/mines/it_IT.properties | 10 ++- .../resources/lang/mines/nl_BE.properties | 10 ++- .../resources/lang/mines/nl_NL.properties | 10 ++- .../resources/lang/mines/zh_TW.properties | 10 ++- .../mines/commands/MinesCommandMessages.java | 73 +++++++++++++++++++ .../prison/mines/commands/MinesCommands.java | 20 +++-- .../mines/commands/MinesCoreCommands.java | 3 +- 12 files changed, 159 insertions(+), 22 deletions(-) create mode 100644 prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommandMessages.java diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index b53de25a2..9f24f3217 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,10 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.9 2021-12-02 +# 3.2.11-alpha.9 2021-12-04 + + +* **Move the messages for /mines tp to the language files.** * **3.2.11-alpha.9 2021-12-02** diff --git a/prison-core/src/main/resources/lang/mines/de_DE.properties b/prison-core/src/main/resources/lang/mines/de_DE.properties index 2fd6c1936..1ead9ee64 100644 --- a/prison-core/src/main/resources/lang/mines/de_DE.properties +++ b/prison-core/src/main/resources/lang/mines/de_DE.properties @@ -51,7 +51,7 @@ -messages__version=2 +messages__version=3 messages__auto_refresh=true @@ -88,3 +88,11 @@ block_not_removed=&7Dieser Block ist nicht in dieser Mine vorhanden. block_deleted=&7Block &3%1 &7von der Mine entfernt &3%2&7. mine_redefined=&7Erfolgreich die Mine &3neudefiniert &7. missing_world=&7Die Welt, in der die Mine erstellt wurde, kann nicht gefunden werden. + +mines_mtp__unable_to_teleport=Sorry. You're unable to teleport there. +mines_mtp__unable_to_teleport_others=&3You cannot teleport other players to a mine. Ignoring parameter. +mines_mtp__no_target_mine_found=No target mine found. &3Resubmit teleport request with a mine name. +mines_mtp__player_must_be_in_game=mines_mtp__player_must_be_in_game +mines_mtp__player_must_be_in_game=&3Specified player is not in the game so they cannot be teleported. +mines_mtp__cannot_use_virtual_mines=&cInvalid option. This mine is a virtual mine&7. Use &a/mines set area &7to enable the mine. +mines_mtp__teleport_failed=&3Telport failed. Are you sure you're a Player? diff --git a/prison-core/src/main/resources/lang/mines/en_US.properties b/prison-core/src/main/resources/lang/mines/en_US.properties index 5bb530070..3159ad152 100644 --- a/prison-core/src/main/resources/lang/mines/en_US.properties +++ b/prison-core/src/main/resources/lang/mines/en_US.properties @@ -51,7 +51,7 @@ -messages__version=2 +messages__version=3 messages__auto_refresh=true @@ -89,3 +89,11 @@ block_deleted=&7Removed block &3%1 &7from mine &3%2&7. mine_redefined=&7Successfully &3redefined &7the mine. missing_world=&7The world that the mine was created in can't be found. block_search_blank=&7Enter a value to search for a block.&7. + +mines_mtp__unable_to_teleport=Sorry. You're unable to teleport there. +mines_mtp__unable_to_teleport_others=&3You cannot teleport other players to a mine. Ignoring parameter. +mines_mtp__no_target_mine_found=No target mine found. &3Resubmit teleport request with a mine name. +mines_mtp__player_must_be_in_game=mines_mtp__player_must_be_in_game +mines_mtp__player_must_be_in_game=&3Specified player is not in the game so they cannot be teleported. +mines_mtp__cannot_use_virtual_mines=&cInvalid option. This mine is a virtual mine&7. Use &a/mines set area &7to enable the mine. +mines_mtp__teleport_failed=&3Telport failed. Are you sure you're a Player? diff --git a/prison-core/src/main/resources/lang/mines/es_ES.properties b/prison-core/src/main/resources/lang/mines/es_ES.properties index 12f9659fd..6cfa3b940 100644 --- a/prison-core/src/main/resources/lang/mines/es_ES.properties +++ b/prison-core/src/main/resources/lang/mines/es_ES.properties @@ -51,7 +51,7 @@ -messages__version=2 +messages__version=3 messages__auto_refresh=true @@ -88,3 +88,11 @@ block_not_removed=&7Ese bloque no se encuentra en esta mina. block_deleted=&7Se ha eliminado el bloque &3%1 &7de la mina &3%2&7. mine_redefined=&7Se ha &3redefinido &7la mina exitosamente. missing_world=&7El mundo en el que se ha creado la mina no se ha podido encontrar. + +mines_mtp__unable_to_teleport=Sorry. You're unable to teleport there. +mines_mtp__unable_to_teleport_others=&3You cannot teleport other players to a mine. Ignoring parameter. +mines_mtp__no_target_mine_found=No target mine found. &3Resubmit teleport request with a mine name. +mines_mtp__player_must_be_in_game=mines_mtp__player_must_be_in_game +mines_mtp__player_must_be_in_game=&3Specified player is not in the game so they cannot be teleported. +mines_mtp__cannot_use_virtual_mines=&cInvalid option. This mine is a virtual mine&7. Use &a/mines set area &7to enable the mine. +mines_mtp__teleport_failed=&3Telport failed. Are you sure you're a Player? diff --git a/prison-core/src/main/resources/lang/mines/hu_HU.properties b/prison-core/src/main/resources/lang/mines/hu_HU.properties index 842a9a2ef..53bdccfa7 100644 --- a/prison-core/src/main/resources/lang/mines/hu_HU.properties +++ b/prison-core/src/main/resources/lang/mines/hu_HU.properties @@ -51,7 +51,7 @@ -messages__version=2 +messages__version=3 messages__auto_refresh=true @@ -88,3 +88,11 @@ block_not_removed=&7Ez a blokk nem ebben a bányában van. block_deleted=&7A blokk törölve &3%1 &7a(z) &3%2&7 bányából. mine_redefined=&7A bányát sikeresen &3újradefiniálta&7. missing_world=&7Nem található meg a világ, amelyet a bányát hoztak létre. + +mines_mtp__unable_to_teleport=Sorry. You're unable to teleport there. +mines_mtp__unable_to_teleport_others=&3You cannot teleport other players to a mine. Ignoring parameter. +mines_mtp__no_target_mine_found=No target mine found. &3Resubmit teleport request with a mine name. +mines_mtp__player_must_be_in_game=mines_mtp__player_must_be_in_game +mines_mtp__player_must_be_in_game=&3Specified player is not in the game so they cannot be teleported. +mines_mtp__cannot_use_virtual_mines=&cInvalid option. This mine is a virtual mine&7. Use &a/mines set area &7to enable the mine. +mines_mtp__teleport_failed=&3Telport failed. Are you sure you're a Player? diff --git a/prison-core/src/main/resources/lang/mines/it_IT.properties b/prison-core/src/main/resources/lang/mines/it_IT.properties index 2a8d984cd..293a87e32 100644 --- a/prison-core/src/main/resources/lang/mines/it_IT.properties +++ b/prison-core/src/main/resources/lang/mines/it_IT.properties @@ -51,7 +51,7 @@ -messages__version=2 +messages__version=3 messages__auto_refresh=true @@ -88,3 +88,11 @@ block_not_removed=&7Quel blocco non è in quella miniera. block_deleted=&7Rimosso il blocco &3%1 &7dalla miniera &3%2&7. mine_redefined=&7E' con successo stata &3ridefinita &7la miniera. missing_world=&7Il mondo nel quale è stata creata la miniera non è stato trovato. + +mines_mtp__unable_to_teleport=Sorry. You're unable to teleport there. +mines_mtp__unable_to_teleport_others=&3You cannot teleport other players to a mine. Ignoring parameter. +mines_mtp__no_target_mine_found=No target mine found. &3Resubmit teleport request with a mine name. +mines_mtp__player_must_be_in_game=mines_mtp__player_must_be_in_game +mines_mtp__player_must_be_in_game=&3Specified player is not in the game so they cannot be teleported. +mines_mtp__cannot_use_virtual_mines=&cInvalid option. This mine is a virtual mine&7. Use &a/mines set area &7to enable the mine. +mines_mtp__teleport_failed=&3Telport failed. Are you sure you're a Player? diff --git a/prison-core/src/main/resources/lang/mines/nl_BE.properties b/prison-core/src/main/resources/lang/mines/nl_BE.properties index c977e7f5b..64f5480bf 100644 --- a/prison-core/src/main/resources/lang/mines/nl_BE.properties +++ b/prison-core/src/main/resources/lang/mines/nl_BE.properties @@ -51,7 +51,7 @@ -messages__version=2 +messages__version=3 messages__auto_refresh=true @@ -86,3 +86,11 @@ block_not_removed=&7Die blok kon niet verwijderd worden. block_deleted=&7Blok &3%1 verwijderd &7van mijn &3%2&7. mine_redefined=&7Succesvol de mijn &3geherdefineerd. missing_world=&7De wereld van deze mijn kon niet worden gevonden. + +mines_mtp__unable_to_teleport=Sorry. You're unable to teleport there. +mines_mtp__unable_to_teleport_others=&3You cannot teleport other players to a mine. Ignoring parameter. +mines_mtp__no_target_mine_found=No target mine found. &3Resubmit teleport request with a mine name. +mines_mtp__player_must_be_in_game=mines_mtp__player_must_be_in_game +mines_mtp__player_must_be_in_game=&3Specified player is not in the game so they cannot be teleported. +mines_mtp__cannot_use_virtual_mines=&cInvalid option. This mine is a virtual mine&7. Use &a/mines set area &7to enable the mine. +mines_mtp__teleport_failed=&3Telport failed. Are you sure you're a Player? diff --git a/prison-core/src/main/resources/lang/mines/nl_NL.properties b/prison-core/src/main/resources/lang/mines/nl_NL.properties index c977e7f5b..64f5480bf 100644 --- a/prison-core/src/main/resources/lang/mines/nl_NL.properties +++ b/prison-core/src/main/resources/lang/mines/nl_NL.properties @@ -51,7 +51,7 @@ -messages__version=2 +messages__version=3 messages__auto_refresh=true @@ -86,3 +86,11 @@ block_not_removed=&7Die blok kon niet verwijderd worden. block_deleted=&7Blok &3%1 verwijderd &7van mijn &3%2&7. mine_redefined=&7Succesvol de mijn &3geherdefineerd. missing_world=&7De wereld van deze mijn kon niet worden gevonden. + +mines_mtp__unable_to_teleport=Sorry. You're unable to teleport there. +mines_mtp__unable_to_teleport_others=&3You cannot teleport other players to a mine. Ignoring parameter. +mines_mtp__no_target_mine_found=No target mine found. &3Resubmit teleport request with a mine name. +mines_mtp__player_must_be_in_game=mines_mtp__player_must_be_in_game +mines_mtp__player_must_be_in_game=&3Specified player is not in the game so they cannot be teleported. +mines_mtp__cannot_use_virtual_mines=&cInvalid option. This mine is a virtual mine&7. Use &a/mines set area &7to enable the mine. +mines_mtp__teleport_failed=&3Telport failed. Are you sure you're a Player? diff --git a/prison-core/src/main/resources/lang/mines/zh_TW.properties b/prison-core/src/main/resources/lang/mines/zh_TW.properties index 617beeefd..1d85f0401 100644 --- a/prison-core/src/main/resources/lang/mines/zh_TW.properties +++ b/prison-core/src/main/resources/lang/mines/zh_TW.properties @@ -51,7 +51,7 @@ -messages__version=3 +messages__version=4 messages__auto_refresh=true @@ -89,3 +89,11 @@ block_deleted=&7將方塊 &3%1 &7從礦場 &3%2 &7中刪除 mine_redefined=&7成功 &3重新宣告 &7礦場 missing_world=&7無法找到已經建立礦場的世界 block_search_blank=&7請輸入值以搜索方塊。&7 + +mines_mtp__unable_to_teleport=Sorry. You're unable to teleport there. +mines_mtp__unable_to_teleport_others=&3You cannot teleport other players to a mine. Ignoring parameter. +mines_mtp__no_target_mine_found=No target mine found. &3Resubmit teleport request with a mine name. +mines_mtp__player_must_be_in_game=mines_mtp__player_must_be_in_game +mines_mtp__player_must_be_in_game=&3Specified player is not in the game so they cannot be teleported. +mines_mtp__cannot_use_virtual_mines=&cInvalid option. This mine is a virtual mine&7. Use &a/mines set area &7to enable the mine. +mines_mtp__teleport_failed=&3Telport failed. Are you sure you're a Player? diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommandMessages.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommandMessages.java new file mode 100644 index 000000000..6281b61fd --- /dev/null +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommandMessages.java @@ -0,0 +1,73 @@ +package tech.mcprison.prison.mines.commands; + +import tech.mcprison.prison.commands.BaseCommands; +import tech.mcprison.prison.internal.CommandSender; +import tech.mcprison.prison.mines.PrisonMines; + +public class MinesCommandMessages + extends BaseCommands +{ + + public MinesCommandMessages( String cmdGroup ) + { + super( cmdGroup ); + } + + protected void exampleMsg( CommandSender sender, String mineName ) { + PrisonMines.getInstance().getMinesMessages() + .getLocalizable( "mines_mtp__" ) + .withReplacements( + mineName ) + .sendTo( sender ); + } + + protected void teleportUnableToTeleportMsg( CommandSender sender ) { + // Sorry. You're unable to teleport there. + PrisonMines.getInstance().getMinesMessages() + .getLocalizable( "mines_mtp__unable_to_teleport" ) + .sendTo( sender ); + } + + protected void teleportCannotTeleportOtherPlayersMsg( CommandSender sender ) { + // &3You cannot teleport other players to a mine. Ignoring parameter. + PrisonMines.getInstance().getMinesMessages() + .getLocalizable( "mines_mtp__unable_to_teleport_others" ) + .sendTo( sender ); + } + + protected void teleportNoTargetMineFoundMsg( CommandSender sender ) { + // No target mine found. &3Resubmit teleport request with a mine name. + PrisonMines.getInstance().getMinesMessages() + .getLocalizable( "mines_mtp__no_target_mine_found" ) + .sendTo( sender ); + } + + protected void teleportPlayerMustBeIngameMsg( CommandSender sender ) { + // &3The player must be in the game. + PrisonMines.getInstance().getMinesMessages() + .getLocalizable( "mines_mtp__player_must_be_in_game" ) + .sendTo( sender ); + } + + protected void teleportNamedPlayerMustBeIngameMsg( CommandSender sender ) { + // &3Specified player is not in the game so they cannot be teleported. + PrisonMines.getInstance().getMinesMessages() + .getLocalizable( "mines_mtp__player_must_be_in_game" ) + .sendTo( sender ); + } + + protected void teleportCannotUseVirtualMinesMsg( CommandSender sender ) { + // &cInvalid option. This mine is a virtual mine&7. Use &a/mines set area &7to enable the mine. + PrisonMines.getInstance().getMinesMessages() + .getLocalizable( "mines_mtp__cannot_use_virtual_mines" ) + .sendTo( sender ); + } + + protected void teleportFailedMsg( CommandSender sender ) { + // &3Telport failed. Are you sure you're a Player? + PrisonMines.getInstance().getMinesMessages() + .getLocalizable( "mines_mtp__teleport_failed" ) + .sendTo( sender ); + } + +} diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java index 2272d1142..310016bfc 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommands.java @@ -2822,8 +2822,7 @@ public void mineTp(CommandSender sender, if ( m == null ) { - sender.sendMessage( "&cNo target mine found. " + - "&3Resubmit teleport request with a mine name." ); + teleportNoTargetMineFoundMsg( sender ); return; } } @@ -2841,7 +2840,7 @@ public void mineTp(CommandSender sender, if ( m.isVirtual() ) { - sender.sendMessage( "&cInvalid option. This mine is a virtual mine&7. Use &a/mines set area &7to enable the mine." ); + teleportCannotUseVirtualMinesMsg( sender ); return; } @@ -2852,13 +2851,14 @@ public void mineTp(CommandSender sender, if ( playerName != null && playerName.trim().length() > 0 && playerAlt == null) { - sender.sendMessage( "&3Specified player is not in the game so they cannot be teleported." ); + teleportNamedPlayerMustBeIngameMsg( sender ); return; } if ( (player == null || !player.isOnline()) && playerAlt != null && !playerAlt.isOnline() ) { - sender.sendMessage( "&3The player must be in the game." ); + + teleportPlayerMustBeIngameMsg( sender ); return; } @@ -2884,7 +2884,7 @@ else if ( (player == null || !player.isOnline()) && playerAlt != null && playerA } else if ( playerAlt != null && !player.getName().equalsIgnoreCase( playerAlt.getName() ) ) { - sender.sendMessage( "&3You cannot teleport other players to a mine. Ignoring parameter." ); + teleportCannotTeleportOtherPlayersMsg( sender ); return; } @@ -2897,8 +2897,7 @@ else if ( playerAlt != null && !player.getName().equalsIgnoreCase( playerAlt.get if ( m == null ) { - sender.sendMessage( "&cNo target mine found. " + - "&3Resubmit teleport request with a mine name." ); + teleportNoTargetMineFoundMsg( sender ); return; } } @@ -2908,7 +2907,7 @@ else if ( playerAlt != null && !player.getName().equalsIgnoreCase( playerAlt.get // NOTE: Mine.hasTPAccess() checks for rank access and also if they have perms set. if ( !isOp && !m.hasTPAccess( player ) ) { - Output.get().sendError(sender, "Sorry. You're unable to teleport there." ); + teleportUnableToTeleportMsg( sender ); return; } @@ -2934,8 +2933,7 @@ else if ( playerAlt != null && !player.getName().equalsIgnoreCase( playerAlt.get teleportPlayer( (Player) sender, m, target ); // m.teleportPlayerOut( (Player) sender, target ); } else { - sender.sendMessage( - "&3Telport failed. Are you sure you're a Player?"); + teleportFailedMsg( sender ); } } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCoreCommands.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCoreCommands.java index 7df0488da..7e82c09a5 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCoreCommands.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCoreCommands.java @@ -1,12 +1,11 @@ package tech.mcprison.prison.mines.commands; -import tech.mcprison.prison.commands.BaseCommands; import tech.mcprison.prison.internal.CommandSender; import tech.mcprison.prison.mines.PrisonMines; import tech.mcprison.prison.util.Text; public class MinesCoreCommands - extends BaseCommands + extends MinesCommandMessages { private Long confirmTimestamp; From b5443e3783608981af55b32a0a80671dd1348d27 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sat, 4 Dec 2021 01:52:24 -0500 Subject: [PATCH 178/283] Slight adjustment to the mine backups's file name. --- docs/changelog_v3.3.x.md | 3 +++ .../java/tech/mcprison/prison/file/FileVirtualDelete.java | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 9f24f3217..15d008a4a 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.9 2021-12-04 +* **Slight adjustment to the mine backups's file name.** + + * **Move the messages for /mines tp to the language files.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/file/FileVirtualDelete.java b/prison-core/src/main/java/tech/mcprison/prison/file/FileVirtualDelete.java index 1e985a439..5be2b65a6 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/file/FileVirtualDelete.java +++ b/prison-core/src/main/java/tech/mcprison/prison/file/FileVirtualDelete.java @@ -18,7 +18,7 @@ public abstract class FileVirtualDelete { public static final String FILE_LOGICAL_DELETE_PREFIX = ".deleted_"; - public static final String FILE_LOGICAL_BACKUP_PREFIX = ".backup"; + public static final String FILE_LOGICAL_BACKUP_PREFIX = ".backup_"; public FileVirtualDelete() { @@ -56,7 +56,7 @@ protected boolean virtualDelete( File source ) protected File virtualBackup( File source ) { SimpleDateFormat sdf = new SimpleDateFormat("_yyyy-MM-dd_HH-mm-ss"); - String name = FILE_LOGICAL_BACKUP_PREFIX + source.getName() + sdf.format( new Date() ) + ".del"; + String name = FILE_LOGICAL_BACKUP_PREFIX + source.getName() + sdf.format( new Date() ) + ".bu"; File backupFile = new File( source.getParentFile(), name); try { From c0483e318b58154db0a34992addcdea67ae54df6 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sat, 4 Dec 2021 01:55:02 -0500 Subject: [PATCH 179/283] Bug fix: One of the blockEvent placeholders was inserting the wrong value. {blocksMinedTotal} was inserted the blockName. --- docs/changelog_v3.3.x.md | 4 ++++ .../java/tech/mcprison/prison/mines/data/MineScheduler.java | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 15d008a4a..b9c967cc9 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.9 2021-12-04 +* **Bug fix: One of the blockEvent placeholders was inserting the wrong value.** +{blocksMinedTotal} was inserted the blockName. + + * **Slight adjustment to the mine backups's file name.** diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineScheduler.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineScheduler.java index 79c17d3a8..240fd0143 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineScheduler.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineScheduler.java @@ -620,7 +620,7 @@ private void processBlockEventDetails( Player player, PrisonBlock prisonBlock, cmdTask.addCustomPlaceholder( CustomPlaceholders.blocksPlaced, Integer.toString( originalBlock.getBlockPlacedCount() )); cmdTask.addCustomPlaceholder( CustomPlaceholders.blockRemaining, Long.toString( originalBlock.getBlockCountUnsaved() )); - cmdTask.addCustomPlaceholder( CustomPlaceholders.blocksMinedTotal, originalBlock.getBlockName() ); + cmdTask.addCustomPlaceholder( CustomPlaceholders.blocksMinedTotal, Long.toString( originalBlock.getBlockCountSession() ) ); cmdTask.addCustomPlaceholder( CustomPlaceholders.mineBlocksRemaining, Integer.toString( getRemainingBlockCount() )); cmdTask.addCustomPlaceholder( CustomPlaceholders.mineBlocksRemainingPercent, Double.toString( getPercentRemainingBlockCount() ) ); From 5e4dbeee846828b15a7690a98aa44215f5346ee7 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sat, 4 Dec 2021 02:06:04 -0500 Subject: [PATCH 180/283] Updates some documents. --- docs/changelog_v3.3.x.md | 3 + .../images/prison_docs_115_blockevents_01.png | Bin 0 -> 13457 bytes .../images/prison_docs_115_blockevents_02.png | Bin 0 -> 50912 bytes docs/knownissues_v3.3.x.md | 210 +++++++++++++++--- ...son_docs_010_setting_up_a_spigot_server.md | 39 ++-- ...rison_docs_012_setting_up_prison_basics.md | 110 +++++++-- docs/prison_docs_013_Prison_Help.md | 95 +++++--- docs/prison_docs_115_using_BlockEvents.md | 155 ++++++++++++- docs/prison_docs_117_setting_up_backpacks.md | 5 + docs/prison_docs_310_guide_placeholders.md | 119 +++++++--- 10 files changed, 607 insertions(+), 129 deletions(-) create mode 100644 docs/images/prison_docs_115_blockevents_01.png create mode 100644 docs/images/prison_docs_115_blockevents_02.png diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index b9c967cc9..e70e1e9e9 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.9 2021-12-04 +* **Updates some documents.** + + * **Bug fix: One of the blockEvent placeholders was inserting the wrong value.** {blocksMinedTotal} was inserted the blockName. diff --git a/docs/images/prison_docs_115_blockevents_01.png b/docs/images/prison_docs_115_blockevents_01.png new file mode 100644 index 0000000000000000000000000000000000000000..2adab6b28fb25e9d542cffee5dbbb287f999496d GIT binary patch literal 13457 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 literal 0 HcmV?d00001 diff --git a/docs/images/prison_docs_115_blockevents_02.png b/docs/images/prison_docs_115_blockevents_02.png new file mode 100644 index 0000000000000000000000000000000000000000..20c7c4d76ca37445202a8f5579d379abf0c227b5 GIT binary patch literal 50912 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 Xy?G8wxyC!seut8R`lC`gvzPx1<(Hz5 literal 0 HcmV?d00001 diff --git a/docs/knownissues_v3.3.x.md b/docs/knownissues_v3.3.x.md index b0747c03e..d740c7c73 100644 --- a/docs/knownissues_v3.3.x.md +++ b/docs/knownissues_v3.3.x.md @@ -3,43 +3,162 @@ # Prison Known Issues and To Do's for v3.3.x +# TODO Items for v3.2.11-alpha.7 -# TODOs for v3.2.10 release: -1. DONE: Final testing of ladder rank multipliers -2. DONE: /ranks ladder moveRank not working -3. DONE: Forced global refresh of rank multipliers when a ladder multiplier is changed. - - Should be simple - - Run as async task - - DONE: Force update when updating a ladder's multiplier - all players - - DONE: Force update when changing ranks - only targeted player -4. DONE: Add ladder base cost multiplier to /ranks autoConfigure. Start with a simple 10%. - - Include message that it's enabled and how to change it or disable it: - - /ranks ladder rankCostMultiplier prestiges 0 -5. Add to /ranks player the detail information on rank cost multipliers -6. DONE: For '/ranks autoConfigure' add an alias to '/prison autoConfigure' +* New documentation - Madog's knowledge + - look for pins -7. DONE: Change /ranks list so if non-op it does not show all the extra details. A simplified list for plain players. -8. Liners: Some are only for later releases and do not work with 1.8.8. So need to setup something to restrict the liners that are not functional for the older releases of spigot. +* Add mine effects. See conversation with Madog. + - Use PlayerCache and existing utils. + - Simple to implement some features, including flying in a mine. -9. Hook up Prison's Explosion event. -### Others +* DONE: Revert a mine to a virtual mine. Maybe with the command: `/mines set area *virtual*`. Backup the mine's data file before updating and saving. + + +* DONE: the command /mines reset *all* is not working correctly. Could be an issue with the chaining not submitting the next reset since this is all done through async processes right now. + + +**List for v3.2.11 release:** + + +* Players need to be restructured. Move rank player object, or at least most of the core, to the core project so as to reduce the number of player types. + +* Cache player + - cache player's balance + - cache player's ranks... only prestiges, default + +* Top-n ranks + - total blocks mined + - total tokens earned (or currently has) + - balance + - highest rank: prestiges, default, balance + - most online time, or most mining time (which will probably be better) + + + +* DONE: Add a few more options to auto features for auto sell, such on full inventory. This was removed recently to stabilize some of the new code. + - Just refined what was already there. + + +* Issue with blocks. Explosions are creating "untouchable" blocks that cannot be included in other explosions. + - My observations were with multiple explosions leaving rings that are within the the radius of an explosion + - I could break the blocks. + - jamo said that the pillars that were created on his server could not be broke + + +* DONE: Concurrent modification error on the MineTargetPrisonBlock when resetting the mine. + tech.mcprison.prison.spigot.game.SpigotWorld.setBlocksSynchronously() (146). + Serialize Id the mine resets and provide a locking mechanism that will prevent auto features from being processed when it goes in to a reset mode. Also when in a reset mode, prevent another reset from being submitted so they cannot run concurrently or back to back. Maybe attach a cooldown to the resets too, such as 10 seconds would be long enough to prevent a runaway chained reaction. + - DONE: Create an object such as a MineStateToken that will hold the state of the mine reset (in progress, mineable, stable, usable, locked, etc... not sure proper terminology right now... or how many states), with a serial number that will be incremented on each reset. + - (on hold) Do not perform a clear on the collection of MineTargetPrisonBlocks within the mine. Just replace the collection with a new collection and let the garbage collection handle reclaiming all resources. Carefully review for possible memory leaks. May be a good idea to hold on to that collection and submit a task that runs in about 30 seconds to perform a clear on the collection to release the resources. This may be important since the target blocks contains references to the stats blocks and may not be GC'd automatically. May want to null those refs first too. + MineReset.clearMineTargetPrisonBlocks() (1799) + + +* DONE: PlayerCache Time per Mine stats - not recording correctly. + +* Review placeholders - add and test placeholders that are tied to playerCache stats + +* DONE: new auto features autosell should place items in inventory that have no sell value. Items that cannot be auto sold. + +* Mine Bombs - Finish + - Add sound and particle effects + - Other features? + - Make sure the bomb is set within a mine. Do not allow it to be placed outside of a mine. + - DONE: When exploding large bombs with block decay, there is a chance that you can get the first block in the decay as part of the drops. + - DONE: Check to make sure the block broke is the one in the target block. If not, then ignore. + - make sure the block is not "locked" + + +* Add a top 10 listing commands + - Top player on server (rank / ladder) + - Top player per mine? + - Top Player per Blocks + - Top Player per time + +* Add Block & Time requirements for rankups + - Upon rankup, player will get a new "object" that would track rankup progress + - Would record current blocks and time for that rank, which is needed for when they + prestige. The rankup Progress won't change until they rankup and it will be reset. + It's used to subtract from current stats to get "progress". + +* BackPacks & Vaults & Warehouses - rewrite + - Add PlayerCache support with integrated backpack data object to track details + - Create new gradle module for backpacks and other items. Call it something like Accessories. + - Remove hooks in the spigot module except for the code to read existing old backpacks to migrate contents. + - Backpacks are able to have pickup and sell used against them. + - Vaults are protected from pickup and sell - Have to manually move items in and out to main inventory in order to sell them. Max size limit is a double chest. + - Backpacks can be protected from pickup and sell via command, which can be used to charge players. + - Warehouses are not normal player inventory/chests. They are virtual containers for items and blocks. + - Warehouses have slots, where each slot is one item. A slot can have a dynamic amount of items it can store. The player can buy more slots in their warehouse and increase the capacity of each slot. + - Warehouses - have formula to calculate costs of slots and capacity, where prices increase on both depending upon number of slots, and total capacity size of warehouse. + - Warehouses - Initial capacity of 5 slots, each at 100 to 200 capacity. + - Should vaults be tied to a physical location, such a server-wide "bank"? If so, then players has to physically go there to access their vaults. Same with warehouses. A defined bank or warehouse would be similar to a mine in such it would be 3d and access would work anywhere in there. Or a given mine could be designated as a bank or mine. So like for example, mine c could be the bank so a player would have to rank up to C to access it. Then a vault could be tied to a third tier prestige or something (but those don't have physical locations, but could make it mine a) or create a new mine that is empty, then link that new mine to that prestige rank so players have access to it. + + + + + + +* Mine reset messages: Have setting to control by percent remaining in the mine. + + +* Save files do not include the block type prefix. Such as used with CustomItems. +Not sure if it needs to? Need to test and confirm if working correctly. World coordinates would be wrong if missing. + + + +* DONE: New update to combine block processing results in many block.getDrops() being combined. Since they are combined, the extended fortune calculations may not work properly since it does not know how many original blocks were included. +- May need to have an intermediate object to better collect original blocks, drops, and targetBlocks. It can include some of the more basics that are not tracked, such as original block count to better calculate the fortunes. + + + +* DONE: Rewrite the `/prison utils titles` to use XSeries' title commands. XSeries only supports 1.9+ so I still need to support 1.8.8 directly within prison. + + + +* DONE: Common messaging framework so if hundreds of messages are sent, only one is displayed. Eliminate the duplicates. + + +- Not sure why the following would be needed: +* Auto Features Settings : Create an API object that has the auto features settings listed. Basically this would serve as a simple cache with a life span of about 10 seconds. So if a player is mining hundreds of blocks within 10 seconds, odds are these settings will not be changing... both server config settings, and the player's permissions. Can provide helper classes that will a simple check of all these details, such as passing tool in hand to check perms for auto pickup settings for the server, the player's perms and lore on the tool. ... as an example. +- Store in the player cache object, but make transient. Refresh every 10 to 15 seconds.. maybe even 30? +- Add to the auto features event so its available there +- Change function parameters to use the event and this new object as parameters... reduces number of parms... + + + + + +* Multi-language - Unable to create a custom language file that is not within the prison jar. It's been reported by Ingrosso that cannot create a new language file that does not match a file within the jar? + + +* BlockEvent processing queue - submit blockEvents to a job queue to run in another async thread... the individual commands would have to run in a sync thread. + - This will release the block break thread faster and won't contribute to lag. + + + + +* https://github.com/PrisonTeam/Prison/issues/222 + DecimalFormat not being used correctly in saving mine data so if different Locale is used, other than EN US, then parsing the saved file can result in a failure. + - MineBlockEvent is an example of where this was a problem + - The offending sections were corrected and should now work + + +* Add option to /ranks to rename a rank. Tag too? -* DONE: Add a rank cost multiplier to ladders. Sum all active ranks a player has to get the total multiplier to use for rank costs. -* DONE: Fix the "next rank" value with PlayerRanks.... needs to recalc with the new rank. -* DONE: When a ladder's rate cost multiplier is changed, need to recalculate all player's multipliers. Setup a task? # Start on mine bombs 1. Select size of bomb. Configuration. - 1a. Identify items to use as bombs - 1b. Bomb size - 1c. Bomb explosion pattern. Currently only sphere, but could include other shapes. + 1a. DONE: Identify items to use as bombs + 1b. DONE: Bomb size + 1c. DONE: Bomb explosion pattern. Currently only sphere, but could include other shapes. 2. DONE: Select list of blocks that will be effected by bomb explosion 3. Throw bomb, or place bomb... start processing count down. 4. Pre-fire effects: sound & particles (low priority) @@ -48,6 +167,8 @@ 7. Hook up prison's event handler for prison's explosion event + + * DONE: Modified /ranks list to provide this feature - Maybe provide a /rankcost command? Show current player rank costs with rank cost multipliers applied - /rankcost @@ -86,10 +207,6 @@ # **Possible bugs/issues:** -* DONE: /ranks ladder moveRank did not work to move from one ladder to another - -* DONE: When adding a new rank or mine, auto reload all placeholders so they pick up the new entry. - * Test BlockEvent perms... they appear like they don't work. * If ranks module fails due to no economy, try to make that a little more obvious. @@ -498,6 +615,45 @@ Offers for translation:
+# Features recently added for v3.2.10 + + +# TODOs for v3.2.10 release: + +1. DONE: Final testing of ladder rank multipliers +2. DONE: /ranks ladder moveRank not working +3. DONE: Forced global refresh of rank multipliers when a ladder multiplier is changed. + - Should be simple + - Run as async task + - DONE: Force update when updating a ladder's multiplier - all players + - DONE: Force update when changing ranks - only targeted player +4. DONE: Add ladder base cost multiplier to /ranks autoConfigure. Start with a simple 10%. + - Include message that it's enabled and how to change it or disable it: + - /ranks ladder rankCostMultiplier prestiges 0 +5. Add to /ranks player the detail information on rank cost multipliers +6. DONE: For '/ranks autoConfigure' add an alias to '/prison autoConfigure' + +7. DONE: Change /ranks list so if non-op it does not show all the extra details. A simplified list for plain players. + +8. DONE: Liners: Some are only for later releases and do not work with 1.8.8. So need to setup something to restrict the liners that are not functional for the older releases of spigot. + +9. DONE: Hook up Prison's Explosion event. + + +### Others + +* DONE: Add a rank cost multiplier to ladders. Sum all active ranks a player has to get the total multiplier to use for rank costs. +* DONE: Fix the "next rank" value with PlayerRanks.... needs to recalc with the new rank. +* DONE: When a ladder's rate cost multiplier is changed, need to recalculate all player's multipliers. Setup a task? + + + +* DONE: /ranks ladder moveRank did not work to move from one ladder to another + +* DONE: When adding a new rank or mine, auto reload all placeholders so they pick up the new entry. + + + # Features recently added since v3.2.9 diff --git a/docs/prison_docs_010_setting_up_a_spigot_server.md b/docs/prison_docs_010_setting_up_a_spigot_server.md index 12b635bf6..814fbc645 100644 --- a/docs/prison_docs_010_setting_up_a_spigot_server.md +++ b/docs/prison_docs_010_setting_up_a_spigot_server.md @@ -13,6 +13,7 @@ Buildtools also allows easy setup of many test environments since all you would need to do is to just change the version. +*Documented updated: 2021-12-03*
@@ -22,8 +23,9 @@ This is intended strictly as a high-level overview on how to setup Java. If you need more assistance, please search for online documentation since there are many good resources out there. -* First install a copy of Java that is accessible from the command line. - - It’s strongly suggested to use only the latest version 1.8.0_x since that is the version spigot and most other plugins are developed under. +* First install a copy of Java that is accessible from the command line. + - The current version of Java is version 17. Even if you are using jars and other plugins that were compiled with Java 1.8.x, it is recommended to use Java 17. + - If you feel like you must use Java 1.8, it’s strongly suggested to use only the latest version 1.8.0_x. * You can download it from [Sun SE Development Kit 8]https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html) for product that you need. @@ -48,18 +50,25 @@ there are many good resources out there. ``` java -jar BuildTools.jar --rev 1.8.8 + java -jar BuildTools.jar --rev 1.9.4 + java -jar BuildTools.jar --rev 1.10.2 + java -jar BuildTools.jar --rev 1.11 java -jar BuildTools.jar --rev 1.12.2 java -jar BuildTools.jar --rev 1.13.2 java -jar BuildTools.jar --rev 1.14.4 - java -jar BuildTools.jar --rev 1.15.1 + java -jar BuildTools.jar --rev 1.15.2 + java -jar BuildTools.jar --rev 1.16.5 + java -jar BuildTools.jar --rev 1.17.1 + java -jar BuildTools.jar --rev 1.18 ``` -* For example, with BuildTools.jar being in a root directory, create a subdirectory and then start a build within that directory. The benefit is that you can use the same BuildTools.jar to build multiple different versions of spigot. This example starts off with building a v1.14.4 instance and then builds a 1.8.8 instance. +* For example, with BuildTools.jar being in a root directory, create a subdirectory and then start a build within that directory. The benefit is that you can use the same BuildTools.jar to build multiple different versions of spigot. This example starts off with building a v1.17.1 instance and then builds a 1.8.8 instance. Normally you wouldn't build multiple versions of spigot, but this shows how easy and flexible it is to build any version of spigot that has been released. ``` - mkdir spigot-1.14.4 - cd spigot-1.14.4 - java -jar ../BuildTools.jar –rev 1.14.4 + mkdir spigot-1.17.1 + cd spigot-1.17.1 + java -jar ../BuildTools.jar –rev 1.17.1 + cd .. mkdir spigot-1.8.8 cd spigot-1.8.8 @@ -78,33 +87,35 @@ there are many good resources out there. # Creating a Runnable Spigot Server -* Create a runnable server directory by creating a new directory outside of the build directory. Then copy the newly generated jar file, such as spigot-1.14.4.jar, to the new server run time directory. +* Create a runnable server directory by creating a new directory outside of the build directory. Then copy the newly generated jar file, such as spigot-1.17.1.jar, to the new server run time directory. + +* NOTE: At the time when this document was updated, Spigot 1.18 was just released. Because 1.18 requires Java 17, it is advisable to use that version of Java. Prison, because it is still being ran on older servers and under older environments, it must try to support the widest array of Spigot versions; therefore it is built with the latest version of Java 1.8.x, and built using Spigot 1.13.2. The environments in which Prison is built, should not impact how you build and run your server, of which it could easily be with Java 17 and Spigot 18. * Windows example, if you’re still in the build directory: ``` cd ../.. - mkdir spigot-1.14.4_server - copy /B builds\spigot-1.14.4\spigot-1.14.4.jar spigot-1.14.4_server + mkdir spigot-1.17.1_server + copy /B builds\spigot-1.17.1\spigot-1.17.1.jar spigot-1.17.1_server ``` * Linux example, if you’re still in the build directory: ``` cd ../.. - mkdir spigot-1.14.4_server - cp builds/spigot-1.14.4/spigot-1.14.4.jar spigot-1.14.4_server + mkdir spigot-1.17.1_server + cp builds/spigot-1.17.1/spigot-1.17.1.jar spigot-1.17.1_server ``` -* Run the server for the first time (see the next step). It will start to auto-generate the server environment and then will stop. You will need to manually modify eula.txt and set eula=true. Save. Close. Restart the server. It will startup successfully now. +* Run the server for the first time (see the next step). It will start to auto-generate the server environment and then will stop. You will need to manually modify the `eula.txt` file and set `eula=true`. Save. Close. Restart the server. It will startup successfully now. * This is a simple example of what is needed for a windows cmd file. It sets the minimum memory to 2 GB and the max to 8 GB. A linux script would be similar, but without the pause. ``` - java -Xms2g -Xmx8g -jar spigot-1.14.4.jar + java -Xms2g -Xmx8g -jar spigot-1.17.1.jar pause ``` diff --git a/docs/prison_docs_012_setting_up_prison_basics.md b/docs/prison_docs_012_setting_up_prison_basics.md index 35b801f3b..1dcf09962 100644 --- a/docs/prison_docs_012_setting_up_prison_basics.md +++ b/docs/prison_docs_012_setting_up_prison_basics.md @@ -6,6 +6,9 @@ This document provides a quick overview on how to install Prison and get it running. + +*Documented updated: 2021-12-03* +
@@ -40,7 +43,7 @@ Setting up Prison is simple: * Prison's startup information contains a lot of information. If you ever have issues, check that information first since it probably will identify what the issues are. -* It is strongly suggested that `/ranks autoConfigure` is ran to initially setup your Prison environment. +* It is strongly suggested that `/ranks autoConfigure` is ran to initially setup your Prison environment. A great deal of configurations are setup that can save a lot of effort. Even if you are wanting to start from scratch, it may be worth giving it a try to see how some of the more complex settings are configured. You can always start over by deleting the `plugins/Prison/` directory. * Follow Prison's documentation on customization; at this point it's ready for use. @@ -54,13 +57,15 @@ Setting up Prison is simple: * **None - No hard dependencies** - There are no hard dependencies for Prison. -There may be no hard dependencies that will prevent Prison from running, but there are some core plugins that will make it easier to use. This short list is just a suggestion, but alternatives do exist and may be outside of our ability to comment or assist in their usage. +There may be no hard dependencies that will prevent Prison from running, but there are some core plugins that will make it easier to use, and are even required for activation of some features within Prison. This short list is just a suggestion, but alternatives do exist and may be outside of our ability to comment or assist in their usage. * **Vault** - Optional, but STRONGLY Suggested - This is perhaps the most important plugin. This plugin provides a common way to access other plugins running on your server, but without having to write any code within Prison to support them. Vault provides the mapping of a plugin's unique APIs to a common Vault API. Vault helps support Economy, Permissions, and Placeholders. Because of Vault, Prison can work flawlessly with dozens of other plugins. Please refer to Vault's documentation for what it supports. -* **EssentialsX** - **STRONGLY SUGGESTED**, but still Optional - Provides many of the basic commands and behaviors that you would expect from a Spigot server such as chat, warps, and even some moderation commands and commands that can be given to premium players. EssentialsX is not Essentials, since Essentials is an older abandoned project, and EssentialsX is a forked project that is still maintained. Unfortunately, internally it is identified as simply Essentials, but you can tell it's EssentialsX if the version is greater than 2.15.x. EssentialsX is released as a zip file and you must extract the jars that you are interested in. It should also be pointed out that all EssentialsX jars should come from the same zip file so they will be of the same version and the same release. +* **EssentialsX** - **STRONGLY SUGGESTED**, but still Optional - Provides many of the basic commands and behaviors that you would expect from a Spigot server such as chat, warps, and even some moderation commands and commands that can be given to premium players. EssentialsX is not Essentials, since Essentials is an older abandoned project, and EssentialsX is a forked project that is still maintained. Unfortunately, internally it is identified as simply Essentials, but you can tell it's EssentialsX if the version is greater than 2.15.x. + + EssentialsX is released as a zip file and you must extract the jars that you are interested in. It should also be pointed out that all EssentialsX jars should come from the same zip file so they will be of the same version and the same release. UPDATE: The last I checked EssentialsX may not be released in a single zip file anymore. It looks like you have to download the parts you are interested in using. ### Economy Plugins - Required @@ -68,15 +73,36 @@ There may be no hard dependencies that will prevent Prison from running, but the Prison requires an active economy in order to active the Ranks plugin. When Prison starts up, it performs many validations on the mines and ranks as they are being loaded. With Ranks, if Prison cannot find an active economy, then it will refuse to load the Ranks module due to possible server corruption (ie... what failed that there is no economy). -* **EssentialsX Economy** - SUGGESTED - Optional - This is a simple economy plugin that just works well. If you don't have a specific need to use another economy plugin, then it may be best to use this one since it works so well. +* **EssentialsX Economy** - SUGGESTED - Optional - This is a simple economy plugin that just works well. If you don't have a specific need to use another economy plugin, then it may be best to use this one since it works so well. The reason why we recommend this economy is because it always works. That said, we acknowledge the reason it works well, is because it is so simple, so if there are features in other economy plugins that you want to use on your sever, then please explore using them. But overall, if you just want an economy that is rock solid, then EssentialsX's Economy is a great choice. + + +* **CMI Economy** - Optional - Formerly we could not recommend its use, but Prison now has a couple of advanced tools that is able to allow CMI to fully load before Prison needs to use CMI's functions. Therefore if you want to use many of CMI's features, you now can! + + CMI "tries" to load last, thus it can ensure all of it's dependencies and hooks are in place before it starts up. That's understandable, and Prison also has similar requirements and expectations. Unfortunately, this also causes a conflict with Prison, since Prison must perform validation on startup, and if there is no economy, then Prison could fail to start. + + To get CMIE to work correctly with prison, there are a couple of things that you must do. + + 1) You must use the normal version of Vault and then use the CMI Vault Injector. We've never seen the CMI provided version of Vault work with prison, so therefore recommend not using it. Symptom is that prison reports a 0.00 amount for the online player when using `/ranks player `. The Vault inject has always worked well. + 2) The CMI Economy **has** to be fully loaded and active *before* prison loads the Ranks. Otherwise prison will refuse to load the ranks and prison will not work. You must make a configuration change within Prison's `plugins/Prison/config.yml` file. Near the bottom of that config, are a few settings that need to be enabled. The following is an example of what is needed, along with a configuration that will work in most situations. + +``` +delayedPrisonStartup: + enabled: true + cooldown-secs: 5 + max-attempts: 6 + inspect-vault: true + triggers: + vault: true + vault-economy-name: Economy_Essentials +``` + If enabled, and you are still having problems, please contact Blue on Prison's discord server. To get CMIE to work may be as simple as increasing the `cooldown-secs` or the `max-attempts` settings, but there could be another conflict going on. Blue can review your server's startup log to identify the problem and help you fix it. + -* **CMI Economy** - Not Suggested - CMI has a lot of really neat features, so it's totally understandable that you may want to use their economy too. But the reason why we do not suggest it's use is because it is difficult to get to work with prison for a few reasons. We will try to support your use of CMIE, but you will have to try to be proactive in trying to get it to work; if you just want "simple", then try EssentialsX Economy first. -1) You must use the normal Vault and then use the CMI Vault Injector. We've never seen the CMI provided version of Vault work with prison. Symptom is that prison reports a 0.00 amount for the player when using `/ranks player `. The Vault inject has always worked well. -2) The CMI Economy **has** to be fully loaded and active *before* prison loads the Ranks. Otherwise prison will refuse to load the ranks and prison will not work. It appears as if CMIE is purposefully delaying it's activation until all other plugins are finished loading; I'm sure there is a good reason for that, but it causes prison to fail. Setting up proper soft dependencies within Prison does not work. To address this serious issue, because we really want CMIE to work with Prison, there is a new setting that will actually delay prison's startup to give CMIE a chance to active. This new feature should not be used without a good reason since it alters Prison's startup processes, but it has shown to work very well. The configs are within the config.yml file, but talk to Blue *before* trying to enable it. +### Chat Prefix Plugins - Optional +These plugins are used to add rank tags to the player's chat messages that they send. -### Chat Plugins - Optional * **EssentialsX Chat** - Optional - Enhanced Chat experience. Provides customizations to the chat prefixes. @@ -95,36 +121,55 @@ Permission plugins are not *strictly* required for Prison to work, but within a Prison actually uses bukkit's permission interfaces. This makes it simple for Prison, but it also limits what prison can do. For example, one limitation is with permission groups; Prison is unable to resolve permission groups since that "concept" does not exist in bukkit, but is a concept that is implemented through plugins like PEX and LuckPerms. -* **LuckPerms** - Required - LuckPerms is a great permission plugin that is actively supported and has many new features to make managing your server easier. +* **LuckPerms** - Required - Strongly Suggested - LuckPerms is a great permission plugin that is actively supported and has many new features to make managing your server easier. -* **LuckPerms v5.x.x** - Use the latest version of LuckPerms whenever you can. Keep in mind that releases to spigotmc.org is somewhat infrequent; giving them the "counts" for downloads is nice, but you may have to go to their main download page to get the most recent releases: [https://luckperms.net/download](https://luckperms.net/download). Please note that is normal for issues to surface once in a while, and there were a few that needs to be avoided: The releases v5.3.0 through about v5.3.3 had some issues that caused significant logging and failures. +* **LuckPerms v5.x.x** - Use the latest version of LuckPerms whenever you can. Keep in mind that releases to spigotmc.org is somewhat infrequent; giving them the "counts" for downloads is nice, but you may have to go to their main download page to get the most recent releases: [https://luckperms.net/download](https://luckperms.net/download). Please note that it is normal for issues to surface once in a while, and there were a few that needs to be avoided: The releases v5.3.0 through about v5.3.3 had some issues that caused significant logging and failures. * **LuckPerms v4.x.x** This older version of LuckPerms is still supported, but it is highly recommended to upgrade to the latest v5.x.x release. LuckPerms v4.x.x is required for prison v3.2.0 and older (Prison v3.2.1 and newer supports all versions of LuckPerms). Please consider upgrading both Prison and LuckPerms to the latest releases for the best experience. -* **NOTE: A permissions plugin of your choice** - Required - Prison works with many different permission plugins through Vault. I strongly suggest LuckPerms since it is free and is under active development so bugs and performance issues will be addressed. If you choose to use another permission plugin, then please consider ones that work with Vault; Prison uses Vault provide the flexibility of choosing from many different plugins. +* **Gems Economy** - Gems Economy supports multiple currencies. Support for Gems Economy was added a few years ago and worked well at the time. If you try to use this plugin and have issues, please contact Blue on Prison's discord server so the issues can be addressed. + + +* **NOTE: A permissions plugin of your choice** - Required - Prison works with many different permission plugins through Vault. I strongly suggest LuckPerms since it is free and is under active development so bugs and performance issues will be addressed if they ever become an issue. If you choose to use another permission plugin, then please consider ones that work with Vault; Prison uses Vault to provide the flexibility of choosing from many different plugins. * **Other Permission Plugins** There are many out there, and as developer of Prison, and through providing support, we don't hear of any issues with other permission plugins. The reason for this is because they probably just work well to begin with, and that Prison uses bukkit's permission interfaces. So it keeps things simple for setting up Prison. If you are just getting started with building a server, then we suggested keeping it simple with something like LuckPerms, but there are other permission plugins out there that can provide a whole new experience with your server, such as jobs and careers for your players. + ### Placeholder Plugins -Chat related plugins provides access to Prison placeholders, but these placeholder plugins takes it to the next level and allows other plugins to access prison data. There are not many out there, mostly because papi is so simple and does it so well so there is no real need for other plugins. +Chat related plugins are able to provides access to Prison placeholders, which can allow Prison data to be included in their content. PAPI is simple and works so well, that it usually is the default choice. + + +The way a placeholder works, is that it is a text based **key** that is used to request data. Generally the key is included with other text, such as a chat message, holographic display, or a scoreboard content, and the key is replaced with the requested data. Usually the plugins using placeholders have no idea what other plugins are supplying the requested data; they basically make a general request for information to all plugins, and the plugins that recognize that **key** will respond. + + +It should be noted that Prison's placeholders are just text based keys. They are usually all lower case alpha numeric characters, with underscores, and maybe some colons too. The important thing to understand is that they do not include the escape characters, and that the escape characters may differ from what is required in other plugins. Placeholder escape characters are usually `{ }` or `% %`, and sometimes you may have to mix the two. The plugin's documentation should help you identify what's the correct usage. + +All prison placeholders start with `prison_` and are usually all lower case. Upper case may work too, but lower case is recommended. Prison tries to ignore the case of its placeholder keys, but its the other plugins that can have issues. For example, if Prison registers all of the plugins as lower case, then the other plugins may not recognize all upper case, or mixed case, as being related to Prison, so therefore they may not send the request to Prison. -It should be noted that Prison's placeholders do not include the escape characters, and they may vary in the other plugins that you use placeholders. Sometimes they may be { } or % %, and sometimes you may have to mix the two. The plugin's documentation should help you identify what's the correct usage. +An example of a prison placeholder is `prison_rank`. But used in another plugin, you will need to add escape characters such that it may be either `{prison_rank}` or `%prison_rank%`. Prison only controls what the text key is; prison cannot control which escape characters are used in another plugin. -* **PlaceholderAPI** - Strongly Suggested - Also known as papi. Used through Vault, it is free and provides the core interfaces in to the usage of placeholders. Prison also has a special integration setup for PlaceholderAPI to register all of the Prison placeholders dynamically upon startup. You do not need to download anything from the cloud for prison to work with this plugin. Also if you reload papi, you do not have to reload Prison's placeholders. Prison registers placeholders that are all lower case and more recently, all upper case too so it's easier to use placholders through papi. + +All of Prison's placeholders have an alias. An alias is a shortened name for a placeholder. Some placeholder names can become large based upon trying to keep their names informative as to what they represent. As an example, `prison_rank` has an alias of `prison_r`. And `prison_player_balance_earnings_per_minute_formatted` has an alias of `prison_pb_epmf` which can be useful if there is limited space in the configurations. The command `/prison placeholders list` shows all available placeholders, along with their aliases. + + +* **PlaceholderAPI** - Strongly Suggested - Also known as **papi**. Used through Vault, it is free and provides the core interfaces in to the usage of placeholders. Prison also has a special integration setup for PlaceholderAPI to register all of the Prison placeholders dynamically upon startup. You do not need to download anything from the cloud for prison to work with this plugin. Also if you reload papi, you do not have to reload Prison's placeholders. Prison registers placeholders that are all lower case and more recently, all upper case too so it's easier to use placeholders through papi. + + NOTE: You may also need to install the follow plugin for full support: ProtocolLib. * **MVdWPlaceholder** - Suggested to Avoid - Prison does support this plugin, but since it is used mostly with premium plugins, we have no way to fully test this plugin to ensure it actually works correctly. We've heard very few people have used this plugin, but we've heard it does work well. Use at your own risk. -With this plugin, all placeholders are registered with it automatically when prison starts up, and all placeholders should be used as all lower case. Because prison has so many plugins, with many that are expanded based upon ladders, ranks, and mine names, a modest prison server could generate and register well over 1000 placeholders. MVdWPlaceholder appears to be very verbose so you will see a lot of logging. -It should also be noted that because of some of the limitations of MVdW, not all features of Prison's placeholder support will be supported. For example, you may not be able to reload placeholders, or use placeholder attributes to customize how placeholders are used. +With this plugin, all placeholders are registered with it automatically when prison starts up, and all placeholders should be used as all lower case. Because prison has so many placeholders, with many that are expanded based upon ladders, ranks, and mine names, a modest prison server could generate and register well over 1000 placeholders. MVdWPlaceholder appears to be very verbose so you will see a lot of logging in the console when it starts up. + + It should also be noted that because of some of the limitations of MVdW, not all features of Prison's placeholder support will be supported. For example, you may not be able to reload placeholders, or use placeholder attributes to customize how placeholders are used. @@ -216,7 +261,7 @@ Some of the important details that are listed: * Which modules were successfully loaded * The root commands that are available * The integration status of all related plugins that are supported -* The list of active placeholders +* The list of active placeholders (removed due to size. see `/prison placeholders list`) * Startup error messages, if any. Examples would be if a rank is configured to use a custom currency and that currency cannot be found in any economy. @@ -230,7 +275,7 @@ custom currency and that currency cannot be found in any economy. If you are leasing a server from a hosting service you may not be able to customize the startup script. But if you have control over it, then the following information may help. -`java -Xdebug -Xms2g -Xmx4g -jar spigot-1.16.5.jar -nogui` +`java -Xms2g -Xmx4g -jar spigot-1.16.5.jar -nogui` Example of enabling debug hooks for the server. This is used with Eclipse, and may work with other IDEs since it's a java directive. @@ -274,6 +319,35 @@ through: ``` +# Prison Support Submit Information + +Prison now has a built in way to share your configurations and settings with support personnel. + +More information will be documented in the future, but for now, here are the basics on how to use it. + +When requested by the Prison support team, you would first enter the following command to set your name that will be included on all reports to help identify who the are related to. It doesn't have to be your full discord name, but enough characters to allow us to identify who you are. + + +These commands will collect all of the related information from your Prison setup, and send it to the website `https://paste.helpch.at`. It will provide you with an URL. All you need to do is to copy and paste that URL in to the discord chat so the Prison support team can help with your issue. + + +`/prison support setSupportName ` + +Once entered, it will enable the following submit tools: + +`/prison support submit` - Show the available tools. + +``` +/prison support submit configs +/prison support submit latestLogs +/prison support submit mines +/prison support submit ranks +/prison support submit version +``` + +Here is an example that I generated from one of my test servers on 2021-12-03. I have no idea how long the content remains available, but for support purposes, we only need this information for a few hours. + [https://paste.helpch.at/itejovejeh](https://paste.helpch.at/itejovejeh) + # Prison Commands diff --git a/docs/prison_docs_013_Prison_Help.md b/docs/prison_docs_013_Prison_Help.md index 4bddd8f26..f6d6bd04e 100644 --- a/docs/prison_docs_013_Prison_Help.md +++ b/docs/prison_docs_013_Prison_Help.md @@ -6,6 +6,9 @@ This document provides some important information on how to find help in setting up your prison server, and ultimately, how and where to ask for help. + +*Documented updated: 2021-12-03* +
# Overview @@ -20,19 +23,50 @@ If you are having problem, please take a quick look at the following documents a
+ +# Asking for Help + +Before you actually ask for help, take a look at some of the documents presented here. You may find your answer, or at least become a little more familiar with Prison. There is a good chance that if your question is a common one, then you will just be referred to this documentation anyway. + +When you do ask for help, please realize if you can provide a clear description of the problems you are experiencing, plus the versions of Prison, Spigot, etc, then we can help you faster and more accurately. To help provide you with answers to these questions, see the next section of this document for information on what you can copy and paste to provide all those much needed details. + + + +
+ + + +# Prison Command 'help' keyword + + +Prison has a very advanced command handler that provides a lot of advance features. But one simple feature to know about and to use is the use of the 'help' keyword. + + +If you add '**help**' to any command within prison, prison's command handler will show you information on what the command is, how to use it, parameters, how to get more help and details, and also what permissions are needed to use the command. + + +Prison automatically inserts the **help** keyword if you enter the base commands. So the command **/mines** is really the command handler recognizing there are many commands tied to the path '/mines' that it automatically injects the **help** keyword for you so it will generate the list. It's exactly the same as if you've entered **/mines help**. + + # General Information on Prison Commands + All of the commands for Prison can be ran in-game, and most can be ran from the console. When running commands from the console, you do not have to prefix the commands with a **/**. But within these documents, all commands will be referenced with a prefixed **/** so it is clear that it's a command. Just don't include it when running within the console. -Personal preference is to run the commands from the console since there are less restrictions on width or number of lines shown, and they are easier to see without the busy background of the game. -Within most of these documents, the console will be used to screen print from for those reasons. +My (Blue) personal preference is to run the commands from the console since there are less restrictions on width or number of lines shown, and they are easier to see without the busy background of the game. + + +Within most of these documents, the console will be used for screen prints for those reasons. + The only commands that cannot be ran from the console are the commands that expect you to be an in-game player. Examples are **/mines whereami** and **/mines tp **. But note, you can now run the TP command from the console if you supply the name of an online player: **/mines tp **. + If you need to do some maintenance, or configurating of your Prison, the console could be an easier environment to use. -But in-game, some commands have clickable actions. Such as page next or page prior. Or even command completion, such as with **/mines block search** and clicking on a search result provides you with a filled in copy of **/mines block add** where all you need to do is just fill in the percentage since it uses the last mine name that has been used. + +But in-game, some commands have clickable actions such as **page next** or **page prior**. Or even command completion, such as with **/mines block search** and clicking on a search result provides you with a filled in copy of **/mines block add** where all you need to do is just fill in the percentage since it uses the last mine name that has been used.
@@ -43,14 +77,16 @@ But in-game, some commands have clickable actions. Such as page next or page pr It may be helpful to know what commands are available, and what options exist for those commands. +Prison's command handler not only understands what commands have been registered within Prison, but it has awareness of what parameters are needed, and what permissions some commands are required. The command handler is able to provide a lot of information if you know a few basic things. -**Note: the details below still apply, but are slightly out of date.** The best way to start exploring all commands within prison is to start with `/prison` which will list all subcommands related to `/prison`, but also will show all other root commands and aliases. +Prison's commands are based upon a hierarchy of commands, which groups them by context. If you enter a lower command in the hierarchy that includes sub commands, then Prison will list them. This is a great way to explore what commands are available within Prison. -Upon startup, prison lists many details about the environment, and one set of those details, are the base commands that are available within Prison. See the area pertaining to the modules, since the commands generally are tied to modules. +The best starting point is with the root command `/prison`. Not only is that the root command for everything that starts with `/prison`, but it has special behavior in that it also includes all other command roots. So if a command exists in prison, you can find it through starting with `/prison` and exploring their children. -Prison Commands + +Some of the root commands that are important to know: `/prison`, `/mines`, `/ranks`, `/rankup`, `/gui`, `/sellall`. Many commands within prison are compound commands, such that they start with a base command, followed by one or more other commands. When Prison lists the available commands, if there are sub commands, that information is included in the command listing, including the sub command count. For example: @@ -73,8 +109,6 @@ Let's take a closer look at **/mines set notification** and how the **help** key But notice within the above screen print, the same command has been entered, but this time with the keyword **help** added as if it were the first parameter. For example, **/mines set notification help**. Prison recognizes that you are requesting help for that command, and then it displays all of the information it has for each parameter. -Prison automatically inserts the **help** keyword if you enter the base commands. So **/mines** is really injecting the **help** keyword for you so it will generate the list. It's like you've entered **/mines help**. -
@@ -95,40 +129,42 @@ You can also submit a help ticket on the Prison github Issues tab, but the respo -# Asking for Help - -Before you actually ask for help, take a look at some of the documents presented here. You may find your answer, or at least become a little more familiar with Prison. There is a good chance that if your question is a common one, then you will just be referred to this documentation anyway. - -When you do ask for help, please realize if you can provide a clear description of the problems you are experiencing, plus the versions of Prison, Spigot, etc, then we can help you faster and more accurately. To help provide you with answers to these questions, see the next section of this document for information on what you can copy and paste to provide all those much needed details. - - - -
- - # Prison Debugger Prison has been evolving to provide many new features, but as a result, it's also becoming very complex in some areas. To help address these greater complexities, Prison has some debugging details that can be dynamically enabled. These can help identify what's happening and provide hints as to what may be the trouble. -New targets will be added to Prison overtime. So check with the command for the latests updates for the version that you are using. +New targets will be added to Prison overtime. So check with the command for the latest updates for the version that you are using. To enable the debugger, you can toggle them all on with `/prison debug` once to turn it on, and again to turn them all off. + To review the options available, use the command `/prison debug help`. There are also debug targets that only enable specific debug statements and the list of the available targets can be displayed with `/prison debug targets`. + ``` >prison debug help -[21:07:00 INFO]: For internal use only. Do not use unless instructed. -[21:07:00 INFO]: /prison debug [targets] -[21:07:00 INFO]: [targets] Enable or disable a debugging target. Use 'targets' to list all available targets. Use 'on' or 'off' to toggle on and off individual targets, or all targets if no target is specified. -[21:07:00 INFO]: Permissions: -[21:07:00 INFO]: prison.debug +[12:16:39 INFO]: ---------- < Cmd: /prison debug > ------------- (3.2.11-alpha.9) +[12:16:39 INFO]: Enables debugging and trouble shooting information. For internal use only. Do not use unless instructed. +[12:16:39 INFO]: /prison debug [targets] +[12:16:39 INFO]: [targets] Optional. Enable or disable a debugging target. [on, off, targets, jarScan, testPlayerUtil, testLocale, rankup] Use 'targets' to list all available targets. Use 'on' or 'off' to toggle on and off individual targets, or all targets if no target is specified. jarScan will identify what Java version compiled the class files within the listed jars +[12:16:39 INFO]: Permissions: +[12:16:39 INFO]: prison.debug + + >prison debug targets -[21:08:21 INFO]: Global Debug Logging is enabled -[21:08:21 INFO]: . Valid Targets: all, on, off, blockBreak, blockBreakFortune, durability +[12:17:19 INFO]: Global Debug Logging is enabled +[12:17:19 INFO]: . Valid Targets: all, on, off, blockBreak, blockBreakFortune, rankup, support + +>prison debug +[12:18:18 INFO]: Global Debug Logging is enabled +[12:18:18 INFO]: . Valid Targets: all, on, off, blockBreak, blockBreakFortune, rankup, support + +>prison debug +[12:18:20 INFO]: Global Debug Logging is disabled +[12:18:20 INFO]: . Valid Targets: all, on, off, blockBreak, blockBreakFortune, rankup, support ``` It should be noted that every time you use the command, other than with the help keyword, it will always show the current status of the debugging information. It will show if the global logging is enabled or not, and if any targets are enabled, it will list all of the active ones. Plus it will show all of the available targets too. @@ -359,4 +395,9 @@ Once you are running Prison v3.x.x then you can safely upgrade to Prison v3.2.0,
+**Obsolete Screen Prints:** +Prison Commands + + +
diff --git a/docs/prison_docs_115_using_BlockEvents.md b/docs/prison_docs_115_using_BlockEvents.md index 65e55fcf5..c0f374bf2 100644 --- a/docs/prison_docs_115_using_BlockEvents.md +++ b/docs/prison_docs_115_using_BlockEvents.md @@ -13,11 +13,52 @@ A single BlockEvent can also have more than one command that is ran together wit BlockEvents have a taskMode that defines how the specified commands are to be ran. +*Documented updated: 2021-12-03* +
+# BlockEvent Commands + +BlockEvents can be access through the command prefixes of: + +`/mines blockEvent` + +There are 9 sub-commands, which includes add and list, which are probably the most important of the commands. + + +BlockEvent Sub-Commands + + +In the above screen print, the sub-commands have as a parameter named **row**. See the next section in this document for more information. + + +The BlockEvent listings can also be included in the following command by including the keyword **all**: +`/mines info all` + + +## Use of Row Numbers In The BlockEvent Commands: + + Due to the complexity of the blockEvent commands being deeply nested, and there could be so many of them, many of the blockEvent commands uses a **Row** identifier. This row identifier is based upon the order of the commands as listed under the `/mines blockEvent list` command. + +A number of examples of a few different blockEvets is as follows. Emphasis is on the row numbers. + +BlockEvent Sub-Commands + + + + + # BlockEvents Placeholders -Within the BlockEvents commands you can use placeholders and Prison will substitute the correct values for you. +Within the BlockEvents commands you can use placeholders and Prison will substitute the correct values within the commands. + + +For a current list of all blockEvent commands use **placeholders** keyword with the **add** command: + +`/mines blockEvent add placeholders` + + +`{player} {player_uid} {msg} {broadcast} {title} {actionBar} {inline} {inlinePlayer} {sync} {syncPlayer} {blockName} {mineName} {locationWorld} {locationX} {locationY} {locationZ} {coordinates} {worldCoordinates} {blockCoordinates} {blockChance} {blockIsAir} {blocksPlaced} {blockRemaining} {blocksMinedTotal} {mineBlocksRemaining} {mineBlocksRemainingPercent} {mineBlocksTotalMined} {mineBlocksSize} {blockMinedName} {blockMinedNameFormal} {blockMinedBlockType} {eventType} {eventTriggered} {utilsDecay}` - **{player}** Provides the player's name. @@ -32,22 +73,124 @@ Prison's BlockEvents also supports more advanced placeholders that can help simp - **{msg}** Send a message to the player. This is a shortcut for the prison command: `/prison utils msg`. Example: `{msg} Congrats! You found a token!`. -- **{broadcast}** Sends a broadcast message to all players on the server. this is a shortcut for the prison command: `/prison utils broadcast`. Example: `{broadcast} {player} found a treasure trove of 100 voter keys!`. +- **{broadcast}** Sends a broadcast message to all players on the server. Just use this placeholder followed by the message. This is a shortcut for the prison command: `/prison utils broadcast`. Example: `{broadcast} {player} found a treasure trove of 100 voter keys!`. + + +- **{actionBar}** Sends a message to the "actionBar" on the player's screen. Just use this placeholder followed by the message. This is a shortcut for the prison command: `\prison utils titles actionBar `. Example: `{actionBar}You Found Tokens!` + + +- **{title}** Sends a message to the "title" on the player's screen. Just use this placeholder followed by the message. This is a shortcut for the prison command: `\prison utils titles title `. Example: `{title}You Found Tokens!` + + + +**How the command runs:** + +There are four **taskModes** on how BlockEvent commands run. The taskModes can be setup through the command `/mines blockEvent taskMode help`, or they can be specified as placeholders. There are 4 taskModes, and the placeholder versions are listed here: + +- **{inline}** This is the default taskMode if not specified. **{inline}** runs the commands in the same thread that in which Prison is handling the Block Break Events within Auto Features, and runs them as console (OP). If the command you use with BlockEvents is "slow" to run, then it could cause significant lag on the server. + +- **{inlinePlayer}** This placeholder is similar to the **{inline}** placeholder, but it is ran as the player who is mining. This too can cause significant lag if the command is not fast. +- **{sync}** This placeholder uses the taskMode of synchronous task submission. The command specified will be submitted to run in the bukkit's synchronous thread, and is ran as console (OP). Since all block break events are ran in the same bukkit synchronous thread, the specified command will run after prison is finished processing the broken block. Long running commands will not cause lag through the handling of the block break events, but they could still cause lag. +- **{syncPlayer}** This placeholder is similar to the **{sync}** placeholder, with the exception the commands are ran as the player, so the player must have access to those commands. -Some examples showing how to use these in BlockEvent: +NOTE: It is impossible to run a command asynchronously, since the execution of a command must always be in a synchronous thread. Hence you can submit an async task, but then when you run the command, it does so in a sync thread. + + +`/mines blockEvent add help` +`/mines blockEvent add placeholders` + + +Some examples showing how to use placeholders in the blockEvents. ``` -/mines blockevent add A 0.075 none inline prison utils repairAll {player};{msg} Congrats! Everything in your inventory has been repaired! -/mines blockevent add A 1 none inline prison utils smelt {player};prison utils block {player} +/mines blockEvent add a 100 {utilsDecay} rainbow {blockCoordinates} AIR 40 {mineName} + +/mines blockevent add A 0.075 prison utils repairAll {player};{actionBar}Your items have been repaired! + +/mines blockevent add A 1 prison utils smelt {player} -/mines blockEvent add A 5.0 none inline prison utils potionEffect speed 90 2;prison utils potionEffect night_vision 300 1 +/mines blockEvent add A 5.0 prison utils potionEffect speed 90 2;prison utils potionEffect night_vision 300 1 ``` + +- **{blockName}** The name of the block that was placed in the mine during the last mine reset. The same name as used and provided within the command `/mines block search`. + + +- **{mineName}** The name of the mine. If outside of a mine it will be blank. + + +- **{locationWorld}** Provides the world name in which the block was mined. + + +-**{locationX}** The **X** coordinates for the broken block. This is an integer value. + + +- **{locationY}** The **Y** coordinates for the broken block. This is an integer value. + + +- **{locationZ}** The **Z** coordinates for the broken block. This is an integer value. + + +- **{coordinates}** This provides the X, Y, and Z coordinates for the broken block. These are double values, surrounded by parenthesis and separated by commas. Format: **(X,Y,Z)** Example: `(183.2,88.3792,-3828.248)` + + +- **{blockCoordinates}** This is similar to the **{coordinates}** placeholder, except for the use of integer values. Format: **(blockName,world,X,Y,Z)** Example: `(,prisonWorld,183,88,-3828)` + + +- **{worldCoordinates}** This combines both the **{locationWorld}** and **{blockCoordinates}** placeholder in to one placeholder. The coordinates are integer values. Format: **(world,X,Y,Z)** Example: `(prisonWorld,183,88,-3828)` + + +- **{blockChance}** The blockEvent's percent chance as defined when setting up the command. + + +- **{blockIsAir}** A boolean value of either TRUE or FALSE as to if the block was originally set to AIR during the last mine reset. Technically, if the block is set to AIR, then it is ignored in all block events that prison processes through the auto features. Therefore this should always return FALSE. + + +- **{blocksPlaced}** This is the number of blocks placed in the mine during the last Mine reset. This value should be equal to the mine's total block size, minus the number of AIR blocks that were placed during the reset. + + +- **{blockRemaining}** The current number of blocks remaining in the mine, until there would be zero blocks left to mine. Note that this is a dynamic and changing value, especially if many other players are mining at the same time. There is even a chance that this value may be non-zero with another player's block break handling triggering a mine reset event, or zero blocks remaining. + + +- **{blocksMinedTotal}** The total number of blocks mined of the same type that was just broke since the last mine reset. + + +- **{mineBlocksRemaining}** The total number of block remaining of the same type that was just broke. See **{blockName}** for the block name. + +- **{mineBlocksRemainingPercent}** The percent number of blocks remaining in the mine. + + +- **{mineBlocksTotalMined}** This is the total number of all blocks mined since the stats were first enabled. + + +- **{mineBlocksSize}** This is the total block count of all blocks mined. + + +- **{blockMinedName}** This is the name of the block that was mined. It may not be identical to the **{blockName}** placeholder, especially if another process replaced it with another block. + + +- **{blockMinedNameFormal}** This is the formal name of the block that was mined. The formal nature is the namespace prefixed to the block name, with a colon between the two. For example a block name may be "cobblestone" and then the formal name being "minecraft:cobblestone". This is more useful for custom blocks, such that their namespace is not "minecraft", which an example being "customitems:compressed_cobblestone". + + +- **{blockMinedBlockType}** This is the bukkit Material name for the block. It may not match the block name, especially on older versions of spigot. + + +- **{eventType}** This is the event type that Prison listened to that initiated the block break handling. + + +- **{eventTriggered}** A few enchantment plugins identify the enchantment that triggered the event. If it is available, then that value will be provided by this placeholder. One plugin that provides this value is TokenEnchant. + + +- **{utilsDecay}** This is a shortcut for `/prison utils decay`. + + + +
diff --git a/docs/prison_docs_117_setting_up_backpacks.md b/docs/prison_docs_117_setting_up_backpacks.md index cf47f4124..b39dc6646 100644 --- a/docs/prison_docs_117_setting_up_backpacks.md +++ b/docs/prison_docs_117_setting_up_backpacks.md @@ -5,10 +5,15 @@ # Backpacks +*NOTE: At this time it is not advisable to use Prison's backpacks. It is scheduled to undergo a rewrite soon. An alternative backbacks plugin that should work with Prison is MinePacks.* + + Prison provides backpacks. +*Documented updated: 2021-12-03* +
diff --git a/docs/prison_docs_310_guide_placeholders.md b/docs/prison_docs_310_guide_placeholders.md index 0c5e3cc34..0b4a04f28 100644 --- a/docs/prison_docs_310_guide_placeholders.md +++ b/docs/prison_docs_310_guide_placeholders.md @@ -6,6 +6,10 @@ This document covers different aspects of placeholders within Prison. It explains how they work, how to use them, and different ways to use them. + +*Documented updated: 2021-12-03* + +
@@ -13,34 +17,100 @@ This document covers different aspects of placeholders within Prison. It explai Placeholders allow the sharing of data from one plugin with another plugin, and without either plugin knowing anything about each other. -On the surface they appear to be simple, but there are a lot of moving parts below the surface, and with Prison Mines, there are even more things going on. +On the surface they appear to be simple, but there are a lot of moving parts below the surface, and with Prison Mines, there are even more complicated things going on. Add in to the mix, that different plugins deal with placeholders in slightly different ways, and you can wind up with a challenge to get them to work under different circumstances.
+ + + +# Placeholder Commands + + +*Since Prison v3.2.1-alpha.13* + + +There are a few useful commands within prison that will allow you list placeholders, search for placeholders, and to test random text that includes placeholders. + + +Sub-command listing of all placeholders commands: + +* **/prison placeholders** + + +* **/prison placeholders list** +* **/prison placeholders search** +* **/prison placeholders test** + +* **/prison placeholders reload** + +NOTE: the `/prison placeholders reload` command only reloads and registers the placeholders with the placeholder integrations. This would be required to enable placeholders when adding a new mine, a new rank, or a new ladder. If you reload another plugin, such as papi, you may need to reload the placeholders which will re-register them. Prison has been setup to survive a papi restart, but there could still be issues. + + +NOTE: Information on these command are provided in detail below. + + +
+ + # Placeholder Types and Counts -* **Rank Related:** 4 including aliases -* **Rankup Related:** 18 including aliases +Prison has numerous placeholders, with number of different types. Each of these types have different internal requirements and conditions of usage. This is a high overview of the various types and their counts. + +* **Player Related:** 92 including aliases + * **Rank Related:** 8 including aliases + * **Rankup Related:** 20 including aliases + * **Player Balance Related:** 8 including aliases + * **Player Tool Related:** 34 including aliases + * **Player Health Related:** 14 including aliases + * **Player XP and Levels Related:** 6 including aliases + * **Player Walk Speed:** 2 including aliases + + +* **Ladders Related:** 30 including aliases **times** each ladder + A LADDERS placeholder must include the ladder's name in the placeholder and therefore is static. + + +* **Ranks Related:** 22 including aliases **times** each rank + A RANKS placeholder needs to specify the Rank name as part of the placeholder. Each placeholder must specify a Rank and is static. -* **Rank Ladder Related:** 4 including aliases **times** each ladder -* **Rankup Ladder Related:** 18 including aliases **times** each ladder +* **RankPlayers Related:** 12 including aliases **times** each rank -* **Player Balance Related:** 2 including aliases -* **Player Ladder Balance Related:** 2 including aliases **times** each ladder + A RANKPLAYERS placeholder is one that will change based upon the player's own Rank. Each player could have a different rank. Because of this relationship, these can only be used with instances of players such as scoreboards and chat prefixes; they will not work in holographic displays or with signs. -* **Mine Related:** 28 including aliases **times** each mine -* **Mine Player Related:** 14 including aliases +* **Mines Related:** 18 including aliases **times** each ladder -**Total base Placeholders:** 90 including aliases +* **Player Ladder Balance Related:** 32 including aliases **times** each Mine + + A MINES placeholder must specify the Mine mine as part of the placeholder. Each placeholder must specify a mine and is static. + + +* **MinePlayers Related:** 34 including aliases + + A MINEPLAYERS placholder is similar to a RankPlayers placeholder in that it is dynamic and you cannot specify a mine's name with it. How it works, is that it provides the related stats for the mine in which the player is standing in. When the player leaves the mine, then these placeholders returns an empty string value (a blank). + + +* *STATSMINES Related:** 14 including aliases + + These are a work in progress, but will provide access to some mine stats such as total blocks mined. + + +* *STATSRANKS Related:** 6 including aliases + + These are a work in progress, but will provide access to some rank stats such as top ranked player in that rank. + + + +**Total base Placeholders:** 240 including aliases + -**Total if 26 Mines and 3 Ladders:** 844 placeholder including aliases (22 + 26*3 ladder + 2 + 28*26 mines + 14)
@@ -57,7 +127,7 @@ There is always more than one way to do things, and the same goes for having mor # Placeholder Theory for Prison -There are two major types of placeholders in prison: Player based and Mine based. With the most recent releases of prison, there have been hybrids added that are a combination of the two. For example there are now ladder based placeholder that allow targeting ranks on a specific ladder, instead of all ladders. Also there are player mine placeholders that report on the mine stats for the mine in which the player is physically located in. The player mine placeholders have no value when the player is not in a mine, and they will change as the player goes from mine to mine. +There are few major types of placeholders in prison: Player, Ranks, Ladders, Mines, and Stats based. With the most recent releases of prison, there have been hybrids added that are a combination of the player placeholders and with mines and ranks. For example there are now ladder based placeholder that allow targeting ranks on a specific ladder, instead of all ladders. Also there are player mine placeholders that report on the mine stats for the mine in which the player is physically located in. The player mine placeholders have no value when the player is not in a mine, and they will change as the player goes from mine to mine. There are also different types of data that are returned in placeholders. Text, numbers, formatted numbers, and bar graphs. @@ -348,31 +418,6 @@ This is mentioned here since these rank command placeholders are not part of all -# Placeholder Commands - - -*Since Prison v3.2.1-alpha.13* - - -There are a few commands within prison that will allow you list placeholders, search for placeholders, and to test random text that includes placeholders. - - -* **/prison placeholders** - - -* **/prison placeholders list** -* **/prison placeholders search** -* **/prison placeholders test** - -* **/prison placeholders reload** - -NOTE: the `/prison placeholders reload` command only reloads and registers the placeholders with the placeholder integrations. This would be required to enable placeholders on a new mine or new ranks or a new ladder that were added since the last server restart. Also if you reload another plugin, such as papi, you will need to reload the plugins, which just re-registers them. - - - -* **/prison version** No longer provides a list of placeholders since it's become too large. - -

Prison Placeholder Command Listing

From b129898eb01e2072d663c9a36cd2de4dda33271b Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sat, 4 Dec 2021 18:52:53 -0500 Subject: [PATCH 181/283] Added access to the player cache within the Player object so it's easier to use it. --- docs/changelog_v3.3.x.md | 5 +++++ .../java/tech/mcprison/prison/internal/Player.java | 7 ++++++- .../mcprison/prison/ranks/data/RankPlayer.java | 13 +++++++++++++ .../test/java/tech/mcprison/prison/TestPlayer.java | 14 ++++++++++++++ .../prison/spigot/game/SpigotOfflinePlayer.java | 12 ++++++++++++ .../mcprison/prison/spigot/game/SpigotPlayer.java | 13 +++++++++++++ 6 files changed, 63 insertions(+), 1 deletion(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index e70e1e9e9..f06ad5e01 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,11 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.9 2021-12-04 + + +* **Added access to the player cache within the Player object so it's easier to use it.** + + * **Updates some documents.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/Player.java b/prison-core/src/main/java/tech/mcprison/prison/internal/Player.java index f9386696d..6b0e47216 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/Player.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/Player.java @@ -22,6 +22,8 @@ import java.util.Optional; import java.util.UUID; +import tech.mcprison.prison.cache.PlayerCache; +import tech.mcprison.prison.cache.PlayerCachePlayerData; import tech.mcprison.prison.internal.block.Block; import tech.mcprison.prison.internal.inventory.InventoryHolder; import tech.mcprison.prison.internal.scoreboard.Scoreboard; @@ -144,6 +146,9 @@ public interface Player public void setActionBar( String actionBar ); - + + PlayerCache getPlayerCache(); + + PlayerCachePlayerData getPlayerCachePlayerData(); } diff --git a/prison-core/src/main/java/tech/mcprison/prison/ranks/data/RankPlayer.java b/prison-core/src/main/java/tech/mcprison/prison/ranks/data/RankPlayer.java index 7934ea2c6..bb3d0ea91 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/ranks/data/RankPlayer.java +++ b/prison-core/src/main/java/tech/mcprison/prison/ranks/data/RankPlayer.java @@ -27,6 +27,8 @@ import tech.mcprison.prison.Prison; import tech.mcprison.prison.PrisonAPI; +import tech.mcprison.prison.cache.PlayerCache; +import tech.mcprison.prison.cache.PlayerCachePlayerData; import tech.mcprison.prison.integration.EconomyCurrencyIntegration; import tech.mcprison.prison.integration.EconomyIntegration; import tech.mcprison.prison.internal.ItemStack; @@ -1005,4 +1007,15 @@ public void setTitle( String title, String subtitle, int fadeIn, int stay, int f @Override public void setActionBar( String actionBar ) { } + + @Override + public PlayerCache getPlayerCache() { + return PlayerCache.getInstance(); + } + + @Override + public PlayerCachePlayerData getPlayerCachePlayerData() { + return PlayerCache.getInstance().getOnlinePlayer( this ); + } + } diff --git a/prison-core/src/test/java/tech/mcprison/prison/TestPlayer.java b/prison-core/src/test/java/tech/mcprison/prison/TestPlayer.java index 52d75f24f..cd8ffec87 100644 --- a/prison-core/src/test/java/tech/mcprison/prison/TestPlayer.java +++ b/prison-core/src/test/java/tech/mcprison/prison/TestPlayer.java @@ -24,6 +24,8 @@ import java.util.Optional; import java.util.UUID; +import tech.mcprison.prison.cache.PlayerCache; +import tech.mcprison.prison.cache.PlayerCachePlayerData; import tech.mcprison.prison.internal.ItemStack; import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.internal.block.Block; @@ -194,4 +196,16 @@ public void setTitle( String title, String subtitle, int fadeIn, int stay, int f @Override public void setActionBar( String actionBar ) { } + + @Override + public PlayerCache getPlayerCache() + { + return null; + } + + @Override + public PlayerCachePlayerData getPlayerCachePlayerData() + { + return null; + } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotOfflinePlayer.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotOfflinePlayer.java index e47f16db8..712591380 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotOfflinePlayer.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotOfflinePlayer.java @@ -10,6 +10,8 @@ import org.bukkit.entity.Player; import org.bukkit.permissions.PermissionAttachmentInfo; +import tech.mcprison.prison.cache.PlayerCache; +import tech.mcprison.prison.cache.PlayerCachePlayerData; import tech.mcprison.prison.internal.ItemStack; import tech.mcprison.prison.internal.OfflineMcPlayer; import tech.mcprison.prison.internal.inventory.Inventory; @@ -300,5 +302,15 @@ public void setTitle( String title, String subtitle, int fadeIn, int stay, int f @Override public void setActionBar( String actionBar ) { } + + @Override + public PlayerCache getPlayerCache() { + return PlayerCache.getInstance(); + } + + @Override + public PlayerCachePlayerData getPlayerCachePlayerData() { + return PlayerCache.getInstance().getOnlinePlayer( this ); + } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayer.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayer.java index b19c4a3cc..bd111c1f0 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayer.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayer.java @@ -30,6 +30,8 @@ import org.bukkit.event.player.PlayerTeleportEvent; import tech.mcprison.prison.autofeatures.PlayerMessaging.MessageType; +import tech.mcprison.prison.cache.PlayerCache; +import tech.mcprison.prison.cache.PlayerCachePlayerData; import tech.mcprison.prison.internal.ItemStack; import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.internal.inventory.Inventory; @@ -621,4 +623,15 @@ public void setActionBar( String actionBar ) { // .sendActionBar( getWrapper(), actionBar ); } } + + @Override + public PlayerCache getPlayerCache() { + return PlayerCache.getInstance(); + } + + @Override + public PlayerCachePlayerData getPlayerCachePlayerData() { + return PlayerCache.getInstance().getOnlinePlayer( this ); + } + } From 0060052d16f5dd425de71b354c00b92d636ed50f Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sat, 4 Dec 2021 18:56:03 -0500 Subject: [PATCH 182/283] Added the title and actionBar to the Player object so it will work in all forms of Player, such as RankPlayer. Had to use the Platform to cross over to spigot from core. --- docs/changelog_v3.3.x.md | 2 + .../prison/internal/platform/Platform.java | 6 ++ .../prison/ranks/data/RankPlayer.java | 2 + .../tech/mcprison/prison/TestPlatform.java | 13 +++++ .../prison/spigot/SpigotPlatform.java | 55 +++++++++++++++++++ 5 files changed, 78 insertions(+) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index f06ad5e01..8e4c773b9 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,8 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.9 2021-12-04 +* **Added the title and actionBar to the Player object so it will work in all forms of Player, such as RankPlayer.** +Had to use the Platform to cross over to spigot from core. * **Added access to the player cache within the Player object so it's easier to use it.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/platform/Platform.java b/prison-core/src/main/java/tech/mcprison/prison/internal/platform/Platform.java index 5b47f64b2..b4ecffe90 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/platform/Platform.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/platform/Platform.java @@ -423,5 +423,11 @@ public void autoCreateMineLinerAssignment( List rankMineNames, public void reloadAutoFeaturesEventListeners(); + void setTitle( Player player, String title, String subtitle, int fadeIn, int stay, int fadeOut ); + + + void setActionBar( Player player, String actionBar ); + + } diff --git a/prison-core/src/main/java/tech/mcprison/prison/ranks/data/RankPlayer.java b/prison-core/src/main/java/tech/mcprison/prison/ranks/data/RankPlayer.java index bb3d0ea91..bb287faec 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/ranks/data/RankPlayer.java +++ b/prison-core/src/main/java/tech/mcprison/prison/ranks/data/RankPlayer.java @@ -1002,10 +1002,12 @@ public List getPermissionsIntegrations( boolean detailed ) { @Override public void setTitle( String title, String subtitle, int fadeIn, int stay, int fadeOut ) { + Prison.get().getPlatform().setTitle( this, title, subtitle, fadeIn, stay, fadeOut ); } @Override public void setActionBar( String actionBar ) { + Prison.get().getPlatform().setActionBar( this, actionBar ); } @Override diff --git a/prison-core/src/test/java/tech/mcprison/prison/TestPlatform.java b/prison-core/src/test/java/tech/mcprison/prison/TestPlatform.java index 789021ced..1e9f6d03a 100644 --- a/prison-core/src/test/java/tech/mcprison/prison/TestPlatform.java +++ b/prison-core/src/test/java/tech/mcprison/prison/TestPlatform.java @@ -427,7 +427,20 @@ public ChatDisplay dumpEventListenersChatDisplay( String eventType, HandlerList * tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.reloadConfig() * */ + @Override public void reloadAutoFeaturesEventListeners() { } + + @Override + public void setTitle( Player player, String title, String subtitle, int fadeIn, int stay, int fadeOut ) + { + + } + + @Override + public void setActionBar( Player player, String actionBar ) + { + + } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java index 0b248d0f0..b790f8310 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotPlatform.java @@ -2368,4 +2368,59 @@ public String getRanksListString() { + @Override + public void setTitle( Player player, String title, String subtitle, int fadeIn, int stay, int fadeOut ) { + + if ( player != null ) { + + SpigotPlayer sPlayer = null; + + if ( player instanceof SpigotPlayer ) { + sPlayer = (SpigotPlayer) player; + } + else { + Player p = getPlayer( player.getName() ).orElse( null ); + + if ( p != null ) { + + sPlayer = (SpigotPlayer) p; + } + } + + if ( sPlayer != null ) { + + sPlayer.setTitle( title, subtitle, fadeIn, stay, fadeOut );; + } + + } + } + + + @Override + public void setActionBar( Player player, String actionBar ) { + + if ( player != null ) { + + SpigotPlayer sPlayer = null; + + if ( player instanceof SpigotPlayer ) { + sPlayer = (SpigotPlayer) player; + } + else { + Player p = getPlayer( player.getName() ).orElse( null ); + + if ( p != null ) { + + sPlayer = (SpigotPlayer) p; + } + } + + if ( sPlayer != null ) { + + sPlayer.setActionBar( actionBar ); + } + + } + } + } From c744f0e83900127f6b59b3e5fdfc966668ea4756 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sat, 4 Dec 2021 18:58:09 -0500 Subject: [PATCH 183/283] Prison tokens: Added admin functions of balance, add, remove, and set. --- docs/changelog_v3.3.x.md | 3 + .../tech/mcprison/prison/PrisonCommand.java | 227 ++++++++++++++++++ .../prison/cache/PlayerCachePlayerData.java | 69 +++++- .../prison/ranks/commands/RanksCommands.java | 14 +- 4 files changed, 304 insertions(+), 9 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 8e4c773b9..201926c11 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.9 2021-12-04 +* **Prison tokens: Added admin functions of balance, add, remove, and set.** + + * **Added the title and actionBar to the Player object so it will work in all forms of Player, such as RankPlayer.** Had to use the Platform to cross over to spigot from core. diff --git a/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java b/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java index 6db8f9709..4be9a3b91 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java +++ b/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java @@ -1533,6 +1533,233 @@ public void supportListenersDump(CommandSender sender, } + + @Command(identifier = "prison tokens balance", + description = "Prison tokens: a player's current balance.", + aliases = "bal", + permissions = "tokens.bal", + altPermissions = "tokens.bal.others" ) + public void tokensBalance(CommandSender sender, + @Arg(name = "player", def = "", description = "Player to get token balance for. " + + "If player is online this is not required for their own balance. " + + "This is needed if used from console or to get the balance of " + + "another player.") String playerName + ) { + + Player player = getPlayer( sender ); + + // If player is null, then need to use the playerName, so if it's empty, we have a problem: + if ( ( player == null || !player.isOnline() ) && + ( playerName == null || playerName.isEmpty() ) ) { + + String message = "Prison Tokens: A player's name is required when used from console."; + + Output.get().logWarn( message ); + return; + } + else { + + if ( playerName != null && !sender.isOp() && + !sender.hasPermission( "tokens.bal.others" ) ) { + String message = "Prison Tokens: You do not have permission to view other " + + "player's balances."; + Output.get().logWarn( message ); + return; + } + + player = getPlayer( playerName ); + } + + +// player.getPlayerCache() + + DecimalFormat dFmt = new DecimalFormat("#,##0"); + + String tokens = dFmt.format( player.getPlayerCachePlayerData().getTokens() ); + + String message = String.format( "&3%s has %s tokens.", player.getName(), tokens ); + + sender.sendMessage( message ); + } + + @Command(identifier = "prison tokens add", + description = "Prison tokens Admin: an admins tool to give more tokens to a player", + permissions = "tokens.admin.add" ) + public void tokensAdd( CommandSender sender, + @Arg(name = "player", + description = "Player to add the tokens to.") String playerName, + + @Arg(name = "amount", verifiers = "min[1]", + description = "The number of tokens to add to the player's account.") int amount + ) { + + if ( playerName == null || playerName.isEmpty() ) { + + String message = "Prison Tokens: A player's name is required."; + Output.get().logWarn( message ); + return; + } + + DecimalFormat dFmt = new DecimalFormat("#,##0"); + + if ( amount <= 0 ) { + + String message = + String.format( + "Prison Tokens: Invalid amount: '%s'. Must be greater than zero.", + dFmt.format( amount ) ); + Output.get().logWarn( message ); + return; + } + + Player player = getPlayer( playerName ); + + player.getPlayerCachePlayerData().addTokensAdmin( amount ); + + + + String tokens = dFmt.format( player.getPlayerCachePlayerData().getTokens() ); + + String message = String.format( "&3%s now has &7%s &3tokens after adding &7%s&3.", + player.getName(), tokens, dFmt.format( amount ) ); + + // The person adding the tokens, or console: + sender.sendMessage( message ); + + // The player getting the tokens, if they are online: + if ( player.isOnline() ) { + + player.sendMessage( message ); + } + } + + @Command(identifier = "prison tokens remove", + description = "Prison tokens Admin: an admins tool to remove tokens from a player. " + + "It is possible to remove more tokens than what the player has, which can " + + "be treated like a debt.", + permissions = "tokens.admin.add" ) + public void tokensRemove( CommandSender sender, + @Arg(name = "player", + description = "Player to remove the tokens from.") String playerName, + + @Arg(name = "amount", verifiers = "min[1]", + description = "The number of tokens to remove from the player's account. " + + "This amount must be positive. ") int amount + ) { + + if ( playerName == null || playerName.isEmpty() ) { + + String message = "Prison Tokens: A player's name is required."; + Output.get().logWarn( message ); + return; + } + + DecimalFormat dFmt = new DecimalFormat("#,##0"); + + if ( amount <= 0 ) { + + String message = + String.format( + "Prison Tokens: Invalid amount: '%s'. Must be greater than zero.", + dFmt.format( amount ) ); + Output.get().logWarn( message ); + return; + } + + Player player = getPlayer( playerName ); + + player.getPlayerCachePlayerData().removeTokensAdmin( amount ); + + + + String tokens = dFmt.format( player.getPlayerCachePlayerData().getTokens() ); + + String message = String.format( "&3%s now has &7%s &3tokens after removing &7%s&3.", + player.getName(), tokens, dFmt.format( amount ) ); + + // The person adding the tokens, or console: + sender.sendMessage( message ); + + // The player getting the tokens, if they are online: + if ( player.isOnline() ) { + + player.sendMessage( message ); + } + } + + @Command(identifier = "prison tokens set", + description = "Prison tokens Admin: an admins tool to set number of tokens " + + "for a player to a specific amount. " + + "It is possible to set the tokens to a negavtie amount, which can " + + "be treated like a debt.", + permissions = "tokens.admin.add" ) + public void tokensSet( CommandSender sender, + @Arg(name = "player", + description = "Player to remove the tokens from.") String playerName, + + @Arg(name = "amount", + description = "The number of tokens to set the player's account to. " + + "This amount must amount can be negative. ") int amount + ) { + + if ( playerName == null || playerName.isEmpty() ) { + + String message = "Prison Tokens: A player's name is required."; + Output.get().logWarn( message ); + return; + } + + DecimalFormat dFmt = new DecimalFormat("#,##0"); + + Player player = getPlayer( playerName ); + +// // Set to zero: +// long totalTokens = player.getPlayerCachePlayerData().getTokens(); +// player.getPlayerCachePlayerData().removeTokensAdmin( totalTokens ); + + + player.getPlayerCachePlayerData().setTokensAdmin( amount ); + + + String tokens = dFmt.format( player.getPlayerCachePlayerData().getTokens() ); + + String message = String.format( "&3%s now has &7%s &3tokens.", + player.getName(), tokens ); + + // The person adding the tokens, or console: + sender.sendMessage( message ); + + // The player getting the tokens, if they are online: + if ( player.isOnline() ) { + + player.sendMessage( message ); + } + } + + + + /** + *

This function tries to first get the online player, otherwise it + * gets an offline player. Hopefully it always returns a player if the + * have been on the server before. + *

+ * + * @param playerName + * @return + */ + private Player getPlayer( String playerName ) { + Player player = null; + if ( playerName != null && !playerName.trim().isEmpty() ) { + + player = Prison.get().getPlatform().getPlayer( playerName ).orElse( null ); + } + if ( player == null ) { + + player = Prison.get().getPlatform().getOfflinePlayer( playerName ).orElse( null ); + } + return player; + } + // This functionality should not be available in v3.2.1! If someone is still running Prison 2.x.x // then they must first upgrade to diff --git a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java index 4c9a94104..87b858ca9 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java @@ -86,6 +86,7 @@ public class PlayerCachePlayerData { private long tokens; private long tokensTotal; + private long tokensTotalRemoved; private long tokensLastBlocksTotals; private TreeMap tokensByMine; @@ -542,8 +543,7 @@ private void addTokensByBlocks( String mineName, int blocks ) { */ public void addTokens( long newTokens, String mineName ) { - this.tokens += newTokens; - this.tokensTotal += newTokens; + addTokensAdmin( newTokens ); SimpleDateFormat dateFmt = new SimpleDateFormat("yyyy-MM-dd_hh:mm"); String key = dateFmt.format( new Date() ); @@ -580,6 +580,62 @@ public void addTokens( long newTokens, String mineName ) { dirty = true; } + + /** + *

This adds tokens to the player, but it is from an admin-related purpose, or task, + * so it has no effects on the player's Tokens-Per-Minute calculations, or + * per mine stats. + *

+ * + * @param newTokens + */ + public void addTokensAdmin( long newTokens ) { + + this.tokens += newTokens; + this.tokensTotal += newTokens; + + dirty = true; + } + + /** + *

This removes tokens from the player, but it is from an admin-related purpose, or task, + * so it has no effects on the player's Tokens-Per-Minute calculations, or + * per mine stats. + *

+ * + *

Note: The player can have a negative balance with this function! This may be useful for + * small "token loans" when purchasing something. Such allowances would have to be + * handled in the task that calls this function. + *

+ * + * @param newTokens + */ + public void removeTokensAdmin( long removeTokens ) { + + this.tokens -= removeTokens; + this.tokensTotalRemoved += removeTokens; + + dirty = true; + } + + public void setTokensAdmin( long newBalance ) { + + long delta = newBalance - this.tokens; + + if ( delta > 0 ) { + + this.tokens += delta; + this.tokensTotal += delta; + } + else { + + this.tokens -= delta; + this.tokensTotalRemoved -= delta; + } + + dirty = true; + } + /** * This returns the average tokens earned per minute for the * last 5 minutes. @@ -627,6 +683,8 @@ public String toString() { .append( getAverageTokensPerMinute() ) .append( " totalTokens: " ) .append( getTokensTotal() ) + .append( " totalTokensRemoved: " ) + .append( getTokensTotalRemoved() ) .append( " tokens: " ) .append( getTokens() ) ; @@ -762,6 +820,13 @@ public void setTokensTotal( long tokensTotal ) { this.tokensTotal = tokensTotal; } + public long getTokensTotalRemoved() { + return tokensTotalRemoved; + } + public void setTokensTotalRemoved( long tokensTotalRemoved ) { + this.tokensTotalRemoved = tokensTotalRemoved; + } + public long getTokensLastBlocksTotals() { return tokensLastBlocksTotals; } diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java index 26061d313..90cfaa0dc 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java @@ -1450,6 +1450,7 @@ public void rankPlayer(CommandSender sender, List msgs = new ArrayList<>(); + DecimalFormat iFmt = new DecimalFormat("#,##0"); DecimalFormat dFmt = new DecimalFormat("#,##0.00"); DecimalFormat fFmt = new DecimalFormat("0.0000"); DecimalFormat pFmt = new DecimalFormat("#,##0.0000"); @@ -1610,15 +1611,14 @@ public void rankPlayer(CommandSender sender, cPlayer.getTokensByMine().size() > 0 ) { msgs.add( String.format( - " Tokens By Mine: &2Tokens: &3%s &2Avg Tokens per min: &3%s " + - "", - dFmt.format( cPlayer.getTokens() ), - dFmt.format( cPlayer.getAverageTokensPerMinute() )) ); + " Tokens By Mine: &2Tokens: &3%s &2Avg Tokens per min: &3%s", + iFmt.format( cPlayer.getTokens() ), + dFmt.format( cPlayer.getAverageTokensPerMinute() )) ); msgs.add( String.format( - " &2Tokens Total: &3%s &2Tokens per Block: &3%d " + - "", - dFmt.format( cPlayer.getTokensTotal() ), + " &2Total: &3%s &2Total Removed: &3%s &2Tokens per Block: &3%d", + iFmt.format( cPlayer.getTokensTotal() ), + iFmt.format( cPlayer.getTokensTotalRemoved() ), AutoFeaturesWrapper.getInstance().getInteger( AutoFeatures.tokensBlocksPerToken )) ); msgs.addAll( From 7fb18b2a5a37034942b318da47a1fd702eb3be4b Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sat, 4 Dec 2021 20:26:05 -0500 Subject: [PATCH 184/283] Added 12 new placeholders: 4 new ones for player blances and 8 new ones for tokens. --- docs/changelog_v3.3.x.md | 3 + .../placeholders/PlaceholderManager.java | 16 ++++ .../prison/ranks/managers/PlayerManager.java | 89 +++++++++++++++++++ 3 files changed, 108 insertions(+) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 201926c11..e88ef70b8 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.9 2021-12-04 +* **Added 12 new placeholders: 4 new ones for player blances and 8 new ones for tokens.** + + * **Prison tokens: Added admin functions of balance, add, remove, and set.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderManager.java b/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderManager.java index 1159db5b7..be4869909 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderManager.java +++ b/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderManager.java @@ -240,7 +240,9 @@ public enum PrisonPlaceHolders { // player balances. Both with and without ladders. prison_pb(PlaceholderFlags.PLAYER, PlaceholderFlags.ALIAS), + prison_pbf(PlaceholderFlags.PLAYER, PlaceholderFlags.ALIAS), prison_player_balance(prison_pb, PlaceholderFlags.PLAYER), + prison_player_balance_formatted(prison_pbf, PlaceholderFlags.PLAYER), prison_pb_epm(PlaceholderFlags.PLAYER, PlaceholderFlags.ALIAS), @@ -250,10 +252,24 @@ public enum PrisonPlaceHolders { prison_pb_laddername(PlaceholderFlags.LADDERS, PlaceholderFlags.ALIAS), + prison_pbf_laddername(PlaceholderFlags.LADDERS, PlaceholderFlags.ALIAS), prison_player_balance_laddername(prison_pb_laddername, PlaceholderFlags.LADDERS), + prison_player_balance_formatted_laddername(prison_pbf_laddername, PlaceholderFlags.LADDERS), + prison_ptb(PlaceholderFlags.PLAYER, PlaceholderFlags.ALIAS), + prison_ptbf(PlaceholderFlags.PLAYER, PlaceholderFlags.ALIAS), + prison_player_token_balance(prison_ptb, PlaceholderFlags.PLAYER), + prison_player_token_balance_formatted(prison_ptbf, PlaceholderFlags.PLAYER), + + prison_ptb_epm(PlaceholderFlags.PLAYER, PlaceholderFlags.ALIAS), + prison_ptb_epmf(PlaceholderFlags.PLAYER, PlaceholderFlags.ALIAS), + prison_player_token_balance_earnings_per_minute(prison_ptb_epm, PlaceholderFlags.PLAYER), + prison_player_token_balance_earnings_per_minute_formatted(prison_ptb_epmf, PlaceholderFlags.PLAYER), + + + prison_psm(PlaceholderFlags.PLAYER, PlaceholderFlags.ALIAS), prison_player_sellall_multiplier(prison_psm, PlaceholderFlags.PLAYER), diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/PlayerManager.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/PlayerManager.java index 35313e2cd..fca6337f0 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/PlayerManager.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/PlayerManager.java @@ -1024,6 +1024,61 @@ else if ( formatted ) { } + private String getPlayerTokenBalance( RankPlayer rankPlayer, + boolean formatted, PlaceholderAttribute attribute ) { + StringBuilder sb = new StringBuilder(); + + DecimalFormat dFmt = new DecimalFormat("#,##0"); + + long tokens = rankPlayer.getPlayerCachePlayerData().getTokens(); + + if ( attribute != null && attribute instanceof PlaceholderAttributeNumberFormat ) { + PlaceholderAttributeNumberFormat attributeNF = + (PlaceholderAttributeNumberFormat) attribute; + sb.append( attributeNF.format( tokens ) ); + } + + else if ( formatted ) { + sb.append( PlaceholdersUtil.formattedMetricSISize( tokens )); + } + else { + sb.append( dFmt.format( tokens )); + } + + return sb.toString(); + } + + + private String getPlayerTokenAverageEarningsPerMinute( RankPlayer rankPlayer, + boolean formatted, PlaceholderAttribute attribute ) { + StringBuilder sb = new StringBuilder(); + + + if ( !rankPlayer.getLadderRanks().isEmpty()) { + DecimalFormat dFmt = new DecimalFormat("#,##0"); + + + double tpm = rankPlayer.getPlayerCachePlayerData().getAverageTokensPerMinute(); + + if ( attribute != null && attribute instanceof PlaceholderAttributeNumberFormat ) { + PlaceholderAttributeNumberFormat attributeNF = + (PlaceholderAttributeNumberFormat) attribute; + sb.append( attributeNF.format( tpm ) ); + } + + else if ( formatted ) { + sb.append( PlaceholdersUtil.formattedMetricSISize( tpm )); + } + else { + sb.append( dFmt.format( tpm )); + } + + } + + return sb.toString(); + } + + // /** // *

This gets the player's balance, and if the rank is provided, it will check to @@ -1375,6 +1430,13 @@ public String getTranslatePlayerPlaceHolder( UUID playerUuid, String playerName, results = getPlayerBalance( rankPlayer, ladderName, false, attribute ); break; + case prison_pbf: + case prison_player_balance_formatted: + case prison_pbf_laddername: + case prison_player_balance_formatted_laddername: + results = getPlayerBalance( rankPlayer, ladderName, true, attribute ); + break; + case prison_pb_epm: case prison_player_balance_earnings_per_minute: @@ -1387,6 +1449,33 @@ public String getTranslatePlayerPlaceHolder( UUID playerUuid, String playerName, results = getPlayerAverageEarningsPerMinute( rankPlayer, ladderName, true, attribute ); break; + + + case prison_ptb: + case prison_player_token_balance: + results = getPlayerTokenBalance( rankPlayer, false, attribute ); + break; + + case prison_ptbf: + case prison_player_token_balance_formatted: + results = getPlayerTokenBalance( rankPlayer, true, attribute ); + break; + + case prison_ptb_epm: + case prison_player_token_balance_earnings_per_minute: + + results = getPlayerTokenAverageEarningsPerMinute( rankPlayer, false, attribute ); + break; + + case prison_ptb_epmf: + case prison_player_token_balance_earnings_per_minute_formatted: + + results = getPlayerTokenAverageEarningsPerMinute( rankPlayer, true, attribute ); + break; + + + + case prison_psm: case prison_player_sellall_multiplier: results = getPlayerSellallMultiplier( rankPlayer, attribute ); From e78daa0cd5923bd7e8fb945b7d9fe47517215eab Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 5 Dec 2021 11:32:38 -0500 Subject: [PATCH 185/283] Bug fix: If a block has been placed in the mine that should not be there, prison was canceling the event which was preventing other plugins, or normal breakage, from breaking the block. The event is no longer being canceled. --- docs/changelog_v3.3.x.md | 8 ++++++-- .../prison/spigot/block/OnBlockBreakEventCore.java | 8 ++++++-- .../mcprison/prison/spigot/block/OnBlockBreakMines.java | 4 +++- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index e88ef70b8..737f694b5 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,10 +13,14 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.9 2021-12-04 +# 3.2.11-alpha.9 2021-12-05 -* **Added 12 new placeholders: 4 new ones for player blances and 8 new ones for tokens.** +* **Bug fix: If a block has been placed in the mine that should not be there, prison was canceling the event which was preventing other plugins, or normal breakage, from breaking the block.** +The event is no longer being canceled. + + +* **Added 12 new placeholders: 4 new ones for player balances and 8 new ones for tokens.** * **Prison tokens: Added admin functions of balance, add, remove, and set.** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index b59dccc82..800a97f41 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -581,12 +581,13 @@ private boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent, StringBuilder pmEvent.setTargetBlock( targetBlock ); // If ignore all block events has been set on this target block, then shutdown - if ( targetBlock.isIgnoreAllBlockEvents() ) { + if ( targetBlock != null && targetBlock.isIgnoreAllBlockEvents() ) { debugInfo.setLength( 0 ); pmEvent.setForceIfAirBlock( false ); - pmEvent.setCancelOriginalEvent( true ); + // do not cancel event so some other listener can process it + pmEvent.setCancelOriginalEvent( false ); return false; } @@ -624,6 +625,9 @@ private boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent, StringBuilder targetBlock.setAirBroke( true ); targetBlock.setIgnoreAllBlockEvents( true ); + // do not cancel event so some other listener can process it + pmEvent.setCancelOriginalEvent( false ); + blockTypeNotExpected++; } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakMines.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakMines.java index c686b1d5e..b96881007 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakMines.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakMines.java @@ -111,7 +111,9 @@ protected boolean ignoreMinesBlockBreakEvent( Cancellable event, Player player, // If ignore all block events, then exit this function without logging anything: if ( targetBlock.isIgnoreAllBlockEvents() ) { - event.setCancelled( true ); + + // Do not cancel the event... let other plugins deal with it... prison does not care about this block. + //event.setCancelled( true ); ignoreEvent = true; } } From 1fd31cb4f0e848c8c5fc1c6fd8509820c70fb540 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 5 Dec 2021 16:08:23 -0500 Subject: [PATCH 186/283] Removed the DebugTarget value of "support" since it is not using anymore. --- .../prison/discord/DiscordWebhook.java | 12 ++++----- .../prison/discord/PrisonDiscordWebhook.java | 26 +++++++++---------- .../tech/mcprison/prison/output/Output.java | 4 +-- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/prison-core/src/main/java/tech/mcprison/prison/discord/DiscordWebhook.java b/prison-core/src/main/java/tech/mcprison/prison/discord/DiscordWebhook.java index 2490a5f95..09203dfb6 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/discord/DiscordWebhook.java +++ b/prison-core/src/main/java/tech/mcprison/prison/discord/DiscordWebhook.java @@ -205,12 +205,12 @@ public void execute() throws IOException { json.put("embeds", embedObjects.toArray()); } - if ( Output.get().isDebug( DebugTarget.support ) ) { - String jsonString = json.toString(); - Output.get().logDebug( DebugTarget.support, - "Prison Webhook debug: jsonSize: " + jsonString.length() + - " " + jsonString ); - } +// if ( Output.get().isDebug( DebugTarget.support ) ) { +// String jsonString = json.toString(); +// Output.get().logDebug( DebugTarget.support, +// "Prison Webhook debug: jsonSize: " + jsonString.length() + +// " " + jsonString ); +// } URL url = new URL(this.url); HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); diff --git a/prison-core/src/main/java/tech/mcprison/prison/discord/PrisonDiscordWebhook.java b/prison-core/src/main/java/tech/mcprison/prison/discord/PrisonDiscordWebhook.java index 085de2af6..66b4b40ec 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/discord/PrisonDiscordWebhook.java +++ b/prison-core/src/main/java/tech/mcprison/prison/discord/PrisonDiscordWebhook.java @@ -80,19 +80,19 @@ public void send( CommandSender sender, String title, String message, boolean ad } - if ( Output.get().isDebug( DebugTarget.support ) ) { - Output.get().logDebug( DebugTarget.support, - "Prison Webhook debug: total fields: %d total chars: %d ", - getFields().size(), totalSize ); - - if ( getFields().size() > 25 || totalSize > 6000 ) { - Output.get().logDebug( DebugTarget.support, - "Prison Webhook debug: total fields: Failure. Max number of " + - "fields is 25. Max number of characters is 6000. Please reduce " + - "these to bring in to complience and resubmit. " ); - } - - } +// if ( Output.get().isDebug( DebugTarget.support ) ) { +// Output.get().logDebug( DebugTarget.support, +// "Prison Webhook debug: total fields: %d total chars: %d ", +// getFields().size(), totalSize ); +// +// if ( getFields().size() > 25 || totalSize > 6000 ) { +// Output.get().logDebug( DebugTarget.support, +// "Prison Webhook debug: total fields: Failure. Max number of " + +// "fields is 25. Max number of characters is 6000. Please reduce " + +// "these to bring in to complience and resubmit. " ); +// } +// +// } String results = submitWebhook( webhook ); diff --git a/prison-core/src/main/java/tech/mcprison/prison/output/Output.java b/prison-core/src/main/java/tech/mcprison/prison/output/Output.java index 9b6d89074..8a13717f9 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/output/Output.java +++ b/prison-core/src/main/java/tech/mcprison/prison/output/Output.java @@ -68,8 +68,8 @@ public enum DebugTarget { blockBreakFortune, // blockBreakXpCalcs, // Removed since it was inlined - rankup, - support + rankup +// support ; public static DebugTarget fromString( String target ) { From 46eb3ca2d409218a3ce59dcec583be90524377e7 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 5 Dec 2021 16:13:54 -0500 Subject: [PATCH 187/283] Add a selective debug option where only the selected element is loged through the debugger. --- docs/changelog_v3.3.x.md | 6 ++ .../tech/mcprison/prison/PrisonCommand.java | 23 ++++++-- .../tech/mcprison/prison/output/Output.java | 57 ++++++++++++++++++- 3 files changed, 80 insertions(+), 6 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 737f694b5..8407d4e21 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,12 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.9 2021-12-05 +* **Add a selective debug option where only the selected element is loged through the debugger.** + + +* **Removed the DebugTarget value of "support" since it is not using anymore.** + + * **Bug fix: If a block has been placed in the mine that should not be there, prison was canceling the event which was preventing other plugins, or normal breakage, from breaking the block.** The event is no longer being canceled. diff --git a/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java b/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java index 4be9a3b91..2eb0e9039 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java +++ b/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java @@ -1006,10 +1006,12 @@ public void toggleDebug(CommandSender sender, @Wildcard(join=true) @Arg(name = "targets", def = " ", description = "Optional. Enable or disable a debugging target. " + - "[on, off, targets, jarScan, " + - "testPlayerUtil, testLocale, rankup] " + + "[on, off, targets, selective, jarScan, " + + "testPlayerUtil, testLocale, rankup ] " + "Use 'targets' to list all available targets. Use 'on' or 'off' to toggle " + - "on and off individual targets, or all targets if no target is specified. " + + "on and off individual targets, or 'all' targets if no target is specified. " + + "If any targets are enabled, then debug in general will be enabled. Selective will only " + + "activate debug with the specified targets. " + "jarScan will identify what Java version compiled the class files within the listed jars" ) String targets ) { @@ -1038,7 +1040,7 @@ public void toggleDebug(CommandSender sender, return; } - + // Applies normal and selective targets: Output.get().applyDebugTargets( targets ); String message = "Global Debug Logging is " + (Output.get().isDebug() ? "enabled" : "disabled"); @@ -1057,6 +1059,19 @@ public void toggleDebug(CommandSender sender, } } + Set selectiveDebugTargets = Output.get().getSelectiveDebugTargets(); + + if ( selectiveDebugTargets.size() > 0 ) { + message = ". Selective Debug Targets:"; + sender.sendMessage( message ); + + for ( DebugTarget target : selectiveDebugTargets ) + { + message = String.format( ". . Target: %s", target.name() ); + sender.sendMessage( message ); + } + } + String validTargets = Output.get().getDebugTargetsString(); message = String.format( ". Valid Targets: %s", validTargets ); sender.sendMessage( message ); diff --git a/prison-core/src/main/java/tech/mcprison/prison/output/Output.java b/prison-core/src/main/java/tech/mcprison/prison/output/Output.java index 8a13717f9..8d5a4594a 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/output/Output.java +++ b/prison-core/src/main/java/tech/mcprison/prison/output/Output.java @@ -57,6 +57,7 @@ public class Output private boolean debug = false; private Set activeDebugTargets; + private Set selectiveDebugTargets; public enum DebugTarget { all, @@ -68,6 +69,8 @@ public enum DebugTarget { blockBreakFortune, // blockBreakXpCalcs, // Removed since it was inlined + targetBlockMismatch, + rankup // support ; @@ -107,6 +110,7 @@ private Output() { instance = this; this.activeDebugTargets = new HashSet<>(); + this.selectiveDebugTargets = new HashSet<>(); this.prefixTemplate = coreOutputPrefixTemplateMsg(); @@ -336,10 +340,19 @@ public String getDebugTargetsString() { public void applyDebugTargets( String targets ) { + boolean isSelective = targets.contains( "selective" ); + TreeSet trgts = DebugTarget.fromMultiString( targets ); if ( trgts.size() > 0 ) { - applyDebugTargets( trgts ); + + if ( isSelective ) { + applySelectiveDebugTargets( trgts ); + } + else { + applyDebugTargets( trgts ); + } + } else { // No targets were set, so just toggle the debugger: @@ -385,9 +398,41 @@ else if ( offTarget ) { // Output.get().setDebug( !Output.get().isDebug() ); } + public void applySelectiveDebugTargets( TreeSet targets ) { + + for ( DebugTarget target : targets ) { + + if ( getSelectiveDebugTargets().contains( target ) ) { + + getSelectiveDebugTargets().remove( target ); + } + else { + + getSelectiveDebugTargets().add( target ); + } + + } + + + } + public boolean isDebug( DebugTarget debugTarget ) { - return isDebug() || getActiveDebugTargets().contains( debugTarget ); + return isDebug() || getActiveDebugTargets().contains( debugTarget ) || + getSelectiveDebugTargets().contains( debugTarget ); + } + + /** + *

This only return true if the specified debug target is enabled. + * The global debug mode, and other debugTargets, are ignored. + *

+ * + * @param debugTarget + * @return + */ + public boolean isSelectiveTarget( DebugTarget debugTarget ) { + return getSelectiveDebugTargets().contains( debugTarget ); } + public boolean isDebug() { return debug; } @@ -403,6 +448,14 @@ public void setActiveDebugTargets( Set activeDebugTargets ) { this.activeDebugTargets = activeDebugTargets; } + public Set getSelectiveDebugTargets() { + return selectiveDebugTargets; + } + public void setSelectiveDebugTargets( Set selectiveDebugTargets ) { + this.selectiveDebugTargets = selectiveDebugTargets; + } + + /** * Send a message to a {@link CommandSender} */ From 22f771aa62181a0110b2242ba62a49580fd756a2 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 5 Dec 2021 16:21:05 -0500 Subject: [PATCH 188/283] For the bukkit 1.8 through bukkit 1.12, if an object has a different data value than what it normally has, it would not be matched through XMaterials... Examples are leaves, chests, etc... if there is no match initially using the block then try to then match on just the name, which eliminates the problem of a failed match. --- docs/changelog_v3.3.x.md | 4 ++++ .../prison/spigot/compat/Spigot113Blocks.java | 12 ++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 8407d4e21..6ff6cef2e 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.9 2021-12-05 +* **For the bukkit 1.8 through bukkit 1.12, if an object has a different data value than what it normally has**, +it would not be matched through XMaterials... Examples are leaves, chests, etc... if there is no match initially using the block then try to then match on just the name, which eliminates the problem of a failed match. + + * **Add a selective debug option where only the selected element is loged through the debugger.** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113Blocks.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113Blocks.java index 562e6859c..8492a4bb4 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113Blocks.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot113Blocks.java @@ -87,11 +87,14 @@ public XMaterial getXMaterial( Block spigotBlock ) { results = getCachedXMaterial( spigotBlock, NO_DATA_VALUE ); if ( results == null ) { - results = XMaterial.matchXMaterial( spigotBlock.getType() ); + results = XMaterial.matchXMaterial( spigotBlock.getType() ); - putCachedXMaterial( spigotBlock, NO_DATA_VALUE, results ); + if ( results == null ) { + results = XMaterial.matchXMaterial( spigotBlock.getType().name() ).orElse( null ); + } if ( results == null ) { + Output.get().logWarn( "Spigot113Blocks.getXMaterial() : " + "Spigot block cannot be mapped to a XMaterial : " + spigotBlock.getType().name() + @@ -99,6 +102,11 @@ public XMaterial getXMaterial( Block spigotBlock ) { spigotBlock.getType().name())); } + + if ( results != null ) { + + putCachedXMaterial( spigotBlock, NO_DATA_VALUE, results ); + } } } From 88dd7e4d9fd6a714f5e81b88c4988bec7ed355dd Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 5 Dec 2021 18:46:49 -0500 Subject: [PATCH 189/283] Renamed Prison's PlayerListener to PrisonPlayerListener to reduce a conflict and to make it more obvious which object is which. --- docs/changelog_v3.3.x.md | 3 +++ ...eractEvent.java => PrisonPlayerInteractEvent.java} | 4 ++-- .../mcprison/prison/selection/SelectionListener.java | 9 +++++---- .../tech/mcprison/prison/spigot/SpigotListener.java | 11 ++++++----- 4 files changed, 16 insertions(+), 11 deletions(-) rename prison-core/src/main/java/tech/mcprison/prison/internal/events/player/{PlayerInteractEvent.java => PrisonPlayerInteractEvent.java} (92%) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 6ff6cef2e..046597c00 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.9 2021-12-05 +* **Renamed Prison's PlayerListener to PrisonPlayerListener to reduce a conflict and to make it more obvious which object is which.** + + * **For the bukkit 1.8 through bukkit 1.12, if an object has a different data value than what it normally has**, it would not be matched through XMaterials... Examples are leaves, chests, etc... if there is no match initially using the block then try to then match on just the name, which eliminates the problem of a failed match. diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/events/player/PlayerInteractEvent.java b/prison-core/src/main/java/tech/mcprison/prison/internal/events/player/PrisonPlayerInteractEvent.java similarity index 92% rename from prison-core/src/main/java/tech/mcprison/prison/internal/events/player/PlayerInteractEvent.java rename to prison-core/src/main/java/tech/mcprison/prison/internal/events/player/PrisonPlayerInteractEvent.java index 0f34ec64f..ab5a328f7 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/events/player/PlayerInteractEvent.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/events/player/PrisonPlayerInteractEvent.java @@ -29,7 +29,7 @@ * @author Faizaan A. Datoo * @since API 1.0 */ -public class PlayerInteractEvent implements Cancelable { +public class PrisonPlayerInteractEvent implements Cancelable { private Player player; private ItemStack itemInHand; @@ -37,7 +37,7 @@ public class PlayerInteractEvent implements Cancelable { private Location clicked; private boolean canceled = false; - public PlayerInteractEvent(Player player, ItemStack itemInHand, Action action, + public PrisonPlayerInteractEvent(Player player, ItemStack itemInHand, Action action, Location clicked) { this.player = player; this.itemInHand = itemInHand; diff --git a/prison-core/src/main/java/tech/mcprison/prison/selection/SelectionListener.java b/prison-core/src/main/java/tech/mcprison/prison/selection/SelectionListener.java index 4c63844d7..7faf7efe7 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/selection/SelectionListener.java +++ b/prison-core/src/main/java/tech/mcprison/prison/selection/SelectionListener.java @@ -23,7 +23,7 @@ import tech.mcprison.prison.PrisonAPI; import tech.mcprison.prison.internal.ItemStack; import tech.mcprison.prison.internal.Player; -import tech.mcprison.prison.internal.events.player.PlayerInteractEvent; +import tech.mcprison.prison.internal.events.player.PrisonPlayerInteractEvent; /** * @author Faizaan A. Datoo @@ -34,7 +34,8 @@ public void init() { Prison.get().getEventBus().register(this); } - @Subscribe public void onPlayerInteract(PlayerInteractEvent e) { + @Subscribe + public void onPlayerInteract(PrisonPlayerInteractEvent e) { ItemStack ourItem = e.getItemInHand(); ItemStack toolItem = SelectionManager.SELECTION_TOOL; @@ -43,7 +44,7 @@ public void init() { } e.setCanceled(true); - if (e.getAction() == PlayerInteractEvent.Action.LEFT_CLICK_BLOCK) { + if (e.getAction() == PrisonPlayerInteractEvent.Action.LEFT_CLICK_BLOCK) { // Set first position Selection sel = Prison.get().getSelectionManager().getSelection(e.getPlayer()); sel.setMin(e.getClicked()); @@ -52,7 +53,7 @@ public void init() { .sendMessage("&7First position set to &8" + e.getClicked().toBlockCoordinates()); checkForEvent(e.getPlayer(), sel); - } else if (e.getAction() == PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK) { + } else if (e.getAction() == PrisonPlayerInteractEvent.Action.RIGHT_CLICK_BLOCK) { // Set second position Selection sel = Prison.get().getSelectionManager().getSelection(e.getPlayer()); sel.setMax(e.getClicked()); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotListener.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotListener.java index 3f421a655..96c407585 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotListener.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotListener.java @@ -46,6 +46,7 @@ import tech.mcprison.prison.internal.events.player.PlayerChatEvent; import tech.mcprison.prison.internal.events.player.PlayerPickUpItemEvent; import tech.mcprison.prison.internal.events.player.PlayerSuffocationEvent; +import tech.mcprison.prison.internal.events.player.PrisonPlayerInteractEvent; import tech.mcprison.prison.internal.events.world.PrisonWorldLoadEvent; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.block.OnBlockBreakEventListener.BlockBreakPriority; @@ -213,9 +214,10 @@ public void onPlayerInteract(PlayerInteractEvent e) { // TODO Accept air events (block is null when air is clicked...) // Check to see if we support the Action - tech.mcprison.prison.internal.events.player.PlayerInteractEvent.Action[] values = tech.mcprison.prison.internal.events.player.PlayerInteractEvent.Action.values(); + PrisonPlayerInteractEvent.Action[] values = PrisonPlayerInteractEvent.Action.values(); + boolean has = false; - for (tech.mcprison.prison.internal.events.player.PlayerInteractEvent.Action value : values) { + for ( PrisonPlayerInteractEvent.Action value : values) { if(value.name().equals(e.getAction().name())) has = true; } if(!has) return; // we don't support this Action @@ -228,12 +230,11 @@ public void onPlayerInteract(PlayerInteractEvent e) { } org.bukkit.Location block = e.getClickedBlock().getLocation(); - tech.mcprison.prison.internal.events.player.PlayerInteractEvent event = - new tech.mcprison.prison.internal.events.player.PlayerInteractEvent( + PrisonPlayerInteractEvent event = new PrisonPlayerInteractEvent( new SpigotPlayer(e.getPlayer()), SpigotUtil.bukkitItemStackToPrison( SpigotCompatibility.getInstance().getItemInMainHand(e)), - tech.mcprison.prison.internal.events.player.PlayerInteractEvent.Action + PrisonPlayerInteractEvent.Action .valueOf(e.getAction().name()), new Location(new SpigotWorld(block.getWorld()), block.getX(), block.getY(), block.getZ())); From 129cec85217619c5ad3fba691a7ad230b0b39662 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 5 Dec 2021 18:47:18 -0500 Subject: [PATCH 190/283] Renamed Prison's PlayerListener to PrisonPlayerListener to reduce a conflict and to make it more obvious which object is which. --- .../mcprison/prison/selection/SelectionTest.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/prison-core/src/test/java/tech/mcprison/prison/selection/SelectionTest.java b/prison-core/src/test/java/tech/mcprison/prison/selection/SelectionTest.java index b1d2a8bfa..8c01dfa75 100644 --- a/prison-core/src/test/java/tech/mcprison/prison/selection/SelectionTest.java +++ b/prison-core/src/test/java/tech/mcprison/prison/selection/SelectionTest.java @@ -28,7 +28,7 @@ import tech.mcprison.prison.TestWorld; import tech.mcprison.prison.internal.ItemStack; import tech.mcprison.prison.internal.World; -import tech.mcprison.prison.internal.events.player.PlayerInteractEvent; +import tech.mcprison.prison.internal.events.player.PrisonPlayerInteractEvent; import tech.mcprison.prison.util.BlockType; import tech.mcprison.prison.util.Location; import tech.mcprison.prison.util.Text; @@ -59,13 +59,13 @@ public class SelectionTest { coloredToolItemStack .setDisplayName(Text.translateAmpColorCodes(coloredToolItemStack.getDisplayName())); - Prison.get().getEventBus().post(new PlayerInteractEvent(ourPlayer, coloredToolItemStack, - PlayerInteractEvent.Action.LEFT_CLICK_BLOCK, new Location(ourWorld, 10, 20, 30))); + Prison.get().getEventBus().post(new PrisonPlayerInteractEvent(ourPlayer, coloredToolItemStack, + PrisonPlayerInteractEvent.Action.LEFT_CLICK_BLOCK, new Location(ourWorld, 10, 20, 30))); assertTrue(ourPlayer.getInput().contains("&7First position set to &8(10, 20, 30)")); - Prison.get().getEventBus().post(new PlayerInteractEvent(ourPlayer, coloredToolItemStack, - PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK, new Location(ourWorld, 30, 20, 40))); + Prison.get().getEventBus().post(new PrisonPlayerInteractEvent(ourPlayer, coloredToolItemStack, + PrisonPlayerInteractEvent.Action.RIGHT_CLICK_BLOCK, new Location(ourWorld, 30, 20, 40))); assertTrue(ourPlayer.getInput().contains("&7Second position set to &8(30, 20, 40)")); } @@ -79,8 +79,8 @@ public class SelectionTest { int initialAmount = ourPlayer.getInput().size(); Prison.get().getEventBus().post( - new PlayerInteractEvent(ourPlayer, new ItemStack("test", 1, BlockType.ACACIA_SAPLING), - PlayerInteractEvent.Action.LEFT_CLICK_BLOCK, new Location(ourWorld, 10, 20, 30))); + new PrisonPlayerInteractEvent(ourPlayer, new ItemStack("test", 1, BlockType.ACACIA_SAPLING), + PrisonPlayerInteractEvent.Action.LEFT_CLICK_BLOCK, new Location(ourWorld, 10, 20, 30))); assertEquals(initialAmount, ourPlayer.getInput() .size()); // nothing should have happened because we have the wrong item in our hand From eab6d48288773c5ca4098cadbac9c1056736f6c7 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 5 Dec 2021 18:53:29 -0500 Subject: [PATCH 191/283] Added a new debug mode to inspect blocks by click on them with the mine wand tool when prison is in debug mode. --- docs/changelog_v3.3.x.md | 3 + .../events/AutoManagerBlockBreakEvents.java | 2 + .../events/PrisonDebugBlockInspector.java | 105 ++++++++++++++++++ .../spigot/block/OnBlockBreakMines.java | 9 +- 4 files changed, 117 insertions(+), 2 deletions(-) create mode 100644 prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/PrisonDebugBlockInspector.java diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 046597c00..3385d5ee6 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.9 2021-12-05 +* **Added a new debug mode to inspect blocks by click on them with the mine wand tool when prison is in debug mode.** + + * **Renamed Prison's PlayerListener to PrisonPlayerListener to reduce a conflict and to make it more obvious which object is which.** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerBlockBreakEvents.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerBlockBreakEvents.java index 15f1b2f5f..761f24647 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerBlockBreakEvents.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerBlockBreakEvents.java @@ -53,6 +53,8 @@ public void registerEvents() { new AutoManagerTokenEnchant().registerEvents(); new AutoManagerZenchantments().registerEvents(); + + new PrisonDebugBlockInspector().init(); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/PrisonDebugBlockInspector.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/PrisonDebugBlockInspector.java new file mode 100644 index 000000000..f4c7345cc --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/PrisonDebugBlockInspector.java @@ -0,0 +1,105 @@ +package tech.mcprison.prison.spigot.autofeatures.events; + +import java.util.UUID; + +import com.google.common.eventbus.Subscribe; + +import tech.mcprison.prison.Prison; +import tech.mcprison.prison.internal.ItemStack; +import tech.mcprison.prison.internal.Player; +import tech.mcprison.prison.internal.block.MineTargetPrisonBlock; +import tech.mcprison.prison.internal.events.player.PrisonPlayerInteractEvent; +import tech.mcprison.prison.mines.data.Mine; +import tech.mcprison.prison.output.Output; +import tech.mcprison.prison.selection.SelectionManager; +import tech.mcprison.prison.spigot.block.OnBlockBreakMines; +import tech.mcprison.prison.spigot.block.SpigotBlock; +import tech.mcprison.prison.util.Location; + +public class PrisonDebugBlockInspector + extends OnBlockBreakMines +{ + + public void init() { + Prison.get().getEventBus().register(this); + } + + @Subscribe + public void onPlayerInteract( PrisonPlayerInteractEvent e ) { + ItemStack ourItem = e.getItemInHand(); + ItemStack toolItem = SelectionManager.SELECTION_TOOL; + + if ( !ourItem.equals(toolItem) || !Output.get().isDebug() ) { + return; + } + //e.setCanceled(true); + + Player player = e.getPlayer(); + + Location location = e.getClicked(); + SpigotBlock sBlock = (SpigotBlock) location.getBlockAt(); + + UUID playerUUID = e.getPlayer().getUUID(); + Mine mine = findMine( playerUUID, sBlock, null, null ); + + if ( mine == null ) { + + player.sendMessage( + String.format( + "&dDebugBlockInfo: &7Not in a mine. &5%s &7%s", + sBlock.getBlockName(), location.toWorldCoordinates()) ); + + } + else { + player.sendMessage( + String.format( + "&dDebugBlockInfo: &3Mine &7%s. " + + "&5%s &7%s", + mine.getName(), + sBlock.getBlockName(), + location.toWorldCoordinates()) ); + + // Get the mine's targetBlock: + MineTargetPrisonBlock tBlock = mine.getTargetPrisonBlock( sBlock ); + + String message = String.format( "&3TargetBlock: &7%s " + + "&3isMined: &7%b &3isBroke: &7%b", + tBlock.getPrisonBlock().getBlockName(), + tBlock.isMined(), + tBlock.isAirBroke() + ); + + player.sendMessage( message ); + + String message2 = String.format( " &3isCounted: &7%b &3isEdge: &7%b " + + "&3isIgnorAllBlockEvents: &7%b", + tBlock.isCounted(), + tBlock.isEdge(), + tBlock.isIgnoreAllBlockEvents() + ); + + player.sendMessage( message2 ); + } + + +// if (e.getAction() == PrisonPlayerInteractEvent.Action.LEFT_CLICK_BLOCK) { +// // Set first position +// Selection sel = Prison.get().getSelectionManager().getSelection(e.getPlayer()); +// sel.setMin(e.getClicked()); +// Prison.get().getSelectionManager().setSelection(e.getPlayer(), sel); +// e.getPlayer() +// .sendMessage("&7First position set to &8" + e.getClicked().toBlockCoordinates()); +// +// checkForEvent(e.getPlayer(), sel); +// } else if (e.getAction() == PrisonPlayerInteractEvent.Action.RIGHT_CLICK_BLOCK) { +// // Set second position +// Selection sel = Prison.get().getSelectionManager().getSelection(e.getPlayer()); +// sel.setMax(e.getClicked()); +// Prison.get().getSelectionManager().setSelection(e.getPlayer(), sel); +// e.getPlayer() +// .sendMessage("&7Second position set to &8" + e.getClicked().toBlockCoordinates()); +// +// checkForEvent(e.getPlayer(), sel); +// } + } +} diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakMines.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakMines.java index b96881007..04f6618ae 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakMines.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakMines.java @@ -3,6 +3,7 @@ import java.util.List; import java.util.Optional; import java.util.TreeMap; +import java.util.UUID; import org.bukkit.block.Block; import org.bukkit.entity.Player; @@ -32,8 +33,12 @@ public OnBlockBreakMines() { public Mine findMine( Player player, SpigotBlock sBlock, List altBlocksSource, PrisonMinesBlockBreakEvent pmEvent ) { - - Long playerUUIDLSB = Long.valueOf( player.getUniqueId().getLeastSignificantBits() ); + return findMine( player.getUniqueId(), sBlock, altBlocksSource, pmEvent ); + } + + public Mine findMine( UUID playerUUID, SpigotBlock sBlock, List altBlocksSource, PrisonMinesBlockBreakEvent pmEvent ) + { + Long playerUUIDLSB = Long.valueOf( playerUUID.getLeastSignificantBits() ); // Get the cached mine, if it exists: Mine mine = getPlayerCache().get( playerUUIDLSB ); From 24d967b4e8c795d30efb8a3634894918b9995b0d Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Mon, 6 Dec 2021 00:27:01 -0500 Subject: [PATCH 192/283] Bug fix: There was an issue that I found where blocks outside of the explosion events were being marked as mined without actually being broken. Therefore prison would not be able to break those blocks. This was caused by the initial explosion setting off a chained reaction explosion through a blockEvent. Now blocks that are part of an explosion cannot be part of a future explosion. --- docs/changelog_v3.3.x.md | 4 + .../internal/block/MineTargetPrisonBlock.java | 9 +- .../events/PrisonDebugBlockInspector.java | 12 +- .../spigot/block/OnBlockBreakEventCore.java | 204 ++++++++++++------ 4 files changed, 155 insertions(+), 74 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 3385d5ee6..7b18cc85c 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.9 2021-12-05 +* **Bug fix: There was an issue that I found where blocks outside of the explosion events were being marked as mined without actually being broken.** +Therefore prison would not be able to break those blocks. This was caused by the initial explosion setting off a chained reaction explosion through a blockEvent. Now blocks that are part of an explosion cannot be part of a future explosion. + + * **Added a new debug mode to inspect blocks by click on them with the mine wand tool when prison is in debug mode.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetPrisonBlock.java b/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetPrisonBlock.java index 06f301489..91cc4dd59 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetPrisonBlock.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetPrisonBlock.java @@ -12,7 +12,7 @@ public class MineTargetPrisonBlock private boolean airBroke; private boolean isEdge; - + private boolean exploded; private boolean mined = false; private Block minedBlock; @@ -125,6 +125,13 @@ public void setEdge( boolean isEdge ) { this.isEdge = isEdge; } + public boolean isExploded() { + return exploded; + } + public void setExploded( boolean exploded ) { + this.exploded = exploded; + } + public boolean isMined() { return mined; } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/PrisonDebugBlockInspector.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/PrisonDebugBlockInspector.java index f4c7345cc..9c2d4ae80 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/PrisonDebugBlockInspector.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/PrisonDebugBlockInspector.java @@ -62,19 +62,23 @@ public void onPlayerInteract( PrisonPlayerInteractEvent e ) { // Get the mine's targetBlock: MineTargetPrisonBlock tBlock = mine.getTargetPrisonBlock( sBlock ); + String message = String.format( "&3TargetBlock: &7%s " + - "&3isMined: &7%b &3isBroke: &7%b", - tBlock.getPrisonBlock().getBlockName(), + "&3Mined: %s%b &3Broke: &7%b", + tBlock.getPrisonBlock().getBlockName(), + (tBlock.isMined() ? "&d" : "&2"), tBlock.isMined(), tBlock.isAirBroke() ); player.sendMessage( message ); - String message2 = String.format( " &3isCounted: &7%b &3isEdge: &7%b " + - "&3isIgnorAllBlockEvents: &7%b", + String message2 = String.format( " &3Counted: &7%b &3Edge: &7%b " + + "&3Exploded: %s%b &3IgnorAllEvents: &7%b", tBlock.isCounted(), tBlock.isEdge(), + (tBlock.isExploded() ? "&d" : "&2"), + tBlock.isExploded(), tBlock.isIgnoreAllBlockEvents() ); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index 800a97f41..838d5297f 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -558,13 +558,21 @@ private boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent, StringBuilder boolean results = true; - Mine mine = findMine( pmEvent.getPlayer(), pmEvent.getSpigotBlock(), + SpigotBlock sBlockHit = pmEvent.getSpigotBlock(); + + Mine mine = findMine( pmEvent.getPlayer(), sBlockHit, pmEvent.getUnprocessedRawBlocks(), pmEvent ); pmEvent.setMine( mine ); debugInfo.append( "mine=" + (mine == null ? "none" : mine.getName()) + " " ); + debugInfo.append( sBlockHit.getLocation().toWorldCoordinates() ).append( " " ); + + // Since BlastUseEvent (crazy enchant) does not identify the block that is initially + // broke, an explosion for them is greater than 1. + boolean isExplosionEvent = pmEvent.getUnprocessedRawBlocks().size() > + (pmEvent.getBlockEventType() == BlockEventType.CEXplosion ? 0 : 1); // validate the blocks, if there are some. Add them to the exploded blocks list if ( mine != null ) { @@ -577,11 +585,15 @@ private boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent, StringBuilder boolean targetBlockAlreadyMined = false; // Get the mine's targetBlock: - MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( pmEvent.getSpigotBlock() ); + MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlockHit ); pmEvent.setTargetBlock( targetBlock ); - // If ignore all block events has been set on this target block, then shutdown - if ( targetBlock != null && targetBlock.isIgnoreAllBlockEvents() ) { + // If ignore all block events has been set on this target block, then shutdown. + // Same if this block was already included in an explosion... prevent it from spawning + // more explosions, which could result in a chain reaction. + if ( targetBlock != null && + (targetBlock.isIgnoreAllBlockEvents() || + targetBlock.isExploded()) ) { debugInfo.setLength( 0 ); pmEvent.setForceIfAirBlock( false ); @@ -593,7 +605,7 @@ private boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent, StringBuilder } // NOTE: for the primary block pmEvent.getSpigotBlock() the unbreakable will be checked later: - if ( targetBlock != null && targetBlock.getPrisonBlock() != null ) { + if ( targetBlock != null && sBlockHit != null ) { if ( !targetBlock.isMined() || !targetBlock.isAirBroke() ) { @@ -603,20 +615,38 @@ private boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent, StringBuilder // high-speed or concurrent operations from multiple players from trying to // process the same block. - // If a chain reaction on explosions, this will prevent the same block from - // being processed more than once: - targetBlock.setMined( true ); - - if ( targetBlock.getPrisonBlock().equals( pmEvent.getSpigotBlock().getPrisonBlock() ) && - collectBukkitDrops( pmEvent.getBukkitDrops(), targetBlock, pmEvent.getItemInHand(), pmEvent.getSpigotBlock() )) { + if ( targetBlock.getPrisonBlock().equals( sBlockHit.getPrisonBlock() ) && + collectBukkitDrops( pmEvent.getBukkitDrops(), targetBlock, pmEvent.getItemInHand(), sBlockHit )) { + + + // If a chain reaction on explosions, this will prevent the same block from + // being processed more than once: + targetBlock.setMined( true ); - targetBlock.setMinedBlock( pmEvent.getSpigotBlock() ); + targetBlock.setMinedBlock( sBlockHit ); + + // Mark the block as being part of an explosion, if it was: + targetBlock.setExploded( isExplosionEvent ); + } else { // The block is not the correct type. It has been changed since the mine was reset // so it cannot be processed. + + if ( Output.get().isDebug( DebugTarget.targetBlockMismatch ) ) { + + String message = String.format( + "TargetBlock mismatch error - primaryBlock: targetBlock: %s blockBroke: %s", + targetBlock.getPrisonBlock().getBlockName() , + sBlockHit.getPrisonBlock().getBlockName() + ); + + Output.get().logWarn( message ); + + } + // Prevent this block from being processed again, or attempted to be processed: targetBlockAlreadyMined = true; @@ -629,6 +659,12 @@ private boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent, StringBuilder pmEvent.setCancelOriginalEvent( false ); blockTypeNotExpected++; + + if ( !pmEvent.isForceIfAirBlock() ) { + + results = false; + } + } @@ -666,76 +702,106 @@ private boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent, StringBuilder } - for ( Block bukkitBlock : pmEvent.getUnprocessedRawBlocks() ) - { - SpigotBlock sBlock = new SpigotBlock( bukkitBlock ); + // Don't start processing the unprocessedRawBlocks unless results is true, otherwise some + // of the blocks could be marked as being mined but then never processed. + if ( results ) { - // Thanks to CrazyEnchant, there is no telling which block was actually hit, so - // if using CrazyEnchant one of the unprocessedRawBlocks may be the same as the - // pmEvent.getSpigotBlock(), so ignore if both are the same. - if ( !sBlock.equals( pmEvent.getSpigotBlock() ) ) { + for ( Block bukkitBlock : pmEvent.getUnprocessedRawBlocks() ) + { + SpigotBlock sBlock = new SpigotBlock( bukkitBlock ); - if ( BlockUtils.getInstance().isUnbreakable( sBlock ) ) { + // Thanks to CrazyEnchant, there is no telling which block was actually hit, so + // if using CrazyEnchant one of the unprocessedRawBlocks may be the same as the + // pmEvent.getSpigotBlock(), so ignore if both are the same. + if ( !sBlock.equals( sBlockHit ) ) { - unbreakable++; - } - else if ( mine.isInMineExact( sBlock.getLocation() ) ) { - - // Get the mine's targetBlock: - MineTargetPrisonBlock targetExplodedBlock = mine.getTargetPrisonBlock( sBlock ); + if ( !mine.isInMineExact( sBlock.getLocation() ) ) { + outsideOfMine++; + } + else if ( BlockUtils.getInstance().isUnbreakable( sBlock ) ) { + + unbreakable++; + } - if ( targetExplodedBlock != null && targetExplodedBlock.getPrisonBlock() != null ) { + else if ( sBlock.isEmpty() ) { + alreadyMined++; + } + else { + + // Get the mine's targetBlock: + MineTargetPrisonBlock targetExplodedBlock = mine.getTargetPrisonBlock( sBlock ); - if ( targetExplodedBlock.isMined() ) { + if ( targetExplodedBlock == null || targetExplodedBlock.getPrisonBlock() == null ) { - alreadyMined++; + // No targetBlock so add it anyway: + pmEvent.getExplodedBlocks().add( sBlock ); + + noTargetBlock++; } - else if ( results && !targetExplodedBlock.isMined() ) { + + else if ( targetExplodedBlock.isMined() ) { - // Check to make sure the block is the same block that was placed there. - // If not, then do not process it. - SpigotBlock sBlockMined = new SpigotBlock( bukkitBlock ); - PrisonBlock pBlockMined = sBlockMined.getPrisonBlock(); + alreadyMined++; + } + else { - if ( targetExplodedBlock.getPrisonBlock().equals( pBlockMined ) && - collectBukkitDrops( pmEvent.getBukkitDrops(), targetExplodedBlock, pmEvent.getItemInHand(), sBlockMined ) ) { + if ( !targetExplodedBlock.isMined() ) { - // If a chain reaction on explosions, this will prevent the same block from - // being processed more than once: - targetExplodedBlock.setMined( true ); + // Check to make sure the block is the same block that was placed there. + // If not, then do not process it. + SpigotBlock sBlockMined = new SpigotBlock( bukkitBlock ); + PrisonBlock pBlockMined = sBlockMined.getPrisonBlock(); - targetExplodedBlock.setMinedBlock( sBlock ); + if ( targetExplodedBlock.getPrisonBlock().equals( pBlockMined ) && + collectBukkitDrops( pmEvent.getBukkitDrops(), targetExplodedBlock, pmEvent.getItemInHand(), sBlockMined ) ) { + + // If a chain reaction on explosions, this will prevent the same block from + // being processed more than once: + targetExplodedBlock.setMined( true ); + + targetExplodedBlock.setMinedBlock( sBlock ); + + + // Mark the block as being part of an explosion, if it was: + targetExplodedBlock.setExploded( isExplosionEvent ); + + + pmEvent.getExplodedBlocks().add( sBlock ); + pmEvent.getTargetExplodedBlocks().add( targetExplodedBlock ); + + + } + else { + // The block is not the correct type. It has been changed since the mine was reset + // so it cannot be processed. + + + if ( Output.get().isDebug( DebugTarget.targetBlockMismatch ) ) { + + String message = String.format( + "TargetBlock mismatch error - multiBLock: targetBlock: %s blockBroke: %s", + targetBlock.getPrisonBlock().getBlockName() , + sBlockHit.getPrisonBlock().getBlockName() + ); + + Output.get().logWarn( message ); + + } + + + // Prevent this block from being processed again, or attempted to be processed: + + targetExplodedBlock.setMined( true ); + targetExplodedBlock.setAirBroke( true ); + targetExplodedBlock.setIgnoreAllBlockEvents( true ); + + blockTypeNotExpected++; + } - pmEvent.getExplodedBlocks().add( sBlock ); - pmEvent.getTargetExplodedBlocks().add( targetExplodedBlock ); - - } - else { - // The block is not the correct type. It has been changed since the mine was reset - // so it cannot be processed. - - // Prevent this block from being processed again, or attempted to be processed: - - targetExplodedBlock.setMined( true ); - targetExplodedBlock.setAirBroke( true ); - targetExplodedBlock.setIgnoreAllBlockEvents( true ); - - blockTypeNotExpected++; } - - } } - else if ( results ) { - // No targetBlock so add it anyway: - pmEvent.getExplodedBlocks().add( sBlock ); - - noTargetBlock++; - } - } - else { - outsideOfMine++; } } } @@ -823,7 +889,7 @@ else if ( results ) { debugInfo.append( "UNUSABLE_TOOL__WORN_OUT (event canceled) " ); results = false; } - if ( mine != null && BlockUtils.getInstance().isUnbreakable( pmEvent.getSpigotBlock() ) ) { + if ( mine != null && BlockUtils.getInstance().isUnbreakable( sBlockHit ) ) { // The block is unbreakable because a utility has it locked: pmEvent.setCancelOriginalEvent( true ); @@ -849,7 +915,7 @@ else if ( results ) { // then everything related to auto manager is disabled. String triggered = null; - doActionBlockEventOnly( pmEvent.getSpigotBlock(), mine, pmEvent.getPlayer(), + doActionBlockEventOnly( sBlockHit, mine, pmEvent.getPlayer(), BlockEventType.blockBreak, triggered ); debugInfo.append( "(actionBlockEventOnly singluar) " ); @@ -877,7 +943,7 @@ else if ( results && pmEvent.isMonitor() && mine == null ) { } else if ( results && pmEvent.isMonitor() && mine != null ) { - doActionMonitor( pmEvent.getSpigotBlock(), mine ); + doActionMonitor( sBlockHit, mine ); debugInfo.append( "(monitor - singular) " ); From a59b4b0f675cb9d965b762a6fb9a24540c0c3311 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Mon, 6 Dec 2021 13:10:19 -0500 Subject: [PATCH 193/283] Released v3.2.11-alpha.10. --- docs/changelog_v3.3.x.md | 6 ++- docs/knownissues_v3.3.x.md | 86 +++++++++++++++++++++++--------------- gradle.properties | 2 +- 3 files changed, 58 insertions(+), 36 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 7b18cc85c..6236c84c4 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,11 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.9 2021-12-05 +# 3.2.11-alpha.10 2021-12-05 + + + +* **3.2.11-alpha.10 2021-12-05** * **Bug fix: There was an issue that I found where blocks outside of the explosion events were being marked as mined without actually being broken.** diff --git a/docs/knownissues_v3.3.x.md b/docs/knownissues_v3.3.x.md index d740c7c73..6684c3240 100644 --- a/docs/knownissues_v3.3.x.md +++ b/docs/knownissues_v3.3.x.md @@ -15,13 +15,6 @@ - Simple to implement some features, including flying in a mine. - -* DONE: Revert a mine to a virtual mine. Maybe with the command: `/mines set area *virtual*`. Backup the mine's data file before updating and saving. - - -* DONE: the command /mines reset *all* is not working correctly. Could be an issue with the chaining not submitting the next reset since this is all done through async processes right now. - - **List for v3.2.11 release:** @@ -39,31 +32,15 @@ - most online time, or most mining time (which will probably be better) - -* DONE: Add a few more options to auto features for auto sell, such on full inventory. This was removed recently to stabilize some of the new code. - - Just refined what was already there. - - * Issue with blocks. Explosions are creating "untouchable" blocks that cannot be included in other explosions. - My observations were with multiple explosions leaving rings that are within the the radius of an explosion - I could break the blocks. - jamo said that the pillars that were created on his server could not be broke -* DONE: Concurrent modification error on the MineTargetPrisonBlock when resetting the mine. - tech.mcprison.prison.spigot.game.SpigotWorld.setBlocksSynchronously() (146). - Serialize Id the mine resets and provide a locking mechanism that will prevent auto features from being processed when it goes in to a reset mode. Also when in a reset mode, prevent another reset from being submitted so they cannot run concurrently or back to back. Maybe attach a cooldown to the resets too, such as 10 seconds would be long enough to prevent a runaway chained reaction. - - DONE: Create an object such as a MineStateToken that will hold the state of the mine reset (in progress, mineable, stable, usable, locked, etc... not sure proper terminology right now... or how many states), with a serial number that will be incremented on each reset. - - (on hold) Do not perform a clear on the collection of MineTargetPrisonBlocks within the mine. Just replace the collection with a new collection and let the garbage collection handle reclaiming all resources. Carefully review for possible memory leaks. May be a good idea to hold on to that collection and submit a task that runs in about 30 seconds to perform a clear on the collection to release the resources. This may be important since the target blocks contains references to the stats blocks and may not be GC'd automatically. May want to null those refs first too. - MineReset.clearMineTargetPrisonBlocks() (1799) - - -* DONE: PlayerCache Time per Mine stats - not recording correctly. * Review placeholders - add and test placeholders that are tied to playerCache stats -* DONE: new auto features autosell should place items in inventory that have no sell value. Items that cannot be auto sold. - * Mine Bombs - Finish - Add sound and particle effects - Other features? @@ -111,17 +88,6 @@ Not sure if it needs to? Need to test and confirm if working correctly. World -* DONE: New update to combine block processing results in many block.getDrops() being combined. Since they are combined, the extended fortune calculations may not work properly since it does not know how many original blocks were included. -- May need to have an intermediate object to better collect original blocks, drops, and targetBlocks. It can include some of the more basics that are not tracked, such as original block count to better calculate the fortunes. - - - -* DONE: Rewrite the `/prison utils titles` to use XSeries' title commands. XSeries only supports 1.9+ so I still need to support 1.8.8 directly within prison. - - - -* DONE: Common messaging framework so if hundreds of messages are sent, only one is displayed. Eliminate the duplicates. - - Not sure why the following would be needed: * Auto Features Settings : Create an API object that has the auto features settings listed. Basically this would serve as a simple cache with a life span of about 10 seconds. So if a player is mining hundreds of blocks within 10 seconds, odds are these settings will not be changing... both server config settings, and the player's permissions. Can provide helper classes that will a simple check of all these details, such as passing tool in hand to check perms for auto pickup settings for the server, the player's perms and lore on the tool. ... as an example. @@ -615,6 +581,58 @@ Offers for translation:
+# Features recently added for v3.2.11 + + + + + + + + + + +* DONE: New update to combine block processing results in many block.getDrops() being combined. Since they are combined, the extended fortune calculations may not work properly since it does not know how many original blocks were included. +- May need to have an intermediate object to better collect original blocks, drops, and targetBlocks. It can include some of the more basics that are not tracked, such as original block count to better calculate the fortunes. + + + +* DONE: Rewrite the `/prison utils titles` to use XSeries' title commands. XSeries only supports 1.9+ so I still need to support 1.8.8 directly within prison. + + + +* DONE: Common messaging framework so if hundreds of messages are sent, only one is displayed. Eliminate the duplicates. + + + + +* DONE: Revert a mine to a virtual mine. Maybe with the command: `/mines set area *virtual*`. Backup the mine's data file before updating and saving. + + +* DONE: the command /mines reset *all* is not working correctly. Could be an issue with the chaining not submitting the next reset since this is all done through async processes right now. + + +* DONE: Add a few more options to auto features for auto sell, such on full inventory. This was removed recently to stabilize some of the new code. + - Just refined what was already there. + + + + +* DONE: Concurrent modification error on the MineTargetPrisonBlock when resetting the mine. + tech.mcprison.prison.spigot.game.SpigotWorld.setBlocksSynchronously() (146). + Serialize Id the mine resets and provide a locking mechanism that will prevent auto features from being processed when it goes in to a reset mode. Also when in a reset mode, prevent another reset from being submitted so they cannot run concurrently or back to back. Maybe attach a cooldown to the resets too, such as 10 seconds would be long enough to prevent a runaway chained reaction. + - DONE: Create an object such as a MineStateToken that will hold the state of the mine reset (in progress, mineable, stable, usable, locked, etc... not sure proper terminology right now... or how many states), with a serial number that will be incremented on each reset. + - (on hold) Do not perform a clear on the collection of MineTargetPrisonBlocks within the mine. Just replace the collection with a new collection and let the garbage collection handle reclaiming all resources. Carefully review for possible memory leaks. May be a good idea to hold on to that collection and submit a task that runs in about 30 seconds to perform a clear on the collection to release the resources. This may be important since the target blocks contains references to the stats blocks and may not be GC'd automatically. May want to null those refs first too. + MineReset.clearMineTargetPrisonBlocks() (1799) + +* DONE: PlayerCache Time per Mine stats - not recording correctly. + +* DONE: new auto features autosell should place items in inventory that have no sell value. Items that cannot be auto sold. + + + + + # Features recently added for v3.2.10 diff --git a/gradle.properties b/gradle.properties index 2498661be..7ab066e1e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ ## # This is actually the "correct" place to define the version for the project. ## # Used within build.gradle with ${project.version}. ## # Can be overridden on the command line: gradle -Pversion=3.2.1-alpha.3 -version=3.2.11-alpha.9 +version=3.2.11-alpha.10 #version=3.2.8.2 #version=3.3.0-alpha.6 From 51611fa4a43824aa76f820f664b6bc240300bf49 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Mon, 6 Dec 2021 16:35:49 -0500 Subject: [PATCH 194/283] Upgrade XSeries to v8.5.0 --- docs/changelog_v3.3.x.md | 5 ++++- prison-spigot/build.gradle | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 6236c84c4..a3d088eb1 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,10 +13,13 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.10 2021-12-05 +# 3.2.11-alpha.10 2021-12-06 +* **Upgrade XSeries to v8.5.0** + + * **3.2.11-alpha.10 2021-12-05** diff --git a/prison-spigot/build.gradle b/prison-spigot/build.gradle index 322701478..72a955d71 100644 --- a/prison-spigot/build.gradle +++ b/prison-spigot/build.gradle @@ -105,7 +105,7 @@ dependencies { // implementation 'com.github.cryptomorin:xseries:b95d195482' // https://mvnrepository.com/artifact/com.github.cryptomorin/XSeries - implementation 'com.github.cryptomorin:XSeries:8.4.0' + implementation 'com.github.cryptomorin:XSeries:8.5.0' @@ -187,7 +187,7 @@ shadowJar { include(dependency('me.clip:placeholderapi:2.10.9')) - include(dependency('com.github.cryptomorin:XSeries:8.4.0')) + include(dependency('com.github.cryptomorin:XSeries:8.5.0')) //include(dependency('org.inventivetalent.spiget-update:bukkit:1.4.2-SNAPSHOT')) //include(dependency('me.badbones69:crazyenchantments-plugin:1.8-Dev-Build-v8')) From 1a4f649d92106e662181a9a612c00986d81e1710 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Mon, 6 Dec 2021 16:46:53 -0500 Subject: [PATCH 195/283] Bug fix: Fixed a class not found except caused by google guava trying to load functions that it should not have been using for their event manager. Moved the PEE event out of this class all together, so now it's safe to use in other areas of prison, such as with guava's event handler. --- docs/changelog_v3.3.x.md | 3 + .../spigot/block/OnBlockBreakEventCore.java | 21 +++ .../spigot/block/OnBlockBreakMines.java | 157 +++++++++++------- 3 files changed, 125 insertions(+), 56 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index a3d088eb1..9479ed7d1 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.10 2021-12-06 +* **Bug fix: Fixed a class not found except caused by google guava trying to load functions that it should not have been using for their event manager.** +Moved the PEE event out of this class all together, so now it's safe to use in other areas of prison, such as with guava's event handler. This was not an issue with spigot 1.8.8, but manifested itself with Spigot 1.16.5 since I believe that version of spigot is using a newer version of guava that has that behavior. + * **Upgrade XSeries to v8.5.0** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java index 838d5297f..3a1359a7a 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakEventCore.java @@ -11,6 +11,7 @@ import org.bukkit.block.Block; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; @@ -444,6 +445,26 @@ else if ( pmEvent.getMine() != null || pmEvent.getMine() == null && } } + protected boolean ignoreMinesBlockBreakEvent( Cancellable event, Player player, Block block ) { + + MinesEventResults eventResults = ignoreMinesBlockBreakEvent( player, block ); + + if ( eventResults.isCancelEvent() ) { + event.setCancelled( eventResults.isCancelEvent() ); + } + return eventResults.isIgnoreEvent(); +} + +protected boolean processMinesBlockBreakEvent( PEExplosionEvent event, Player player, Block block ) { + + MinesEventResults eventResults = ignoreMinesBlockBreakEvent( player, block ); + + if ( eventResults.isCancelEvent() ) { + event.setCancelled( eventResults.isCancelEvent() ); + } + return eventResults.isIgnoreEvent(); +} + /** *

This processes the block finalizations, which are counting the block breakage, diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakMines.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakMines.java index 04f6618ae..e4eceb864 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakMines.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakMines.java @@ -7,9 +7,7 @@ import org.bukkit.block.Block; import org.bukkit.entity.Player; -import org.bukkit.event.Cancellable; -import me.pulsi_.prisonenchants.events.PEExplosionEvent; import tech.mcprison.prison.Prison; import tech.mcprison.prison.internal.block.MineTargetPrisonBlock; import tech.mcprison.prison.mines.PrisonMines; @@ -31,6 +29,29 @@ public OnBlockBreakMines() { } + public class MinesEventResults { + private boolean cancelEvent = false; + private boolean ignoreEvent = false; + + public MinesEventResults() { + super(); + } + + public boolean isCancelEvent() { + return cancelEvent; + } + public void setCancelEvent( boolean cancelEvent ) { + this.cancelEvent = cancelEvent; + } + + public boolean isIgnoreEvent() { + return ignoreEvent; + } + public void setIgnoreEvent( boolean ignoreEvent ) { + this.ignoreEvent = ignoreEvent; + } + } + public Mine findMine( Player player, SpigotBlock sBlock, List altBlocksSource, PrisonMinesBlockBreakEvent pmEvent ) { return findMine( player.getUniqueId(), sBlock, altBlocksSource, pmEvent ); @@ -87,20 +108,44 @@ public Mine findMine( UUID playerUUID, SpigotBlock sBlock, List altBlocks } - protected boolean ignoreMinesBlockBreakEvent( Cancellable event, Player player, Block block ) { - boolean ignoreEvent = false; + // NOTE: The following two commented out functions need to be copied and actived in + // in the class that is using these functions for these two events: + +// protected boolean ignoreMinesBlockBreakEvent( Cancellable event, Player player, Block block ) { +// +// MinesEventResults eventResults = ignoreMinesBlockBreakEvent( player, block ); +// +// if ( eventResults.isCancelEvent() ) { +// event.setCancelled( eventResults.isCancelEvent() ); +// } +// return eventResults.isIgnoreEvent(); +// } +// +// protected boolean processMinesBlockBreakEvent( PEExplosionEvent event, Player player, Block block ) { +// +// MinesEventResults eventResults = ignoreMinesBlockBreakEvent( player, block ); +// +// if ( eventResults.isCancelEvent() ) { +// event.setCancelled( eventResults.isCancelEvent() ); +// } +// return eventResults.isIgnoreEvent(); +// } + + + protected MinesEventResults ignoreMinesBlockBreakEvent( Player player, Block block ) { + MinesEventResults results = new MinesEventResults(); SpigotBlock sBlock = new SpigotBlock( block ); if ( BlockUtils.getInstance().isUnbreakable( sBlock ) ) { - event.setCancelled( true ); - ignoreEvent = true; + results.setCancelEvent( true ); + results.setIgnoreEvent( true ); } Mine mine = findMine( player, sBlock, null, null ); if ( mine == null ) { // Prison is unable to process blocks outside of mines right now, so exit: - ignoreEvent = true; + results.setIgnoreEvent( true ); } else { @@ -109,8 +154,8 @@ protected boolean ignoreMinesBlockBreakEvent( Cancellable event, Player player, SpigotPlayer sPlayer = new SpigotPlayer( player ); sPlayer.setActionBar( "Mine " + mine.getTag() + " is being reset... please wait." ); - event.setCancelled( true ); - ignoreEvent = true; + results.setCancelEvent( true ); + results.setIgnoreEvent( true ); } MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); @@ -119,58 +164,58 @@ protected boolean ignoreMinesBlockBreakEvent( Cancellable event, Player player, // Do not cancel the event... let other plugins deal with it... prison does not care about this block. //event.setCancelled( true ); - ignoreEvent = true; + results.setIgnoreEvent( true ); } } - return ignoreEvent; + return results; } - /** - *

Warning... this is a temp copy of the real function and will be removed - * if PEExplosionEvent adds the interface Cancellable. - *

- * - * @param event - * @param player - * @param block - * @return - */ - protected boolean processMinesBlockBreakEvent( PEExplosionEvent event, Player player, Block block ) { - boolean processEvent = true; - - SpigotBlock sBlock = new SpigotBlock( block ); - if ( BlockUtils.getInstance().isUnbreakable( sBlock ) ) { - event.setCancelled( true ); - processEvent = false; - } - - Mine mine = findMine( player, sBlock, null, null ); - - if ( mine == null ) { - // Prison is unable to process blocks outside of mines right now, so exit: - processEvent = false; - } - - // If not minable, then display message and exit. - if ( !mine.getMineStateMutex().isMinable() ) { - - SpigotPlayer sPlayer = new SpigotPlayer( player ); - sPlayer.setActionBar( "Mine " + mine.getTag() + " is being reset... please wait." ); - event.setCancelled( true ); - processEvent = false; - } - MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); - - // If ignore all block events, then exit this function without logging anything: - if ( targetBlock.isIgnoreAllBlockEvents() ) { - event.setCancelled( true ); - processEvent = false; - } - - - return processEvent; - } +// /** +// *

Warning... this is a temp copy of the real function and will be removed +// * if PEExplosionEvent adds the interface Cancellable. +// *

+// * +// * @param event +// * @param player +// * @param block +// * @return +// */ +// protected boolean processMinesBlockBreakEvent( PEExplosionEvent event, Player player, Block block ) { +// boolean processEvent = true; +// +// SpigotBlock sBlock = new SpigotBlock( block ); +// if ( BlockUtils.getInstance().isUnbreakable( sBlock ) ) { +// event.setCancelled( true ); +// processEvent = false; +// } +// +// Mine mine = findMine( player, sBlock, null, null ); +// +// if ( mine == null ) { +// // Prison is unable to process blocks outside of mines right now, so exit: +// processEvent = false; +// } +// +// // If not minable, then display message and exit. +// if ( !mine.getMineStateMutex().isMinable() ) { +// +// SpigotPlayer sPlayer = new SpigotPlayer( player ); +// sPlayer.setActionBar( "Mine " + mine.getTag() + " is being reset... please wait." ); +// event.setCancelled( true ); +// processEvent = false; +// } +// MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); +// +// // If ignore all block events, then exit this function without logging anything: +// if ( targetBlock.isIgnoreAllBlockEvents() ) { +// event.setCancelled( true ); +// processEvent = false; +// } +// +// +// return processEvent; +// } public void checkZeroBlockReset( Mine mine ) { if ( mine != null ) { From 549254028df7c6d33d12a43c2fca29382c0e54fc Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Mon, 6 Dec 2021 17:47:23 -0500 Subject: [PATCH 196/283] Update Tokens to fix an issue with the admin set. Added better tracking of adminAdded and adminRemoved stats. --- docs/changelog_v3.3.x.md | 4 ++ .../prison/cache/PlayerCachePlayerData.java | 67 +++++++++++++------ .../prison/ranks/commands/RanksCommands.java | 13 ++-- 3 files changed, 58 insertions(+), 26 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 9479ed7d1..aa1c9df9d 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.10 2021-12-06 +* **Update Tokens to fix an issue with the admin set.** +Added better tracking of adminAdded and adminRemoved stats. + + * **Bug fix: Fixed a class not found except caused by google guava trying to load functions that it should not have been using for their event manager.** Moved the PEE event out of this class all together, so now it's safe to use in other areas of prison, such as with guava's event handler. This was not an issue with spigot 1.8.8, but manifested itself with Spigot 1.16.5 since I believe that version of spigot is using a newer version of guava that has that behavior. diff --git a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java index 87b858ca9..1ae833cfc 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCachePlayerData.java @@ -86,7 +86,8 @@ public class PlayerCachePlayerData { private long tokens; private long tokensTotal; - private long tokensTotalRemoved; + private long tokensTotalAdminAdded; + private long tokensTotalAdminRemoved; private long tokensLastBlocksTotals; private TreeMap tokensByMine; @@ -543,7 +544,7 @@ private void addTokensByBlocks( String mineName, int blocks ) { */ public void addTokens( long newTokens, String mineName ) { - addTokensAdmin( newTokens ); + addTokens( newTokens ); SimpleDateFormat dateFmt = new SimpleDateFormat("yyyy-MM-dd_hh:mm"); String key = dateFmt.format( new Date() ); @@ -591,6 +592,13 @@ public void addTokens( long newTokens, String mineName ) { */ public void addTokensAdmin( long newTokens ) { + this.tokens += newTokens; + this.tokensTotalAdminAdded += newTokens; + + dirty = true; + } + public void addTokens( long newTokens ) { + this.tokens += newTokens; this.tokensTotal += newTokens; @@ -613,27 +621,35 @@ public void addTokensAdmin( long newTokens ) { public void removeTokensAdmin( long removeTokens ) { this.tokens -= removeTokens; - this.tokensTotalRemoved += removeTokens; + this.tokensTotalAdminRemoved += removeTokens; + + dirty = true; + } + public void removeTokens( long removeTokens ) { + + this.tokens -= removeTokens; dirty = true; } public void setTokensAdmin( long newBalance ) { - long delta = newBalance - this.tokens; - - if ( delta > 0 ) { + if ( this.tokens > newBalance ) { + + long delta = this.tokens - newBalance; - this.tokens += delta; - this.tokensTotal += delta; + removeTokensAdmin( delta ); } - else { + else if ( this.tokens < newBalance ) { - this.tokens -= delta; - this.tokensTotalRemoved -= delta; + long delta = newBalance - this.tokens; + + addTokensAdmin( delta ); } - - dirty = true; +// else { +// // do nothing if equals and no change is needed: +// } + } /** @@ -681,12 +697,14 @@ public String toString() { .append( " avg tokens/min: " ) .append( getAverageTokensPerMinute() ) - .append( " totalTokens: " ) - .append( getTokensTotal() ) - .append( " totalTokensRemoved: " ) - .append( getTokensTotalRemoved() ) .append( " tokens: " ) .append( getTokens() ) + .append( " totalTokens earned: " ) + .append( getTokensTotal() ) + .append( " totalTokensAdminAdded: " ) + .append( getTokensTotalAdminAdded() ) + .append( " totalTokensAdminRemoved: " ) + .append( getTokensTotalAdminRemoved() ) ; return sb.toString(); @@ -820,11 +838,18 @@ public void setTokensTotal( long tokensTotal ) { this.tokensTotal = tokensTotal; } - public long getTokensTotalRemoved() { - return tokensTotalRemoved; + public long getTokensTotalAdminAdded() { + return tokensTotalAdminAdded; + } + public void setTokensTotalAdminAdded( long tokensTotalAdminAdded ) { + this.tokensTotalAdminAdded = tokensTotalAdminAdded; + } + + public long getTokensTotalAdminRemoved() { + return tokensTotalAdminRemoved; } - public void setTokensTotalRemoved( long tokensTotalRemoved ) { - this.tokensTotalRemoved = tokensTotalRemoved; + public void setTokensTotalAdminRemoved( long tokensTotalAdminRemoved ) { + this.tokensTotalAdminRemoved = tokensTotalAdminRemoved; } public long getTokensLastBlocksTotals() { diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java index 90cfaa0dc..d3010d984 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommands.java @@ -1611,15 +1611,18 @@ public void rankPlayer(CommandSender sender, cPlayer.getTokensByMine().size() > 0 ) { msgs.add( String.format( - " Tokens By Mine: &2Tokens: &3%s &2Avg Tokens per min: &3%s", + " Tokens By Mine: &2Tokens: &3%s &2Avg/min: &3%s &2Blocks/Token: &3%d", iFmt.format( cPlayer.getTokens() ), - dFmt.format( cPlayer.getAverageTokensPerMinute() )) ); + dFmt.format( cPlayer.getAverageTokensPerMinute() ), + AutoFeaturesWrapper.getInstance().getInteger( AutoFeatures.tokensBlocksPerToken ) + )); msgs.add( String.format( - " &2Total: &3%s &2Total Removed: &3%s &2Tokens per Block: &3%d", + " &2TotalEarned: &3%s &2AdminAdded: &3%s &2AdminRemvd: &3%s", iFmt.format( cPlayer.getTokensTotal() ), - iFmt.format( cPlayer.getTokensTotalRemoved() ), - AutoFeaturesWrapper.getInstance().getInteger( AutoFeatures.tokensBlocksPerToken )) ); + iFmt.format( cPlayer.getTokensTotalAdminAdded() ), + iFmt.format( cPlayer.getTokensTotalAdminRemoved() ) + )); msgs.addAll( Text.formatTreeMapStats(cPlayer.getTokensByMine(), 5 ) ); From 9a8afa8372cea9703234a8d5b28f4e5d7201efb6 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Mon, 6 Dec 2021 17:48:08 -0500 Subject: [PATCH 197/283] Bug fix: Fixed a class not found except caused by google guava trying to load functions that it should not have been using for their event manager. Moved the PEE event out of this class all together, so now it's safe to use in other areas of prison, such as with guava's event handler. (forgot to include this class change in the earlier commit) --- .../events/PrisonDebugBlockInspector.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/PrisonDebugBlockInspector.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/PrisonDebugBlockInspector.java index 9c2d4ae80..a7f4f0e99 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/PrisonDebugBlockInspector.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/PrisonDebugBlockInspector.java @@ -17,8 +17,15 @@ import tech.mcprison.prison.util.Location; public class PrisonDebugBlockInspector - extends OnBlockBreakMines +// extends OnBlockBreakMines { + OnBlockBreakMines obbMines; + + public PrisonDebugBlockInspector() { + super(); + + obbMines = new OnBlockBreakMines(); + } public void init() { Prison.get().getEventBus().register(this); @@ -40,7 +47,7 @@ public void onPlayerInteract( PrisonPlayerInteractEvent e ) { SpigotBlock sBlock = (SpigotBlock) location.getBlockAt(); UUID playerUUID = e.getPlayer().getUUID(); - Mine mine = findMine( playerUUID, sBlock, null, null ); + Mine mine = obbMines.findMine( playerUUID, sBlock, null, null ); if ( mine == null ) { From 6161c03109290a076e495753a45eceb2e07fc245 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Tue, 7 Dec 2021 00:48:15 -0500 Subject: [PATCH 198/283] Mine Bombs: Some changes in how they are setup. Added a bombItemId which becomes line one of the lore and is used to identify that it's a mine bomb. Added a nameTag that is used to put a nameTag on the armor stand. Added a itemRemovalDelayTicks field to better control when the armor stand is removed (exact time). Update a lot of Mine Bomb code for creating the time, placing the item (armor stand) etc... It's working better overall. --- docs/changelog_v3.3.x.md | 7 +- .../mcprison/prison/bombs/MineBombData.java | 77 +++- .../tech/mcprison/prison/bombs/MineBombs.java | 39 +- .../java/tech/mcprison/prison/util/Text.java | 11 + .../spigot/utils/PrisonBombListener.java | 7 +- .../spigot/utils/PrisonUtilsMineBombs.java | 380 ++++++++++-------- .../utils/PrisonUtilsMineBombsTasks.java | 86 ++-- 7 files changed, 376 insertions(+), 231 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index aa1c9df9d..889b0b86d 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,12 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.10 2021-12-06 +# 3.2.11-alpha.10 2021-12-07 + + +* **Mine Bombs: Some changes in how they are setup. Added a bombItemId which becomes line one of the lore and is used to identify that it's a mine bomb.** +Added a nameTag that is used to put a nameTag on the armor stand. Added a itemRemovalDelayTicks field to better control when the armor stand is removed (exact time). +Update a lot of Mine Bomb code for creating the time, placing the item (armor stand) etc... It's working better overall. * **Update Tokens to fix an issue with the admin set.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java index db69ba23e..ba9a8aad6 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombData.java @@ -13,9 +13,23 @@ public class MineBombData { private String description; + + /** + *

The 'bombItemId' is first line of the bomb's item lore, and + * it really needs to be unique and not match any other bomb's id. + *

+ */ + private String bombItemId; private List lore; + /** + *

The String value that is shown over the placed item when the bomb is + * placed. Null or empty will show none. The placeholder '{name}' will show + * the bomb's name. + *

+ */ + private String nameTag; /** *

The String name of an XMaterial item to use as the "bomb". @@ -85,7 +99,21 @@ public class MineBombData { private int fuseDelayTicks = 5 * 20; // 5 seconds - private int cooldownTicks = 30 * 20; // 30 seconds + private int cooldownTicks = 5 * 20; // 5 seconds + + + /** + *

This is the number of ticks after the explosion occurs to when + * the armor stand is removed. This is preferred since bukkit is + * managing the removal of the armor stand, which will help prevent it + * from not being removed, which will create a zombie. + *

+ * + *

This value will be added to fuseDelayTicks to setup the removal + * time that will be used when placing the armor stand. + *

+ */ + private int itemRemovalDelayTicks = 5; // 0.25 seconds /** @@ -113,7 +141,14 @@ public class MineBombData { */ private boolean autosell = false; - private boolean activated = false; + + /** + *

Internal just to indicated if a mine bomb is activated or not. + * This has not purpose if used in a save file. + *

+ */ + private transient boolean activated = false; + private TreeSet soundEffects; @@ -139,9 +174,13 @@ public MineBombData( String name, String itemType, String explosionShape, this.name = name; this.itemType = itemType; + this.nameTag = "{name}"; + this.explosionShape = explosionShape; this.radius = radius; + this.bombItemId = "PrisonMineBomb: " + name; + this.lore = new ArrayList<>(); if ( lores != null ) { @@ -159,6 +198,7 @@ public MineBombData( String name, String itemType, String explosionShape, this.cooldownTicks = 30 * 20; + this.itemRemovalDelayTicks = 5; this.glowing = false; this.gravity = true; @@ -170,8 +210,12 @@ public MineBombData clone() { MineBombData cloned = new MineBombData( getName(), getItemType(), getExplosionShape(), getRadius() ); + cloned.setBombItemId( getBombItemId() ); + cloned.setDescription( getDescription() ); + cloned.setNameTag( getNameTag() ); + cloned.setToolInHandName( getToolInHandName() ); cloned.setToolInHandFortuneLevel( getToolInHandFortuneLevel() ); @@ -185,6 +229,7 @@ public MineBombData clone() { cloned.setGlowing( isGlowing() ); cloned.setGravity( isGravity() ); + cloned.setItemRemovalDelayTicks( getItemRemovalDelayTicks() ); cloned.setAutosell( isAutosell() ); cloned.setActivated( isActivated() ); @@ -217,6 +262,13 @@ public void setName( String name ) { this.name = name; } + public String getNameTag() { + return nameTag; + } + public void setNameTag( String nameTag ) { + this.nameTag = nameTag; + } + public String getDescription() { return description; } @@ -224,6 +276,13 @@ public void setDescription( String description ) { this.description = description; } + public String getBombItemId() { + return bombItemId; + } + public void setBombItemId( String bombItemId ) { + this.bombItemId = bombItemId; + } + public List getLore() { return lore; } @@ -315,17 +374,19 @@ public void setGlowing( boolean glowing ) { this.glowing = glowing; } - public boolean isGravity() - { + public boolean isGravity() { return gravity; } - - - public void setGravity( boolean gravity ) - { + public void setGravity( boolean gravity ) { this.gravity = gravity; } + public int getItemRemovalDelayTicks() { + return itemRemovalDelayTicks; + } + public void setItemRemovalDelayTicks( int itemRemovalDelayTicks ) { + this.itemRemovalDelayTicks = itemRemovalDelayTicks; + } public boolean isAutosell() { return autosell; diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java index 579b4079b..ccc1681f8 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java @@ -8,6 +8,7 @@ import tech.mcprison.prison.file.JsonFileIO; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.util.Location; +import tech.mcprison.prison.util.Text; public class MineBombs { @@ -304,6 +305,8 @@ public void setupDefaultMineBombData() mbd.getVisualEffects().add( mbeExplode10.clone() ); mbd.getVisualEffects().add( mbeExplode06.clone() ); + mbd.setCooldownTicks( 60 ); + getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); } @@ -414,11 +417,22 @@ public void setupDefaultMineBombData() MineBombData mbd = new MineBombData( "WimpyBomb", "GUNPOWDER", ExplosionShape.sphere.name(), 5, "A Wimpy Mine Bomb" ); + mbd.setBombItemId( "&7A &2Wimpy &cBomb &9...&02A3F" ); + + mbd.setNameTag( "&7A &2Wimpy &cBomb\n&\n&eR U N !!!" ); + mbd.setRadiusInner( 2 ); mbd.setDescription("A whimpy bomb made with gunpowder and packs the punch of a " + "dull wooden pickaxe. For some reason, it only has a 40% chance of removing " + "a block."); + mbd.getLore().add( "" ); + mbd.getLore().add( "A whimpy bomb made with gunpowder and packs the punch " ); + mbd.getLore().add( "of a dull wooden pickaxe. For some reason, it only " ); + mbd.getLore().add( "has a 40% chance of removing a block." ); + mbd.getLore().add( "" ); + mbd.getLore().add( "Not labeled for retail sale." ); + mbd.setToolInHandName( "WOODEN_PICKAXE" ); mbd.setToolInHandFortuneLevel( 0 ); mbd.setRemovalChance( 40.0d ); @@ -443,7 +457,7 @@ public void setupDefaultMineBombData() mbd.setGlowing( true ); mbd.setGravity( false ); - mbd.setCooldownTicks( 60 ); + mbd.setCooldownTicks( 5 ); getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); } @@ -490,4 +504,27 @@ public MineBombsConfigData getConfigData() { return configData; } + public MineBombData findBombByItemId( String bombItemId ) + { + MineBombData results = null; + + String bombItemIdConvered = Text.convertToAmpColorCodes( bombItemId ); + + if ( bombItemIdConvered != null && !bombItemIdConvered.isEmpty() ) { + for ( String bombKey : getConfigData().getBombs().keySet() ) + { + MineBombData bomb = getConfigData().getBombs().get( bombKey ); + + if ( bomb != null && bomb.getBombItemId() != null && + bomb.getBombItemId().equalsIgnoreCase( bombItemIdConvered ) ) { + + results = bomb; + + } + } + } + + return results; + } + } diff --git a/prison-core/src/main/java/tech/mcprison/prison/util/Text.java b/prison-core/src/main/java/tech/mcprison/prison/util/Text.java index a96f4a0ab..b1df3cc29 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/util/Text.java +++ b/prison-core/src/main/java/tech/mcprison/prison/util/Text.java @@ -414,6 +414,17 @@ public static String translateHexColorCodesCore(String message, char targetColor return results; } + + public static String convertToAmpColorCodes( String textEncoded ) { + + String results = textEncoded; + + if ( textEncoded != null && textEncoded.contains( COLOR_ ) ) { + results = textEncoded.replaceAll( COLOR_, "&" ); + } + + return results; + } /** * Converts a double (3.45) into a US-localized currency string ($3.45). diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java index 547670a64..44d0bee01 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java @@ -54,13 +54,18 @@ public void onInteract( PlayerInteractEvent event ) { Player player = event.getPlayer(); + if ( !getPrisonUtilsMineBombs().isItemABomb( player ) ) { + + return; + } + SpigotBlock sBlock = null; // If clicking AIR, then event.getClickedBlock() will be null... // so if null, then use the player's location for placing the bomb. if ( event.getClickedBlock() == null ) { - SpigotPlayer sPlayer = new SpigotPlayer( event.getPlayer() ); + SpigotPlayer sPlayer = new SpigotPlayer( player ); Location loc = sPlayer.getLocation(); // Get the block 3 away from the player, in the direction (vector) in which diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java index 591b0c79b..d96544172 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java @@ -10,6 +10,7 @@ import org.bukkit.Effect; import org.bukkit.Particle; import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; import com.cryptomorin.xseries.XSound; @@ -590,50 +591,90 @@ public static SpigotItemStack getItemStackBomb( MineBombData bomb ) { bombs.setDisplayName( bomb.getName() ); //bombs.setAmount( count ); +// if ( bomb.isGlowing() ) { +// bombs.addEnchantment( ); +// } - List lore = bombs.getLore(); - - lore.add( MINE_BOMBS_LORE_1 ); - lore.add( MINE_BOMBS_LORE_2_PREFIX + bomb.getName() ); - lore.add( " " ); - - lore.add( "Size, Diameter: " + ( 1 + 2 * bomb.getRadius()) ); - lore.add( "Shape: " + bomb.getExplosionShape() ); + List lore = new ArrayList<>( bombs.getLore() ); - String bombDesc = bomb.getDescription(); - String[] desc = ( bombDesc == null ? "" : bombDesc ).split( " " ); - StringBuilder sb = new StringBuilder(); + lore.add( 0, bomb.getBombItemId() ); - for ( String d : desc ) { - - sb.append( d ).append( " " ); - - if ( sb.length() > 30 ) { - sb.insert( 0, " " ); - - lore.add( sb.toString() ); - sb.setLength( 0 ); - } - } - if ( sb.length() > 0 ) { - sb.insert( 0, " " ); - - lore.add( sb.toString() ); - } -// lore.add( " " + bomb.getDescription() ); +// lore.add( MINE_BOMBS_LORE_1 ); +// lore.add( MINE_BOMBS_LORE_2_PREFIX + bomb.getName() ); +// lore.add( " " ); +// +// lore.add( "Size, Diameter: " + ( 1 + 2 * bomb.getRadius()) ); +// lore.add( "Shape: " + bomb.getExplosionShape() ); - lore.add( " " ); +// String bombDesc = bomb.getDescription(); +// String[] desc = ( bombDesc == null ? "" : bombDesc ).split( " " ); +// StringBuilder sb = new StringBuilder(); +// +// for ( String d : desc ) { +// +// sb.append( d ).append( " " ); +// +// if ( sb.length() > 30 ) { +// sb.insert( 0, " " ); +// +// lore.add( sb.toString() ); +// sb.setLength( 0 ); +// } +// } +// if ( sb.length() > 0 ) { +// sb.insert( 0, " " ); +// +// lore.add( sb.toString() ); +// } +//// lore.add( " " + bomb.getDescription() ); +// +// lore.add( " " ); bombs.setLore( lore ); } } + else { + String message = String.format( + "Invalid MineBomb Item: Bomb: %s Cannot map '%s' to an XMaterial. " + + "See this URL for valid XMaterial types: " + + "https://github.com/CryptoMorin/XSeries/blob/master/src/main/java" + + "/com/cryptomorin/xseries/XMaterial.java", bomb.getName(), bomb.getItemType() ); + + Output.get().logError( message ); + } return bombs; } + public boolean isItemABomb( Player player ) { + + MineBombData bomb = getBombItem( player ); + + return ( bomb != null ); + } + + public MineBombData getBombItem( Player player ) { + MineBombData bomb = null; + + SpigotItemStack itemInHand = SpigotCompatibility.getInstance().getPrisonItemInMainHand( player ); + + if ( itemInHand != null ) { + List lore = itemInHand.getLore(); + + if ( lore.size() > 0 ) { + + String bombItemId = lore.get( 0 ); + + bomb = MineBombs.getInstance().findBombByItemId( bombItemId ); + } + } + + return bomb; + } + /** *

This takes a player and checks their main hand to see if it contains a bomb. * If it does, then it return the selected bomb, and it reduces the quantity by @@ -650,46 +691,33 @@ public static SpigotItemStack getItemStackBomb( MineBombData bomb ) { public boolean setBombInHand( Player player, SpigotBlock sBlock ) { boolean isABomb = false; - - SpigotItemStack itemInHand = SpigotCompatibility.getInstance().getPrisonItemInMainHand( player ); - - if ( itemInHand != null ) { - List lore = itemInHand.getLore(); - - String prisonBombId = lore.size() > 0 ? Text.stripColor( lore.get( 0 ) ) : ""; - String bombName = lore.size() > 1 ? Text.stripColor( lore.get( 1 ) ).trim() : ""; - - if ( prisonBombId.equalsIgnoreCase( Text.stripColor( MINE_BOMBS_LORE_1 )) ) { - - - // String bombName = lore1.trim(); - - MineBombs mBombs = MineBombs.getInstance(); - - MineBombData bomb = mBombs.findBomb( bombName ); - - String prisonExplosiveHandlerPriority = AutoFeaturesWrapper.getInstance().getMessage( - AutoFeatures.ProcessPrisons_ExplosiveBlockBreakEventsPriority ); - - if ( bomb != null && "DISABLED".equalsIgnoreCase( prisonExplosiveHandlerPriority ) ) { - - Output.get().logWarn( "A Prison Mine Bomb was attempted to be used, but the " + - "handling of its explosion is DISABLED. Edit the 'autoFeaturesConfig.yml' " + - "file and set 'ProcessPrisons_ExplosiveBlockBreakEventsPriority: NORMAL'." ); - - // Must return a true from here on out so the original event is canceled. - // Returning a true does not mean the bomb was activated. - isABomb = true; - - return isABomb; - } - - else if ( bomb != null ) { - - // Must return a true from here on out so the original event is canceled. - // Returning a true does not mean the bomb was activated. - isABomb = true; - + MineBombData bomb = getBombItem( player ); + + if ( bomb != null ) { + + + String prisonExplosiveHandlerPriority = AutoFeaturesWrapper.getInstance().getMessage( + AutoFeatures.ProcessPrisons_ExplosiveBlockBreakEventsPriority ); + + if ( bomb != null && "DISABLED".equalsIgnoreCase( prisonExplosiveHandlerPriority ) ) { + + Output.get().logWarn( "A Prison Mine Bomb was attempted to be used, but the " + + "handling of its explosion is DISABLED. Edit the 'autoFeaturesConfig.yml' " + + "file and set 'ProcessPrisons_ExplosiveBlockBreakEventsPriority: NORMAL'." ); + + // Must return a true from here on out so the original event is canceled. + // Returning a true does not mean the bomb was activated. + isABomb = true; + + return isABomb; + } + + else if ( bomb != null ) { + + // Must return a true from here on out so the original event is canceled. + // Returning a true does not mean the bomb was activated. + isABomb = true; + // XMaterial.GUNPOWDER; // XMaterial.BLAZE_POWDER; // XMaterial.WOODEN_PICKAXE; @@ -698,33 +726,33 @@ else if ( bomb != null ) { // XMaterial.GOLDEN_PICKAXE; // XMaterial.DIAMOND_PICKAXE; // XMaterial.NETHERITE_PICKAXE; - + // XMaterial.SLIME_BLOCK + + // if the toolInHand has not been set, use a diamond pickaxe: + if ( bomb.getToolInHandName() == null ) { + XMaterial xMat = XMaterial.DIAMOND_PICKAXE; + bomb.setToolInHandName( xMat.name() ); + } + + SpigotPlayer sPlayer = new SpigotPlayer( player ); + + String playerUUID = player.getUniqueId().toString(); + int cooldownTicks = checkPlayerCooldown( playerUUID ); + + if ( cooldownTicks == 0 ) { - // if the toolInHand has not been set, use a diamond pickaxe: - if ( bomb.getToolInHandName() == null ) { - XMaterial xMat = XMaterial.DIAMOND_PICKAXE; - bomb.setToolInHandName( xMat.name() ); - } - SpigotPlayer sPlayer = new SpigotPlayer( player ); - - String playerUUID = player.getUniqueId().toString(); - int cooldownTicks = checkPlayerCooldown( playerUUID ); - - if ( cooldownTicks == 0 ) { - - - // Set cooldown: - addPlayerCooldown( playerUUID, bomb.getCooldownTicks() ); - - SpigotItemStack bombs = PrisonUtilsMineBombs.getItemStackBomb( bomb ); - - if ( bombs != null ) { - - SpigotBlock bombBlock = sBlock != null ? sBlock : (SpigotBlock) player.getLocation().getBlock(); - - + // Set cooldown: + addPlayerCooldown( playerUUID, bomb.getCooldownTicks() ); + + SpigotItemStack bombs = PrisonUtilsMineBombs.getItemStackBomb( bomb ); + + if ( bombs != null ) { + + SpigotBlock bombBlock = sBlock != null ? sBlock : (SpigotBlock) player.getLocation().getBlock(); + + // // If the clicked on block is empty, then the player probably clicked on air. // // Check the next lower block (y - 1) until a valid block is found, or until y < 1 // while ( sBlock.isEmpty() && sBlock.getLocation().getBlockY() > 0 ) { @@ -743,71 +771,74 @@ else if ( bomb != null ) { //// } //// } // } - - - - // For mine bombs, take the block below where the bomb's item was dropped. The floating - // item is not the block that needs to be the target block for the explosion. Also, the block - // if it is on top of the mine, would be identified as being outside of the mine. - int count = 0; - boolean isAir = bombBlock.isEmpty(); - while ( (count++ <= ( isAir ? 1 : 0 ) || bombBlock.isEmpty()) && bombBlock.getLocation().getBlockY() > 1 ) { - - Block tempBlock = bombBlock.getLocation().getBlockAtDelta( 0, -1, 0 ); - if ( tempBlock != null && tempBlock instanceof SpigotBlock ) { - bombBlock = (SpigotBlock) tempBlock; - } - + + + + // For mine bombs, take the block below where the bomb's item was dropped. The floating + // item is not the block that needs to be the target block for the explosion. Also, the block + // if it is on top of the mine, would be identified as being outside of the mine. + int count = 0; + boolean isAir = bombBlock.isEmpty(); + while ( (count++ <= ( isAir ? 1 : 0 ) || bombBlock.isEmpty()) && bombBlock.getLocation().getBlockY() > 1 ) { + + Block tempBlock = bombBlock.getLocation().getBlockAtDelta( 0, -1, 0 ); + if ( tempBlock != null && tempBlock instanceof SpigotBlock ) { + bombBlock = (SpigotBlock) tempBlock; + } + // Output.get().logInfo( // "#### PrisonUtilsMineBombs: bomb y loc: " + bombBlock.getWrapper().getLocation().getBlockY() + // " " + bombBlock.getLocation().getBlockY() + " count= " + count ); - } - - bomb.setPlacedBombBlock( bombBlock ); - + } + + bomb.setPlacedBombBlock( bombBlock ); + // Output.get().logInfo( // "#### PrisonUtilsMineBombs: bomb loc: " + bombBlock.getLocation().toWorldCoordinates() ); - - //int throwSpeed = 2; - - - - // check if in a mine: - OnBlockBreakMines obbm = new OnBlockBreakMines(); - Mine mine = obbm.findMine( player, bombBlock, null, null ); - - if ( mine == null ) { - // Cannot set the bomb outside of a mine, so cancel: - return isABomb; - } - - // Setting activated to true indicates the bomb is live and it has - // been removed from the player's inventory: - bomb.setActivated( true ); - - // Remove from inventory: - itemInHand.setAmount( itemInHand.getAmount() - 1 ); - - // Not sure if the following is needed? - SpigotCompatibility.getInstance().setItemInMainHand( player, itemInHand.getBukkitStack() ); + + //int throwSpeed = 2; + + + + // check if in a mine: + OnBlockBreakMines obbm = new OnBlockBreakMines(); + Mine mine = obbm.findMine( player, bombBlock, null, null ); + + if ( mine == null ) { + // Cannot set the bomb outside of a mine, so cancel: + return isABomb; + } + + // Setting activated to true indicates the bomb is live and it has + // been removed from the player's inventory: + bomb.setActivated( true ); + + + SpigotItemStack itemInHand = SpigotCompatibility.getInstance().getPrisonItemInMainHand( player ); - - PlacedMineBombItemTask submitPlacedMineBombItem = - submitPlacedMineBombItemTask( bomb, bombBlock, bombs ); + // Remove from inventory: + itemInHand.setAmount( itemInHand.getAmount() - 1 ); + + // Not sure if the following is needed? + SpigotCompatibility.getInstance().setItemInMainHand( player, itemInHand.getBukkitStack() ); + + + PlacedMineBombItemTask submitPlacedMineBombItem = + submitPlacedMineBombItemTask( bomb, bombBlock, bombs ); // placeMineBombItem( bomb, bombBlock, bombs ); - - // This places the item so it will float: + + // This places the item so it will float: // final Item dropped = player.getWorld().dropItem( // bombBlock.getWrapper().getLocation(), bombs.getBukkitStack() ); - + // dropped.setPickupDelay( Integer.MAX_VALUE ); // dropped.setCustomName( bomb.getName() ); - //dropped.setVelocity(player.getLocation().getDirection().multiply( throwSpeed ).normalize() ); - + //dropped.setVelocity(player.getLocation().getDirection().multiply( throwSpeed ).normalize() ); + // int delayInTicks = 5 * 20; // 5 secs - - - // If running MC 1.9.0 or higher, then can use the glowing feature. Ignore for 1.8.x. + + + // If running MC 1.9.0 or higher, then can use the glowing feature. Ignore for 1.8.x. // if ( new BluesSpigetSemVerComparator().compareMCVersionTo( "1.9.0" ) >= 0 ) { // // dropped.setGlowing( bomb.isGlowing() ); @@ -816,36 +847,35 @@ else if ( bomb != null ) { // // setGravity is invalid for spigot 1.8.8: // dropped.setGravity( bomb.isGravity() ); // } - - - - // Submit the bomb's task to go off: - - setoffBombDelayed( sPlayer, bomb, bombBlock ); - - - + + + + // Submit the bomb's task to go off: + + setoffBombDelayed( sPlayer, bomb, bombBlock ); + + + // dropped.setMetadata( "prisonMineBomb", new FixedMetadataValue( SpigotPrison.getInstance(), true ) ); - //dropped.setMetadata( "prisonMineName", new FixedMetadataValue( SpigotPrison.getInstance(), "mineName" ) ); - - } - } - - else { - - float cooldownSeconds = cooldownTicks / 20.0f; - DecimalFormat dFmt = new DecimalFormat( "0.0" ); - - String message = - String.format( "You cannot use another Prison Mine Bomb for %s seconds.", - dFmt.format( cooldownSeconds ) ); - sPlayer.sendMessage( message ); - - } - - } - } - } + //dropped.setMetadata( "prisonMineName", new FixedMetadataValue( SpigotPrison.getInstance(), "mineName" ) ); + + } + } + + else { + + float cooldownSeconds = cooldownTicks / 20.0f; + DecimalFormat dFmt = new DecimalFormat( "0.0" ); + + String message = + String.format( "You cannot use another Prison Mine Bomb for %s seconds.", + dFmt.format( cooldownSeconds ) ); + sPlayer.sendMessage( message ); + + } + + } + } return isABomb; } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombsTasks.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombsTasks.java index 976ce8191..40e89e344 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombsTasks.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombsTasks.java @@ -450,10 +450,10 @@ public class PlacedMineBombItemTask private double twoPI; - private ArmorStand as; + private ArmorStand armorStand; - long ageTicks = 0L; - long terminateOnTicks = 0L; +// long ageTicks = 0L; + long terminateOnZeroTicks = 0L; private BukkitTask bukkitTask; @@ -467,10 +467,10 @@ public PlacedMineBombItemTask( MineBombData bomb, this.twoPI = Math.PI * 2; - this.ageTicks = 0; - this.terminateOnTicks = setTaskLifeSpan(); +// this.ageTicks = 0; + this.terminateOnZeroTicks = getTaskLifeSpan(); - initialize(); + initializeArmorStand(); } @@ -493,31 +493,14 @@ public PlacedMineBombItemTask( MineBombData bomb, * * @return */ - private long setTaskLifeSpan() + private long getTaskLifeSpan() { - long ticks = bomb.getFuseDelayTicks(); - - long maxValue = 0; - for ( MineBombEffectsData effect : bomb.getSoundEffects() ) - { - if ( effect.getEffectState() == EffectState.finished && - effect.getOffsetTicks() > maxValue ) { - maxValue = effect.getOffsetTicks(); - } - } - for ( MineBombEffectsData effect : bomb.getVisualEffects() ) - { - if ( effect.getEffectState() == EffectState.finished && - effect.getOffsetTicks() > maxValue ) { - maxValue = effect.getOffsetTicks(); - } - } - - return ticks + maxValue + 15; + int removeInTicks = bomb.getFuseDelayTicks() + bomb.getItemRemovalDelayTicks(); + return removeInTicks; } - private void initialize() { + private void initializeArmorStand() { Location location = sBlock.getLocation(); location.setY( location.getY() + 2.5 ); @@ -527,44 +510,56 @@ private void initialize() { EulerAngle arm = new EulerAngle( eulerAngleX, eulerAngleY, eulerAngleZ ); - as = sWorld.getWrapper().spawn( + armorStand = sWorld.getWrapper().spawn( sWorld.getBukkitLocation( location ), ArmorStand.class); - as.setCustomName( bomb.getName() ); - as.setCustomNameVisible(true); - as.setVisible(false); - as.setRemoveWhenFarAway(false); - as.setItemInHand( sWorld.getBukkitItemStack( item ) ); - as.setRightArmPose(arm); - as.setRemoveWhenFarAway(false); +// int removeInTicks = (int) getTaskLifeSpan(); + + //armorStand.addAttachment( SpigotPrison.getInstance(), removeInTicks ); + + if ( bomb.getNameTag() != null && !bomb.getNameTag().isEmpty() ) { + + String tagName = bomb.getNameTag(); + if ( tagName.contains( "{name}" ) ) { + tagName.replace( "{name}", bomb.getName() ); + } + armorStand.setCustomName( tagName ); + armorStand.setCustomNameVisible(true); + } + else { + + armorStand.setCustomNameVisible(false); + } + armorStand.setVisible(false); + armorStand.setRemoveWhenFarAway(false); + armorStand.setItemInHand( sWorld.getBukkitItemStack( item ) ); + armorStand.setRightArmPose(arm); if ( new BluesSpigetSemVerComparator().compareMCVersionTo( "1.9.0" ) >= 0 ) { - as.setGlowing( bomb.isGlowing() ); + armorStand.setGlowing( bomb.isGlowing() ); // setGravity is invalid for spigot 1.8.8: - as.setGravity( bomb.isGravity() ); + armorStand.setGravity( bomb.isGravity() ); } } @Override public void run() { - // Track the time that this has lived: - ageTicks += 1; - double speed = 0.25; + double speed = 0.35; eulerAngleX += speed; eulerAngleY += speed / 3; - eulerAngleZ += speed / 9; + eulerAngleZ += speed / 5; EulerAngle arm = new EulerAngle( eulerAngleX, eulerAngleY, eulerAngleZ ); - as.setRightArmPose(arm); + armorStand.setRightArmPose(arm); if ( eulerAngleX > twoPI ) { @@ -577,10 +572,11 @@ public void run() eulerAngleZ -= twoPI; } - - if ( ageTicks >= terminateOnTicks ) { + + // Track the time that this has lived: + if ( --terminateOnZeroTicks == 0 || !armorStand.isValid() ) { - as.remove(); + armorStand.remove(); this.cancel(); } From b2b42c84ddef3e7784ffd9edabab467c33aeedb0 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Tue, 7 Dec 2021 02:21:12 -0500 Subject: [PATCH 199/283] Mine Bombs: A few other minor fixes and changes. --- docs/changelog_v3.3.x.md | 3 + .../tech/mcprison/prison/bombs/MineBombs.java | 2 +- .../spigot/utils/PrisonBombListener.java | 80 +++++++++---------- .../spigot/utils/PrisonUtilsMineBombs.java | 8 +- .../utils/PrisonUtilsMineBombsTasks.java | 4 +- 5 files changed, 48 insertions(+), 49 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 889b0b86d..d5f218dae 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.10 2021-12-07 +* **Mine Bombs: A few other minor fixes and changes.** + + * **Mine Bombs: Some changes in how they are setup. Added a bombItemId which becomes line one of the lore and is used to identify that it's a mine bomb.** Added a nameTag that is used to put a nameTag on the armor stand. Added a itemRemovalDelayTicks field to better control when the armor stand is removed (exact time). Update a lot of Mine Bomb code for creating the time, placing the item (armor stand) etc... It's working better overall. diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java index ccc1681f8..bf8d9af08 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java @@ -419,7 +419,7 @@ public void setupDefaultMineBombData() "A Wimpy Mine Bomb" ); mbd.setBombItemId( "&7A &2Wimpy &cBomb &9...&02A3F" ); - mbd.setNameTag( "&7A &2Wimpy &cBomb\n&\n&eR U N !!!" ); + mbd.setNameTag( "&7A &2Wimpy &cBomb" ); mbd.setRadiusInner( 2 ); mbd.setDescription("A whimpy bomb made with gunpowder and packs the punch of a " + diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java index 44d0bee01..bdd871a7b 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonBombListener.java @@ -5,13 +5,9 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; -import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.player.PlayerDropItemEvent; import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.block.SpigotBlock; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.util.Location; @@ -99,7 +95,7 @@ public void onInteract( PlayerInteractEvent event ) { // @EventHandler( priority = EventPriority.HIGHEST, ignoreCancelled = false ) public void onBlockPlace( PlayerDropItemEvent event ) { - Output.get().logInfo( "### PrisonBombListener: PlayerDropItemEvent " ); + //Output.get().logInfo( "### PrisonBombListener: PlayerDropItemEvent " ); if ( event.isCancelled() && event.getItemDrop().hasMetadata( "prisonMineBomb" ) ) { @@ -118,48 +114,46 @@ public void onBlockPlace( PlayerDropItemEvent event ) { // Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent - oof" ); // } -// @EventHandler( priority = EventPriority.HIGHEST, ignoreCancelled = false ) - public void onBlockPlace3( BlockPlaceEvent event ) { - - Output.get().logInfo( "### PrisonBombListener: BlockPlaceEvent HIGHEST isCanceled= " + event.isCancelled() ); - -// event.getBlockPlaced(); - - - event.setBuild( true ); - event.setCancelled( false ); - - ItemStack item = event.getItemInHand(); - - - if ( item.hasItemMeta() && item.getItemMeta().hasDisplayName() ) { - ItemMeta meta = item.getItemMeta(); - - Output.get().logInfo( "### PrisonBombListener: BlockPlaceEvent " + meta.getDisplayName() ); - -// meta.getCustomTagContainer().hasCustomTag( null, null ) - -// meta. +//// @EventHandler( priority = EventPriority.HIGHEST, ignoreCancelled = false ) +// public void onBlockPlace3( BlockPlaceEvent event ) { +// +// Output.get().logInfo( "### PrisonBombListener: BlockPlaceEvent HIGHEST isCanceled= " + event.isCancelled() ); +// +//// event.getBlockPlaced(); +// +// +// event.setBuild( true ); +// event.setCancelled( false ); +// +// ItemStack item = event.getItemInHand(); +// +// +// if ( item.hasItemMeta() && item.getItemMeta().hasDisplayName() ) { +// ItemMeta meta = item.getItemMeta(); // -// Multimap attributes = meta.getAttributeModifiers(); +// Output.get().logInfo( "### PrisonBombListener: BlockPlaceEvent " + meta.getDisplayName() ); // +//// meta.getCustomTagContainer().hasCustomTag( null, null ) // -// for ( String attri : attributes. ) { -// -// } - - } - - - } +//// meta. +//// +//// Multimap attributes = meta.getAttributeModifiers(); +//// +//// +//// for ( String attri : attributes. ) { +//// +//// } +// +// } +// } -// @EventHandler( priority = EventPriority.HIGHEST, ignoreCancelled = false ) - public void onBlockPlace3( PlayerInteractEvent event ) { - - Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent " ); - - - } +//// @EventHandler( priority = EventPriority.HIGHEST, ignoreCancelled = false ) +// public void onBlockPlace3( PlayerInteractEvent event ) { +// +// Output.get().logInfo( "### PrisonBombListener: PlayerInteractEvent " ); +// +// +// } public PrisonUtilsMineBombs getPrisonUtilsMineBombs() { return prisonUtilsMineBombs; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java index d96544172..6727a71ae 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java @@ -10,7 +10,6 @@ import org.bukkit.Effect; import org.bukkit.Particle; import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; import com.cryptomorin.xseries.XMaterial; import com.cryptomorin.xseries.XSound; @@ -819,8 +818,11 @@ else if ( bomb != null ) { // Remove from inventory: itemInHand.setAmount( itemInHand.getAmount() - 1 ); - // Not sure if the following is needed? - SpigotCompatibility.getInstance().setItemInMainHand( player, itemInHand.getBukkitStack() ); + if ( itemInHand.getAmount() == 0 ) { + SpigotCompatibility.getInstance() + .setItemInMainHand( player, null ); + + } PlacedMineBombItemTask submitPlacedMineBombItem = diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombsTasks.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombsTasks.java index 40e89e344..bb97fdbec 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombsTasks.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombsTasks.java @@ -518,11 +518,11 @@ private void initializeArmorStand() { //armorStand.addAttachment( SpigotPrison.getInstance(), removeInTicks ); - if ( bomb.getNameTag() != null && !bomb.getNameTag().isEmpty() ) { + if ( bomb.getNameTag() != null && !bomb.getNameTag().trim().isEmpty() ) { String tagName = bomb.getNameTag(); if ( tagName.contains( "{name}" ) ) { - tagName.replace( "{name}", bomb.getName() ); + tagName = tagName.replace( "{name}", bomb.getName() ); } armorStand.setCustomName( tagName ); armorStand.setCustomNameVisible(true); From c7754b9bd9a1c03739281f3b5a3c4847fc30320c Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Wed, 8 Dec 2021 00:24:13 -0500 Subject: [PATCH 200/283] Released v3.2..11-alpha.11 --- docs/changelog_v3.3.x.md | 6 +++++- gradle.properties | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index d5f218dae..978d19690 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,11 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.10 2021-12-07 +# 3.2.11-alpha.11 2021-12-07 + + + +* **3.2.11-alpha.11 2021-12-07** * **Mine Bombs: A few other minor fixes and changes.** diff --git a/gradle.properties b/gradle.properties index 7ab066e1e..799be79ec 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ ## # This is actually the "correct" place to define the version for the project. ## # Used within build.gradle with ${project.version}. ## # Can be overridden on the command line: gradle -Pversion=3.2.1-alpha.3 -version=3.2.11-alpha.10 +version=3.2.11-alpha.11 #version=3.2.8.2 #version=3.3.0-alpha.6 From 894796bff49ffee3cee6aed18c235f8eef4484e3 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Wed, 8 Dec 2021 00:31:50 -0500 Subject: [PATCH 201/283] Bug fix: Was causing a null pointer exception when trying to add a player to a new ladder. This now correctly gives the player the requested rank, or if not specified, then the lowest rank on that ladder. --- docs/changelog_v3.3.x.md | 3 +++ .../tech/mcprison/prison/ranks/RankUtil.java | 21 +++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 978d19690..65dc0ea87 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.11 2021-12-07 +* **Bug fix: Was causing a null pointer exception when trying to add a player to a new ladder.** +This now correctly gives the player the requested rank, or if not specified, then the lowest rank on that ladder. + * **3.2.11-alpha.11 2021-12-07** diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/RankUtil.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/RankUtil.java index b0a2fc19b..e2bdaf188 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/RankUtil.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/RankUtil.java @@ -106,6 +106,7 @@ public enum RankupTransactions { failed_player, failed_ladder, + player_has_no_rank_on_ladder, orginal_rank, failed_rank_not_found, @@ -338,11 +339,20 @@ private void rankupPlayerInternal(RankupResults results, // This should never be null, since if a player is not on this ladder, then they // should never make it this far in to this code: // Um... not true when performing a prestige for the first time.... lol + // Also not true when being added to a ladder, since they will not have an existing rank. RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + + + // originalRank can be null... PlayerRank originalRank = rankPlayerFactory.getRank( rankPlayer, ladder ); + if ( originalRank == null ) { + + results.addTransaction( RankupTransactions.player_has_no_rank_on_ladder ); + } + // if ( originalRank == null && ladder.getName().equals( "default" ) ) { // // // Only default ladder should be logged as an error if there is no rank: @@ -358,6 +368,8 @@ private void rankupPlayerInternal(RankupResults results, results.setPlayerRankOriginal( originalRank ); results.setOriginalRank( originalRank == null ? null : originalRank.getRank() ); + + /** * calculate the target rank. In this function the original rank is updated within the * results object, so from here on out, use the results object for original rank. @@ -409,13 +421,18 @@ private void rankupPlayerInternal(RankupResults results, // This calculates the target rank, and takes in to consideration the player's existing rank: - PlayerRank pRankNext = originalRank.getTargetPlayerRankForPlayer( rankPlayer, targetRank ); + PlayerRank pRankNext = + originalRank == null ? null : + originalRank.getTargetPlayerRankForPlayer( rankPlayer, targetRank ); // new PlayerRank( targetRank, originalRank.getRankMultiplier() ); // If player does not have a rank on this ladder, then grab the first rank on the ladder since they need // to be added to the ladder. if ( pRankNext == null ) { - pRankNext = originalRank.getTargetPlayerRankForPlayer( rankPlayer, ladder.getLowestRank().get() ); + + pRankNext = rankPlayerFactory.createPlayerRank( targetRank ); + +// pRankNext = originalRank.getTargetPlayerRankForPlayer( rankPlayer, ladder.getLowestRank().get() ); } From 0d0a33a04ceb79c4205f298088270457b73279fb Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 10 Dec 2021 10:24:36 -0500 Subject: [PATCH 202/283] Mine Bombs: Set them up to auto refresh the data structure that is being saved, if it is detected that there has been a change. Added a version number to the mine bomb save data structure so as to use that to detect when the structure changes. That number will be updated in code when it has been modified. So when running the mine bomb loader, it will detect that the saved data is in an older format, and so it will rename the old file to preserve it as a backup, then write the new data to the file system. This will allow new fields to be added,and then they will appear in the save file upon the next restart. This will make it easier for admins to update and use the new features. --- docs/changelog_v3.3.x.md | 6 ++- .../tech/mcprison/prison/bombs/MineBombs.java | 45 ++++++++++++++++--- .../prison/bombs/MineBombsConfigData.java | 21 +++++++++ .../tech/mcprison/prison/file/FileIO.java | 21 +++++++++ 4 files changed, 87 insertions(+), 6 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 65dc0ea87..140022998 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,11 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.11 2021-12-07 +# 3.2.11-alpha.11 2021-12-10 + + +* **Mine Bombs: Set them up to auto refresh the data structure that is being saved, if it is detected that there has been a change.** +Added a version number to the mine bomb save data structure so as to use that to detect when the structure changes. That number will be updated in code when it has been modified. So when running the mine bomb loader, it will detect that the saved data is in an older format, and so it will rename the old file to preserve it as a backup, then write the new data to the file system. This will allow new fields to be added,and then they will appear in the save file upon the next restart. This will make it easier for admins to update and use the new features. * **Bug fix: Was causing a null pointer exception when trying to add a player to a new ladder.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java index bf8d9af08..8cbf61ccb 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombs.java @@ -17,7 +17,7 @@ public class MineBombs private static MineBombs instance; - private final MineBombsConfigData configData; + private MineBombsConfigData configData; @@ -147,12 +147,42 @@ public void loadConfigJson() { MineBombsConfigData configs = (MineBombsConfigData) fio.readJsonFile( configFile, getConfigData() ); - - if ( configs != null && configs.getBombs().size() > 0 ) { - - getConfigData().getBombs().putAll( configs.getBombs() ); + + if ( configs != null ) { + setConfigData( configs ); + if ( configs.getDataFormatVersion() < + MineBombsConfigData.MINE_BOMB_DATA_FORMAT_VERSION ) { + + // Need to update the format version then save a new copy of the configs. + + // first backup the old file by renaming it: + + int oldVersion = configs.getDataFormatVersion(); + + String backupTag = "ver_" + oldVersion; + File backupFile = fio.getBackupFile( configFile, backupTag, "json" ); + + boolean renamed = configFile.renameTo( backupFile ); + + if ( renamed ) { + configs.setDataFormatVersion( MineBombsConfigData.MINE_BOMB_DATA_FORMAT_VERSION ); + + fio.saveJsonFile( configFile, configs ); + + Output.get().logInfo( String.format( + "MineBomb Data Format was updated and saved: Loaded v%d and updated to v%d. " + + "The old data is archived as: [%s]", + oldVersion, configs.getDataFormatVersion(), + backupFile.getName() +// backupFile.getAbsolutePath() + ) ); + } + + + } } + } } @@ -500,10 +530,15 @@ public void setupDefaultMineBombData() } + public MineBombsConfigData getConfigData() { return configData; } + public void setConfigData( MineBombsConfigData configData ) { + this.configData = configData; + } + public MineBombData findBombByItemId( String bombItemId ) { MineBombData results = null; diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombsConfigData.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombsConfigData.java index 07c4fea5b..573002a0f 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombsConfigData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombsConfigData.java @@ -8,14 +8,35 @@ public class MineBombsConfigData implements FileIOData { + /** + *

If the format of this class, or any other variables and their + * classes change that would effect the structure of the save file, + * then increment this variable by 1. This will force the saved + * files on the servers to be updated to the latest format of the + * data. + *

+ */ + public static final int MINE_BOMB_DATA_FORMAT_VERSION = 1; + + private int dataFormatVersion = 0; + private Map bombs; public MineBombsConfigData() { super(); + this.dataFormatVersion = 0; + this.bombs = new TreeMap<>(); } + public int getDataFormatVersion() { + return dataFormatVersion; + } + public void setDataFormatVersion( int dataFormatVersion ) { + this.dataFormatVersion = dataFormatVersion; + } + public Map getBombs() { return bombs; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/file/FileIO.java b/prison-core/src/main/java/tech/mcprison/prison/file/FileIO.java index 67e0c98a6..5c9f58bf0 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/file/FileIO.java +++ b/prison-core/src/main/java/tech/mcprison/prison/file/FileIO.java @@ -56,6 +56,27 @@ public File getTempFile( File file ) { return tempFile; } + /** + *

This generates a new File with the filename of the backup file. + * This function only generates the File object and does not modify + * or save anything on the file system. + *

+ * + * @param file The original file name + * @param backupTag A no-spaced tag name to identify the type of backup. + * This is inserted after the original file name. + * @param suffix File suffix to use for the backup, not including the dot. + * @return File objct of the target backup file. + */ + public File getBackupFile( File file, String backupTag, String suffix ) { + + String tempFileName = file.getName() + "." + backupTag + "_" + + getTimestampFormat() + "." + suffix; + File tempFile = new File(file.getParentFile(), tempFileName); + + return tempFile; + } + protected void saveFile( File file, String data ) { if ( file != null && data != null ) From e5bf425da580e737328ca99d3ecbae53eb3c66f7 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 10 Dec 2021 11:10:11 -0500 Subject: [PATCH 203/283] Mine Bombs: Noticed the player inventory was not be "updated" through bukkit. This could help prevent wrong item amounts. --- docs/changelog_v3.3.x.md | 4 ++++ .../mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 140022998..d32cd341b 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,10 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.11 2021-12-10 +* **Mine Bombs: Noticed the player inventory was not be "updated" through bukkit.** +This could help prevent wrong item amounts. + + * **Mine Bombs: Set them up to auto refresh the data structure that is being saved, if it is detected that there has been a change.** Added a version number to the mine bomb save data structure so as to use that to detect when the structure changes. That number will be updated in code when it has been modified. So when running the mine bomb loader, it will detect that the saved data is in an older format, and so it will rename the old file to preserve it as a backup, then write the new data to the file system. This will allow new fields to be added,and then they will appear in the save file upon the next restart. This will make it easier for admins to update and use the new features. diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java index 6727a71ae..0d9ec588e 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/utils/PrisonUtilsMineBombs.java @@ -821,9 +821,12 @@ else if ( bomb != null ) { if ( itemInHand.getAmount() == 0 ) { SpigotCompatibility.getInstance() .setItemInMainHand( player, null ); - } + // Apply updates to the player's inventory: + player.updateInventory(); + + PlacedMineBombItemTask submitPlacedMineBombItem = submitPlacedMineBombItemTask( bomb, bombBlock, bombs ); From 8f8a355fc6d326e37250a9d9d6984a8ba56d98a0 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sat, 11 Dec 2021 17:58:14 -0500 Subject: [PATCH 204/283] Update some of the documents. Focus more so on auto configure. --- ..._docs_100_setting_up_auto_configure_03.png | Bin 23666 -> 98385 bytes ..._docs_100_setting_up_auto_configure_04.png | Bin 16455 -> 49771 bytes ..._docs_100_setting_up_auto_configure_05.png | Bin 15217 -> 21277 bytes ..._docs_100_setting_up_auto_configure_06.png | Bin 36043 -> 45116 bytes ...ison_docs_100_setting_up_auto_configure.md | 361 ++---------------- ...son_docs_101_auto_configure_log_example.md | 176 +++++++++ 6 files changed, 215 insertions(+), 322 deletions(-) create mode 100644 docs/prison_docs_101_auto_configure_log_example.md diff --git a/docs/images/prison_docs_100_setting_up_auto_configure_03.png b/docs/images/prison_docs_100_setting_up_auto_configure_03.png index 058b90acc25c8640ff21986f9a6fc309d4fdad68..4d5bf7bd4898f39e79dde693b23d8b174da6c896 100644 GIT binary patch literal 98385 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

C3reVgVoy9? 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 !ShJrMoZ*tKHPE%cr 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 diff --git a/docs/images/prison_docs_100_setting_up_auto_configure_04.png b/docs/images/prison_docs_100_setting_up_auto_configure_04.png index 5d20f112d42b7cb6d68db1853f267010156c7e9d..7e00e68ae4e1569aaea2b2cfd1e826ec18e7cf6f 100644 GIT binary patch literal 49771 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%0Deiw&VycGp*G8j;m9gGGLYcpzGW|bhMlgM$ z&{!)S`45=cSd(YtKQ$(QeZ04l7OY+HJhlydRE(}a-u zV@unTM+h5(<_(cz{)1xAlQyCXtmdPuRs6pGDu4>u(VW&l+EJD5b)!WrzptW}^-PZ+ zV3L1onEca$s4xNa`2>Bb8%A`(ya5(OY2n(=pV7v3_bf~FV`u*%WYS(u6yBsFrwogO zu1Ycl-R)uBrsCFwj3{MG5BLwVG3G{7l9^8&ht zRKk+-D71F;8uiHntAb6SZ?IsQ;mz6_rrj@Hl0*1& z@{3A_f5Nw3%JL#sXviV_a^kRcUSGjJ6BgIBVpevuZ@X#F8|w)?_y357{ErWQR|N*) zvkk>^#SvuU!j_h`ZG4q2(wK+={v%}_ngvyoEu@p@V+HmWoyM+xoK=FJKNxAL{2go%Jp1h%9EFoagcvO8e$Mzq3~>-IONT%_?=k#}C=o-ilXTP1^7%Ysec^b9 zxMHpW2K}rv8j!~S<4COV|27DymD!z9D+d3s(gI%I|6ZEO?GS<^u{w!FZwyfAqGhCY zXZJO}qB8D!CV_XJNp~A7LgY_VF@Z2v8=?JN9vzmi{wDRD6KZ^VR#>VN?W{WF+4>{b zw50^HN4Tk|Zvs^3YYXfTKlL|ELDlRH3dhhgz->hyN&!YzFSwRtj_4kE@h!JZb1OGe z(tgI>Zi#bLo27wQ0amdIxdXf3NYdB4&@}JSBGMy2PS#rGe~OZV3!U@&C|kpQ*XQGe z4WwP2uu(h=FqX?jf5=gPuAl!25RSkE63!j%FG`<8BE;we$iY02goUr&+eJM_7K+Xy zjRCaGvmle<)83!`;Qp@TV9{1$DVC4#v!v&cPO$dvNY07C742{++2jZxi%3HtH&eua#`ji7! znfI1jH2z^g7P+3*C+6KV(zBfQiVD~7cM7DJq$_g&GGoF4`rDS1sR5PliGZuY)W6aE z>xlW;{JTeuNagu=b*6{^37zTJ_JqjBHC;FVMa?Sv-fwktX}lJ`Jnj!$>*bHqz-?nd zJ(@=ZJ4_i^FXs85K!V+l-HAu`wEEno{0&dZT#jymeNiImp65++W?0P-gCEK|8 zDPxknJ@@Idvq=>R>HzT}x0V-$^wBe#KqWCcM>H;i15oMG(Mt`}!bBiN^FH4my);a6 zhZ2bWRycpn!3sI=1&ZF6gUDe&mXI6?!)r5zJR5MsJZ{j6Wz)=0v2SFi_I&)I?Qhp2 zs-LEyBI8nEZ8@O%(QTK9G<#8aXq0xmpc!eod zt`w*{98@dB{kd(clxS@IqfO_tHKoTWu0LAqWiFEPIJD#5oM&})ZxJdGfZZhsWV(ag zVnd<0Eokx}Weg#~_Fi{UEFoI{2GskRR`$2Cm=_d4to57%Sn^2JX%zfpdC8yGIR2@D zw+dm6yA1GK>kOE_{QG=DP8A8dzL21-pZND&jVgL?{@-=)UWvO-4d$U*H%Dx&)8BQ} zUfs3l-t9!LMYgYDw$9Dm^kL8Cbar9W?~z_+pRFGtmL zAhmvNFre&)&N9$ev|u1d{STe(w4Kt+zBMY52)$+g?H?-_pB(n;S2Ou_SZ&*z z1eX(kLynSjUMV>Jt7bS4&b@`(W4lLY?d24l2`ib!c_y0-D!gJ!EYgv4e=zQew zRjrMWK*DlvRJHj0+=f~kBnYwM3GMdF`wEU4db}L1gM}OZ<~Ba|QS2sZFtBaPxmg1W5J`5h+h3boD8i)WTB^d}M8I&T`(NuW72z4LmHJ8f7bmsrH1}?Ru zRk{lKefdJ%8kL6^od>P$*#O+^%?_>0G5Ub(iR_(Xi9P6#l2Qu7|ArK8c{ysHtijAH z-w7k^*@M8^FRy%o$Q#rsLExm3&bWwo09c~7^Y~}RF&R0fpMLO+`6a0nlMmUsTgzc| zcl-Cy%N#GLZW0D-=NF4!UbKh4sAzeV0eZYINd~L6KvC$Wa(~?i|FN0TNG!)HPo$&g z6Y{>SJxbn667R7cr#v9n7sGsMK7VfcWiR7ayWjuU-dRUgov&>l*th}N(gK?hq(fRj zx?37Vx*J3!q#Nl50qIaex}_UIq$MRqy1RLQ+nG5tXU@!=Ip>*~bJp{`{^we*8Dz=6 zzxQ=t*XL3Kk8WTx_^a{za;6Qp3;nMgNUkOljCl9^^=?NSrV8C<>`aJJE)t=_Gs%R} zQkc~`b7GL5BHY=^yM6SV)>&Ul=O4z=@IaR$N@zuBVJM&T$mGAO>q$Qm4K#q`4Cz08MrxrXc!=MgdG=|uZmvx6F@`5!+w53O z3Z*(1l2AK!5vD8kDxNXJ6=U!4zRc6?bC$<0b1#mDlknyRH%hE31fIxqem*}7vl8jy zpf#8GZ-s~|=lugMYuQxsp9Q}kW}%FqTCxAyS=^A}Pd|%CRX^)wLp7=n_>H*tH8c>2 zEOg9Q(kw%@dMqn)JI6=Vc>?@>*tbyMKz7bMf+jTR;Kqq>7J>k!7g9rGv!J(Den&`e zJ_n*_QAKi8o_vZv%e`-L4Hx?m+8ot%t$xx=y&Z7<6{yL$*gW@y?|B1ZwIi*X{WS9f zRK&FPN2o{<62sWMGbJTRCK3j`S`_!A`CUnHvYy(+e>=E`s6aN8`TOj;`o)8YMUW$+ zNhiX$V@lw8M?60QNzHnb2TJGlWxv~z+O~WB!=C2NB!$b* zrPa5n$m8IIV8AP?23&^Y8^;0iPlwE$N zU-XjgX_2OtsrBRd50+8%zJuMUb)(P2S{JI8YxQWREO+}VqevC5^HY)b6ad5#K=Xhy zzt0_Co50UG6G%0l!f*IH84aE1?_{(IJFvk878je_Q~KVL*YL}WVTz@gB+s;_i z`Cz#~(`Ii`@eG`&r=$JJb=~?~z~J-OEjd@@XODj~O0I1MShj9mXd7zI&^K7p2>wb4WCF_h&qE-SbUf>R{2@u@^PJm^UEU(llKwVA)9Ql_Hzlr;p>J>QeK>R6=qa9OdPxkA6{{#<;yd6Yy# z7dJ+RZ;5?>7BSb4l3hAJbcwoIiCAw6m4~Zy5|OPTqL#A4l%d%_(bQo4JG5h@dYBXx z!}zWsbVtRK4;#Cj$1z>~hWoR(>K_Jqmws13kO|Ku`|_Qo4Uq6YaX#TW>9JvESJ3&x zrdQT^>Gw&&-?Q?Z(1KjgliY)xy=Z*XP9xI1bn6zP3eox0l#C-2L8X^PM}6yiMiQeo zk>gcg{0#8W&S3btnmZL*0n2f*kb6RVsuwZQgqWH5%^w%+8i@j5;VAHdOLILO&KYa0 zaB$mo`*)5HjZCE;^$B6@23fYxNS%qPhcuz?A6#G&t$ILS-l@sBJXjKYfWdQ*a5G|R z_||cw2l-TFnXL4rat1SKP-ShY5;-?@XHPb;k%Z)5+EtTybOoe(xqis~Pnd@N8sjE^L0|i2aEX0I)5}RhVA}E@^iVe)dA8VmzNp)# zOZkQ93EY1+dg9$gKXXMjawi!0ST$=ID{@*~vhl1>?nz%yRM9bFH)#&V{SDG0RzNnu zR*~_}C>qfzj{}}bebyZ4qsM}-8p=PplDu;{h>Dk z>KKVm@lB(bdp1>Lhi)85*8e6{>wmyK*%(Y6ZCM)XHf|woI?pQid~~_JH+8*{=5g>= z;MpFVwF6(8tl$UJbY}+ExTlN}4n8g^mSgoWfEyDoLz;JmGI#Wm!T{@C7bP!NJ)IDM zBy9UK`x`?zb}@kl+SubI;0^%nl{t!C)L%?zcJM)ICD;fCHkTQ`T6MXv3<9NE<>V19 zg4-TfJ0F$6RrY}I1774G zz*^!nJ<$GpkxWv7v-O@_SiOp?i*ln#=vz~MAK5Te6WVBi+{RI|_sTHv@1}kxpL@>X zWLk+H6fl;VZ2FY8crcRyMgbyJ19XW#qxX5#eswyuR(2LI~>L0!N`}0nJ!;g@Z z|H%%NxgHG*!ms?3ApBXK3+$)vqk_JY-l?l%q}MIR`c=Kv(Lb5IMfUs2TZui*u+LDk zs)PqMq^Y?fwfDXW_W$cV2fumZQDCc}|2rQ3=&bAFT{t7D=Vn|^{Gd@mTP*t@c=$|c zKSw*-8*Xfx6I&&QD_tR|zVy)6UC`~UL^-on{ns_Ue;}m%PED^0)sCB`@gUkv*4B&G zw<;$SNARB7oQXD3>_6e9*!pC}(%RA7paCsa)*uc*O{FweKneVUQsF_-^WP)unT_}J z=x_h{g$zT-vzb0F+e+|plcl@_!>$yOKtgjSUB`6K=>o?5kR{iDS`Y6Ns zi| zX^KGf>p1#^$TCA$X=~cK49Xxw=9C(&XQ2Tl!*bIfpA2cl+#U+{)_=?d^5rqymaBb8 zMW|;=+395=xk>@i$w@7klzVZbmpkOC@Mb9oPo!}4B;z_I)=T1bV`&T0xV^Kk#^q$! ze)qn9*FNXj)*)>m0AjDy)Vbmw#n_t*;f8;n3O{Hf z<)f8Q&heG$-R?I6F=m2h`c~FQ{*!chkrEVto-vE+qTal>SU?Oi*$jiQBiS8`Vh-h| zJ%t=A2{!slZi4qmfAw5!dEQR(ow9RKLe2W--l?IW;BqWmbt8!I0+> ziHj?b_{JdwP*Ch+?;A56!L89GjD}>fmXtn<6WW?Yq=fmbtvXN&j{O_1yyxG4^+$Pn z%jay={~@JOIeMuj_E4CW6&Mw9=po-uH)o-Ga60i$p1mit<)&!mgcpi55G)ph zVIqZC6`(Mi9CEaG4;<|Gk&s?CGoHc}yyJp!Ee7U(Jz}gVQ-$D=(vRJ=Yq5j=&^$1} z^3wBnRH(zKL5@rhs9Qw6_X)I={=LrS|xJdV~E@{Ap_s9wlVJx z3UJ67?AE{JF52;?_`Y_+(c-*T<@0R_2Do7P{gow|;?F*eo*`B#AysX@)+PeBCY>3i zCn&_~GEenQ;_$0drMQjreFF14b0LxW0LANZUZwZMM8}|_rK(Wcq(!GAPJ}ZF9yn{( zO_V2-y%4;BtWLI^y5z954`>C3+=um?M^hJ)RH+-O0M*OMFJ9C%7^M61V&_+( zx9*st&+;1U(JdFml3F!_Gm+I6=|Rf7tE7e@WGrs8i@GtL`EV)4kY|>pjsm08b!>0A z%Upc3tBB*hv>zyLqqe~|p*#mCkd_74b)8@K?u4xW{DQrSY5GUOc>&<&lRSx=~ z9#<^2W%F^C7(SwpI!{iG&!;Wad>FA8GfO1;44VW|EOT9uo=)K*O?^8rYE{o0X%pkf zNvhIF5fhkkA^XEr=os0h-tjp0cGTC@nEof@gv+h>Tp3!&rP`}+2nm}fvhJh}R#%cQ zwN9YhpAE5uzBX)X0frQ@w=8r(Je7oZ<|J?CMS{>db0>t`k?1fKN&}LoPQ#Rn6Po=n z1VIjkDrAXa#TZ52kE6V1{3w@3$aT*E417B~AiV%rIHdP3ZKbS%l3u3#q-80`{`)Bz zo`aY}zNqQ0JLAW=Ppzb>a8heE#sb=azq_((6c+2WU}{3 zB{j{%SOXI}Is8S+gZe)^e{;6+AOHm?nmEj|Xv<%rB|$SGN6wdI60878mRO>fG*LD( z3^!@*?e6xB-J^oM($9D=fFloo!Yzvm@rslJY8SUaq<(aU;x%8}q*(Z46(Se%iFbJk zKyl0t{tI0j4ihiZ8^Z*~dO*L|GIS?HW)Tq|`wa4=58y}C5d)MjL0$PLnnZV=7Rg4Q z`FEMDx4OH(x@_8eowWR^{$L0%AIf5!t3dm7>;`jMgOs!*IdL&WQYTgDi#!3xI97}| zvSQ<6=eJ4|(F5}oD-!FY79>7`b}F1Lt+&&)tT{z6xbV|VAuAlaBdJI)YMOzl2iG~qNPHoUeb6D_R%M1#bVoheZr%P8%amw`?(TD8s@4V55|7Hjp}*{ zYK!`SiamFzHd`B+=Vx_v*U?(IHY)6+p10tuJS6_pH|#Q)6(Ih&Ep(GxE+*keLufI8&e1oAp@8iWZc+C;>ak8U626`EK{>?R!B>NB5xl&B!r7`7k{kEDFIWv*k& z-|wF&@J6}c)v)PfgwaBG>UJxn$oH8QaiA;|GJQ2FKi!y^>o;|MQabgv=hKSY-_4lx zYtN3qn=!9%gi|OlDM%}TM=VR_ByBV(&5Z*iPq7~_;^*N5q8pz(6<#N0l3FFh$0vhx zsaEC^v>V00HDVr&-q!^w`q2YVAC%)dI{a!@vy0RDtvb`%b?Nc+{Wzf~x7xS5YF(dq zsz^Mti5#i=f>nY_z2>ezzJ;7aTZv}l6%DBn+-ul~(@Ki&fV;C${KbNlP6^HhGMRZ6 zwkh$xleVmNwxQFb*pvr#&jJnWPFhXcc1oNsP6I$2?q?e7UcFkDyzJJVR&y+f#?EUi zbG%sHJ&5U=b&q@!X%$oUB~L#Ao;LO+fUJHCy8}t`_dPexI)}r*fb_t*Y3(LGulUjo zbQC-GLkU_1ZrrJ1IM4tXyBA-+pvGL4qpaHWTwaZ3;OrTI-LIY7o_jE>qJ*zcnE#Vu zvn)7^c=D>-r)BctQ+EW)0)!kGTQV9meu_jPr1i`#7S%2*rF8w$jfd~WM@0Y*4So1= znz!t=O>n`Mdtt=GMOOy?T3SrR9c?G#0TFoGgqO4+KE24{(!p|;-A8@SCYZbA-N1~T z4Q~br_NS!8zFlb(Pd>2CX|D{^SOZEMKsn!oTojAYE-pdq0Z?|6y(Zrk+BcJRl<8BR zQ8UcWalO$#+9JKmb00d;`K3YoN@Vs`JCab;3im+pm#PE>ryyrst2o)X-X2omlm2c% zFRT(pGQJvGEOyqiRZ2ZW{(+A=ZMuZB&tLsW!>=?Z&<54VZ-~_xgP?eHNV5#gr%gN<)sWbmy&n zrXl4b?~`Ot!k0O$v}y}q-1?Ii6l2EE2?M52?M8u?lucMm%9+cvsf8Uc0O&iy#LJ(E3JQVPnXBIV%Ru_xueu3g}vpHUTv zkhx)FAku;lG(=(HPzq2S{5M(vG#3K z$(eFc?Sv=`01^QI$PB3x)jI?Z#ib@KfITqV1@4Xma-cCFu<;zZfDhnK#S|KFTc9B= zQdM*hisRKRellq)zO1eYjVSS2%yn^IwMq<2>~h-lT^y|$pcb35(EL%OhPst~e1(%_ zliw=e`+@Mw_wRC?Q%-sDOs*2-__o6?IRv7Es9keW?E(z*?M01Sj%Ocz@_NS3tqY|& zgy0m5W@eg}5Y!F!$RU82m*;7UUi2YBR!pbEtu+;tv@m4yYs_xf``MQ?9Chjm3tW4vqD4*RDv9a#*e#gCcA4FpfZJNxf_Mgw5^CnX=sE!`F;NsOUI8cTH3WgdI9_*rt8zUI&oRqv zg9~<^7njbiPxSfJzw-6#qTX6|HT{Yw#ss*n_dhs1tG(t@@_eRt97p_iQFN`OfY{T8 z_i}OfIY~Al#Z>l&lLfws;LX>@Iw9@f%2A>t_O&Ng_~F0;zN~O0Y5>cA^Fhf8Rr0jm zix)fc-bhbSVJv(2>ywk#>}4wibY}aS>$1%?_LGdTrlam#i^ZD@z|e$Y1a@neALAv; zs34#yfx#lI^Oa`6U1Tit)MHn`3GG1Et2prll53v5dA~L@cJ^Mhacm(g2}=lW)_)A14=2(GSQZ9A zU@l@pK0<7puNS-bPNR$fE}4ylo}EgqTV#04mwv12uh1RF1M^tmIgeya8oVBVazkX`Irx~zj??Ik)5iqnSVDwIMb=)p+)KxGB3avu%iK9o- zPDp96w2@vp+RxG_GKp|!>|pKR8>dU6ONJClqQD=z0>FBj%T0W>tnJp zf5y9KqSvTPq-}&Im1m6=gMjTmq!Ut^C^4fmnUPko9kjuJ)ZAF@WvI-Wu`}|imY=8! zAd%+>_nHS`eyya@O2~*(3S~`iL4V4OW1a~wG%0NvE7V?4MN9Nb)@`ZJ7iKk>#00Dc z6PaG-&mJ)Kd&wT?+uWOV=6^bGG=#~yZ^XQXH0EpzT&Nt6y}ivw>g)^-6EGjwlX(ax6FrS4 z+(zv>8o>5`cVmrza>Ez>>^@?WLXBOa<9bhWEsRLh90V>^?46(%LP$*)lvtqHXW8`% z4~C9wCHTWCy23nIs^Ms(;EdCY&gJ7b=mnIsN3F?g8;DCTW-2@HPUW8e(&~d#%cKO& zb)e#QqVvYLQ!|g8lW5YsD3qoAjs1rJ@vsmzQTn|Ji2>l|Bb*qA;38)yy3EDcXq4j! z@ysc&Ug?ddn=YC4d!w*+m}2J=z3XgA5Z=TXh}+jJcN>N zBRrL-m2$lxH0$Re>1P83P&>SILSR~%k5M`+(981EF_d6B;HbgFbVr5w9i3ik3pWK> ze>x7HVN#6p2yGTBo6;=+P0)OEGu`p-V@`R%^tP;ji!ASsmjp3_0nq3;8Qzcz&nM`C zsZuQVPDxNn6{QG|diiiqT6SruTq(4ow-E4i&tES*my&5w=oh3_l~H`#_Q=-SXCX<@ zLSHOw@nzv5iq&g0t0|ef2a}VC4fW`svAD}#0-kL;7Aw9O`yQ1Wn6sKHU`bV=)v;h? zvUy`;VI{XRKV9CM-H<1^t6u&i|3BBxuA1WLS=_iEF>v46ihIBgjFyE;N!8Xv{B^_= zKDEYu*lyjR73%_Sm0PXY$VgWKkTi(Kf(^Lqeg|(&X%=NSVvDqx8)wK_Hoy zcTYN2&Pz>D>3QkaObW}Vs856xm76t)8?8Yufbz^^ASqqgMwm_kVu&gb*;UFGhV>tezlaD-;wtBm=59*d7x8~Cj z&_CmTD-*uj-SwABn?RJvA%3r+3Vt%{*SVf*sBOfkh(aL=#fNnJjb+X^0;UV#A$>i^ zHNXkqXi}zE!hx-oCW!L3c@;zw?`PEh^$2MsvxJ}IYwKq-(+wAaS-A*(yVx-@Ww5dx zXN1*i64_f<-F0&8Q=O2AC(?-UZg@IK2MU5W-x&7@qT?^xTOC+EtdFxxRTsUGECb>^ z)#N2yblUuqU30spRa1KqC%m)!(!k?fgbjno^Mt}u<)@mMq3^G1V#DEEu9W-6lGHdl z2B|kRjg=|OStYGw9>2d^4(mo4`fA;28Rb#px)F5z{#k#wDd$EQkX&!T)!(34nDQab zsCWqVt36%aERnK5vM29_p^>A*FTnsB*%6V$Sdh@!W5?-Bjtijy_{P9|8@1^zdf&$Q z*R}7NO$5Vmr5;8L4XL~|s=d$S{$#Nv5Q@Krip$0fH2*TP24s(L1W9=Z@tYTSO!ku7 zFl`RVj~O#wAXs{YXj1V0@R5y=oOM01itMX)r`(%ALl zsTs#^A`d#OrO`}c4v?oq5Z-jp*Ykon23-eZIrKL&@wwej77O%^^+KT(Q^qzRv zMsS?Z`SRat`MvVj?v0~gp8+ZM2)Y_>HdbA0A~rT%feoob`H<-F=r zfH_9<|G0(Y_X=KpB;7p*x9XTBfcjo+D|%93hrm<;cPIu$72u4Puqs%Pl3_G}$$Ust z;LfNjQhGiC_~8TD#{r@zRHVpCkd?|n*mXn_Ob3E(89%v}ID@ToD)$#MK1I>P17%tw zWP1>4Tb3#=F0mBWT4wT3KzlDj!2p^C9s(Xb*1=N&bW04WLpa_w42%x|kzDxex+`l@K&q^zrKbyya_my{KZn%xh6DD zDBzDeicEf)`leX15Db994Jnt7BrcXbXuY4Ja=ORoY>#$6DudrV>kBrN-Dk%Tt3il^ z&+}n@U+6u4`S|&EU&7k^wL>Xu9!B`OrbBAap2~L+yo%wMR zN|AiJpX%HJte%&3;n_LJLh*501W?*j!RFYIW|PxZ!qsCLMeCdQE=i*5KsM@AL-Ao$ zkXvzw1Sh2rTq9~R$b|;b&H;gk`zYbts*r4oizyI&4oWa$GVYvFCw@fyZ7j8bPW6EU(D$~V7(WKVo-7s*1iaL{N0p)UwWDo$g;5vkj*U5A=IbZ2SCO48=Swe62Qc#IH8HBKNFka;%T%qS^j6A z>|#q5?SXq5IE=jmlClb_KJ$UAKItmR8GGbA^lggR~+&sX%Li+JxJTeiP}oK*PCgj+g_aD9EVe(!Fez)GtY z5n#KB>mYE{5AXY+Nj?5Z5cmKm%Y_7IVUerT0@FBsL{OB}<(4R-5I6jRtQk+-+kIW$ zm8251pdDF3jBNY?OU&;M;40vsJ@WSU~2P*2V6hX zmO}Z_ggUH)MXwt#o3A{t4HxA-&m$PQt5p8QC%$T!B9v4W$gq?sS%S*TL$b0)^L_Z+ zB1(xn3}UZJp$SK-HWo5-{;i^s~+|8B>Q*nh&I(W3O?f zpg;$>hJ9GmbwV73U54qT=tcZ`)0)Y;Bs+it_l;Gycg&0v_4(H39h={t{IMA_^hw3l zKNFey?le00G^_Nf+ZLGra3fzn+_)b)%Sm&imgD+;)9JzaHQDW(Re;#PI4Zc|QBe2X z^r3^%A^7j6#M4**?Nb6cmIo3wt?mq|F3H?{gAV-F9*f{N=OHTHFrGV-HLKs^8Wmf@ ziW3AB+Lp+NP7DNFs7sY*jk*`;sUUakIZG;3uq9i|Axdn?&16`8iln&K6Hh^go9p|E zjJ;uwokhp{n+NzD5`fd&n3?_g{`;4Wv}Lu&mHezx+m$CPZ$vSgpU*o8qTc}AH*X-q z(-*y|VL{c;`q)AONu+Rr@)Y3RE%EvT(kedhRj;FFD*SfqgW_256U9 z*C#;Uf-!w@epPz#BxVD+Z%7E@l;@pU~=&QibHCC zEHL$I?q5BIW-5Lprj<{_ywrjD+rbfL=y?eha902S#3x7suYk+-|4*AxAr8 z^1N6U2|fP_OoVt$92bq^uRKdMnu8@N77Luzm9&lU+0w;BD5$zg&FN&Wv|pw0b3S|A z4uKrs2!SR5U}L;Q5hXwX%Wf7;s~9t|UW%%YcU+-fcO|Qf;49f?m>Z9MNW<$;S%e+{ z9C+U3li6t)h&nUe#4|C=#>s-1?SP0NVz0~uBddl8j4`6-Ol}64V5hy?|JKy&hzNW` zt7!CI5%qmw)5C7S+k|>{L>Tc#?`~f?7R2OW1zw(aQsXpU919f4Q$_~UfDC_fY5%Fp zgxUCKt4y!188yLW6$dRHXsObq;i_f!!t-@A&dXai=E^A9U*h1qKd_lyNVS1A4OlT= zzoqc(4m=jONqVpARO3?I*1?pH7#x8SYj^fg2mDZ~;r)T82y_r7UWv((j%&4w5 zY}e^0RRv2)NGTr~pr?oXm^V0~^pJ98@AFUQiV_{N@!RfnfxBDNEP$`_W)JCeYac9F zS$x$3;^=v+&UN$C#l2R<8nBT2y6_vUvWbB4N|aS`4i4WN2 zNMK({|k%ak6s^$6y92MQh#1S0#`BdjD1IMS&t zH#rS(>JwwlCwY-dvZRjz3kook{&wsTGzPjGVQa|}v?67+FXUWJq6j0w6c}ai*=RaC z#+Mdx9C}t-Lsejvz9qsux!TBDh>`qGMK(4=4 z>5)Xz-5$etTwUf7`AG>}i+53osPWsb9ZL}dA@*qf&HwrvmT zSk1e8ym2k0r{?%#z;QqF*EOkD^S^0QZcMH>EXboNz&jY8#A+bLD1-sS0o+eERszBt za#6Rhw%Ctc`KHt()$Ag7PTDWswhJyYS2||>oju;k$sG$wtjTY!HI^C1B})>&to$M$ zk(0)IwdHH?Ym^jAEPtyFBAHRqYZ>+UTP@?BZ6iJ5G*a`NsRDTJOE6HvLX3nv>sRjD zH-K?PyVGo)0V`pdBO%dEI7pPmz~vFfu-|)NakBLJ{A*8=aS&Ta9jG zvsyI6b*#uh$mKm-4Y6efvY{2TvZEqgDqok*%(=9im00= z21P7j5x9oBYw}oOrSMH7vn4)%)tLRuo-e}dVqq>>#^h{evIE5Y9Ec8?Zyl31b->K= zT9M6mQ8w#}t9pJ2#1K4U7S&DxrI0o5Zjvb`wLlzLQS+0=TNlIJCB;X{h z#2jf9eB|9b8bZ4?a+fzcE=4+OxIvTzOu(F?(Zl%?S;k%!RUP?}<~`Bq3+tU)aN zEe|i>3`y);$U~0+Q*JEK*b;tge!yyh?fD&8W6MBzGtk(Ad*fkD8*pK;$~?}bwQe03 zbGEYQK@$>iCqO0tJbk4lQ&vuqx(IG_7i`WnbjO+cUk- zRL0GGw*zJ*9iPydG{?g8zL+0N3WJhLwg7g4aRl&{GuVyhHWz%SAHQ!>IlzN`0%HRV zjKxgh1|R{^%xsVO(uvxqx@jiY#od#^9Wh^|qT2;)`!eHn({S|_!D*!17qjcSygO*8 z)yEf~Ga8@250j<^MaP>CoW#7iRn=}pDjfR59Y@4V(l>~t*PKR9v>1vZE5 z9@14B^B$cI_z^{BAg`$c-SJgNcss(sqDq#D^YGo<7~rcct(!Uh%-MJ{aeJ?gw3!JjXjm73baufJ#$3dCGa zM6atudL|J&IK4+&g9*ABG}p1mrHRL@;vH=(Dp6dVNopwVjTl<|6IBhyU8q)L^KO#m z6J)Up<^yGvlH&2d=~b3m2QSqz?|0d+IooVhpGH08opAS{_g&u)8kqca!>~S^uj%ur zbD^>`y7(&CA!zHtzHk&f&cs)%t&Y;pWA+{cV2S&!sB7LTcVgnJBr{;z5QM>j{rDWo8CcdxjMz?oz>(!0_b@@L0A{H&76=r5)%H;!GZ z%1MitNauHh&QE95PsIjdkb#S5Dal)&;Uj6EKe-!s(Q!p_-?QvWyCW~)d@+r*3hw5h z!hzJOCZuTT_zG*^GuLydequ7z?u^V>ZRtB1X(4pXmACLe2 zRtPok+ftR;C=F5?&YZ^1`G;#5wR?DdHeDPE{)2;1ybRFvycyf5erYiiP7^neLA6r= zXR>w;mX7ah)Vg@YAKZf?fPrT@tW;(Z`Z=6k!;gg{q0%mx{_$pGdJj+>kI%wQkteV# zq(D)Nc7JoFQH@pi1@NY)Tv9Jlm-z7B0HB<2X}OMPOc<2G)7mU%(&V(|PQ?l+s_f%u;O zDmSaPHGv;C>kAyd4NZx<*#B;mS=F`WunZ!3cZWT3@M*M1&D(9e#XiNoJ9h~MMAk^i zIW=oXv!)*y{B4$n70;%Y8_0%zg$=Zz9m;=uppj`as>7Q}udvl{0o~eLjzkY);obS( zS=%}_zvB>E!@HAIh zGt=!)-N-0ELjS=5eV+Z`2XzobnNGpUS*`#l!b2(#XFR0?<%HXROYOCvZ=V|Yoh5c` ziBKeK$!+SA8N8!2q!;AzcvQ{o$ZMK-tZ|Va`P++RB{|DVq4zK(*$$hjXDdu-eH@!} zhAvwQg!+32Q$g59!TnSUT+d=Qf43Q}Kp$^urM}+5$NC1M4=JTjPx=Eomgu-vf=6I! zKq|}}6BNbB#ul9Qt5SZ)ecj>Ph_W7uJd21Z6b#>hi}}rY_P1s1hZ_-dfBI&HqYiH_ z_cK+%mgXQSnkq!g*vUbildCKaFk%P*oTu0ANuf>QIWoZ?y#Q$_k+#3!MAKlB>s$XC z_p0}`>1%v*p*AfE$}DYRYCN8yCL4j1I5mNa6M9|lgL8uqd`(wtz98zRgS=U@Plxxw z#{Zf>;Frb2%1@!2G~e={;!UT4j-r+tx7snwMEm$YuJXsXTIhK^Rrv#ig3zKlwc?kao}!r z<27E>-WPQDLwWwor0q!8=N_lWjmvKZPP>|R9co0Df6KO(ffM&17+ZdeU)cuJ*U6Zj9F1Fu>5uYbOO&24OM@zpQeL;_qX$qLtz!0NcoP7=C> zgq||EB5D~ag3}|v`mV{q(KVxd=SHYK8`4pz8Ue>i^K9xxjQsT*9l>g>p7d?wJVw^P zFs!3chFH(d;U@xOT}tLZU`c%bGhtEI9J`Y-IHN5|+;k>-cKW!mB82;A9iI`hMG<1X zYqtcn%Ze`^Mrl-stsFTHp}6Itd6yEuMQ>;zCI>vfd90G$(yz(_8ij~&D8rG&d52Zz zL!OOM(dhdEF*SNQy#}U@Lv)A)Bhy1KON^0fMkBhrN$!E#Ns&*C4A~x&Mw+a7%Qu>T zR6^YJl7D^ftL~ecn8k-g^&TfpHvQQm)s#b92-5)?-@~D}fF+Nx@mTn@M*~x~AD__V ze6~-aMBGKvP6)}`mnbWH+{V~D=lQAipwPRLfpfP&tiy#NvmNQ0uq-hrf& z)LxA!);Z4{u0oL9u>p^BBMPz)4#G2hD>ydD|I z>#L*{YAq+Hm=ns_E6ENNIK$Cb_)hvai+KTsIsI(}qDp*l5!{IFW!XFx#IAfG7q1Jl zT%C})(2hBZ!e2C{sZrMAKy#=Vwd0?$=|*G)a_%g`bH2%cFzQH@@RnRY zrnKeD#(Yu^`Rw?SeA-orjHh!>{x3|I#6LF*`onbj zl`yCm%ea%!%{$%P0=o)&Qfv3A@7(;2_>CLqpKX)axA$1M%d2u3J&A>WgShCAbi(~Y z5cK??20?$a1~HGY?a*T?-qbmSycf7EA`*aI5B^t4bzhe{=;7~mF255*13VSGcYiR$ z^{g*}qTly@H)fhTjywO+AL07FKVr>K%f*3(`_v*Tao&9Uqa(qqo!NX3VC5PG{fiOJ z4?ZLNGvhXOaYAZii+lpl%^V!ZK7Hjma?dun>XoZb-(}rhI4}2?bxqRFeWQk9q2Hu^ z?BTrp-Q@r`9*Y#YjDJ@ZY_*v5eMY82_!4| z?u%9*YXtVajmxWzo`e3T{kdh{_>vEo(t91cP|*XK{`Ht^=BNFu9kbkC@L=G3aQ7d> z`II(4zw&HwC5>}b%~+PI_IO?Ox}O+wE^VD9q3X01DnjeGV?0ZYPou2f&&EQIGUXZ< zUV+w^rz}^7H;n&Gvx0#Misl8;pK6Gn1Q#3W%Ns0Ujhr((h)*tjVW^$&2$a%jzexY{YYDLJOaKXa)GJSIlGA4S z`uf$a4*-VREC5t~N$a^B49(?H#t~A{)c?wyWP>$^5Mm&I;rsPx*8-IT9HS_q~iTlG*e;+chGuCPf3-r z#6x(CMG7T*;Y@*CntJuWczl@iG*SVRji(lZ7K^tHSbT5q6(e1*x6QKN%DsAbLrFr> z8QfDKQ5Oeq0%Q@&Qoo0i0C$3Y?eC!^zj-IP?O^tnl~nO9?(6E6@ly=fcaP8a=$~)O zJoGYq0{`&rLo0YR2!&i}!#g^LD*+kjDxm%dh<_j+hr9(e4fWY?coE^(SqibnVJozu zz`y^cZy^a4aQ(x``z>iGHvr+oXww_^7F}yZ*|YK)LjWWZjO^N9zf}Jqj{JZd(N_RV zXXt)2)sCVsC3rJa_At-^|0^HT_ZqF-NzKv(k)MZJVb5Bh0!l4s@aNSNw?NDir}|z-_q05YeDhV7x%DQSA0tft(5|a}x64vwie@ze|(EtDd literal 16455 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 diff --git a/docs/images/prison_docs_100_setting_up_auto_configure_05.png b/docs/images/prison_docs_100_setting_up_auto_configure_05.png index a09761c733de8a503257ece2fc269acdb5acd3d3..0514bcbde88104a8e0b63daa13f51843d1c846db 100644 GIT binary patch literal 21277 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 literal 15217 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

Ga@6-c8 zt#|4ET0umdh*;U8IkU;k!r5$9`;Uz^!v0L;{yWO@~VW3`Ywbrv)@XTfvE9r{%Ki95bZV1jEwQ)9Ej-d5+)3Z8U2|$Kgaq zKi{ARsHRT90EvYFH^wMubSYbgXMrV>mwocW`7w83K@b1R#()K>!s9d~E%vcXlfhGc zN#hK48YSl>{8<4i3J7>fkV8BpPz$X3SV-63d}$(R^F3qD?|~4Yyr5K@kc-)>$tDGX zyh-6MtN?GR+75gl5Z0#)a8{sN%Kyu4{|9;)hU1K302FX;I4#HypQrGs1`vliHI$BF z){&gw){T@vz}O(2Tdok1+rJ~ilqG;GRU?fs7-fUrF7W#b@X^befUZ^zU_74wiqM$t z#~afaCz_)t{HCd9_r)s~u#QXs|EqfMH&#kodO8}Bf)nftJ^N@=o9yrBFMq?mdf~_3 z6%pW09OR9^_`|mv&kaO%j+jJ+U)MtO(!53lSP z1Xoa32tL{grBS)~&mEi7&BJO{az_5YpOOEWLu&h!gp=to_hz|k2{1oM2WFs=r*=Q& F{{f`9Xfyx- diff --git a/docs/images/prison_docs_100_setting_up_auto_configure_06.png b/docs/images/prison_docs_100_setting_up_auto_configure_06.png index 9ebd8c78d631f04aa7feed9d7905c8d845bdbe68..eadfe8eb3e345ee0f1dd329f47e856ce3de5c59b 100644 GIT binary patch literal 45116 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 literal 36043 zcmb@uby$<_|NlQlQ52*^MCz7ilz?eo#}(V&Qi=S5VgNPuZZ^D=Az@Ze zRL;vxlv6V8bMM&{nO;aW>$@;s?ucv^pdyP|_8b`Cm%z>?CU0U6H>dPGAm=|)ovl?> zReSahlO;X7zxdvy#GUn=pOua1pC(NoCm~L4&htoS{SZIt>F$cVjYGt^A06Js?nfC> zO71wHcR6rOez<~<8#9|Ob9b2;aP~Y@jh#nKA8fBd%3l|q@jQL#uCF=g^5gE2uYuQ$ zkPz+3kMnIFT)ju)nN4;5$tmO*wNnoQ_1?!Tg^iXx!`b1!%N@|USrZf_ED{n<6rRfu zCFNL~R-L>z@K`$aYd`0hAe5#Wz(P3*6- zBj3L5LzB;??&A8`@s0O=luh&rK!HJYlP?pWv&|xMNL%t=Vk{hd;F_0{ahfCCbV^K2FT%!R zG#sA2w!i8Ry99hkLvIcQbBo07V=R=Jl82vhw0?9C!hWlL^m#CWnJHH$;&E3r0y$9r z>Nq8#t1DtD&sf>_Hc@zx)#$dED#b01ox*j9lzU{1Soo9(g^@@5>V!~*mSc3y)cx08 z*MHr`^=~KWSB{Zg#cm4nZ0-$j9Tu@V3c;OFsVQywg7`vcFmbO&K0c&j=+TL@ z5>E(Hj}$A0cil|kU3^hdP>U4!^&tKrEPxZ%_wl2!pVU#sUAi-B@S6{b%4^?b!xQn= z3&@j9=t;;)CMT@m`rOeM+lEAOZ&j7p68z@<;0+ZqXf9`oaubp^mBqWtB7BqW`^8iC zhNntcRDXsSQ;qE@&jh4oifMq$BY$G$C%PHH(P3P<#k>cyIXz-8)Gy`=7BGhDWT()0 zK}EIWo8WC|dvFxjqUG!O89Fh?*v;|17J~5(5GyE|n7d9}g~n8?s<|s#SxLTmVtKQ4 zn#UmU?ZrRYyBd%|eDT$|tG}iPguVG|w4f8pe_wB(el5h_dJ-rqh(f30HRYh8wRm?G zKTFzu?QvjXA8oG4Gl`3*oSS64-u%1-A-JVMXP{~<=E;WQb17wR_9Hg)-G|EJr&8pB z5hM{Sy;|T2$G3H|RO2#98xOR=vxssViu#gMs%>ItuOF(o_2GI}dsO7O7XE@%CT<9E zf;@-Or06`uwb!3(&8D31)`M?yzrs^$j+s7Lb$4D&;np^dV;b-L@}+u8)XR9XO^4h1 ztl@*O?c!m*ntPF#CJ_jvO*$JL#7n-$=~+^K?9-7w*V*`7f@VxqcCpv4J!&=3oRuIC zJ_X^oH#A?*or8-T!Lck+5bpigp* z<8UW7;-Lwf_u7*r(Bdn*Oyt=NM;HYO(v7{D=%CUJ8Y;;eXKMpsUz;DA g_Z0h85 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�OA9$d?B9;K1*e#xYSc2Xg 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 # Overview @@ -77,33 +82,30 @@ Some of the steps involved and which are covered by this document: * **Turning Virtual Mines in to Actual Mines** - How to set the mine's locations so they become real. -* **Setting a Mine's Spawn Location** -* **Resizing A Mine** +Other topics that may be helpful but not fully covered in this document: +* **Setting a Mine's Spawn Location** -* **Moving A Mine** +* **Resizing A Mine** +* **Moving A Mine** * **Changing A Mine's Liner** - * **Submitting a New Liner Request** - * **Working with Mines within a Void World** - Special considerations for resizing, moving, and liners when in a Void World. - * **Working with Mine's Permissions** - * **Using Mine Reset Commands** - * **Working with Rank Commands** +
@@ -119,9 +121,9 @@ These listings are to help guide you in planning on what you need. A minecraft * **Minecraft Server Version** - - Prison support a native minecraft server version of v1.8 through v1.16.5. - - Prison is developed and compiled with the Spigot v1.13.2 build. This ensures that Prison is able to natively support all functional behaviors from v1.8 through v1.16.5 since v.1.13 is the only version of Spigot that has both the old internal functions and new internal functions coexisting at the same time. - - Prison will try to support v1.17 when it is released, but not sure what special requirements it will place upon the development environment. + - Prison support a native minecraft server version of v1.8 through v1.18.x. + - Prison is developed and compiled with the Spigot v1.13.2 build. This ensures that Prison is able to natively support all functional behaviors from v1.8 through v1.18.x since v.1.13 is the only version of Spigot that has both the old internal functions and new internal functions coexisting at the same time. + - Prison supports the early releases of v1.18. There has been no issues found. Prison will try to support all of the new blocks within 1.18, we use a library called XSeries to provide the new blocks. So as they release their updates, prison will pickup support for more blocks. * **Memory Requirements** @@ -206,7 +208,7 @@ The current version of Prison's `/ranks autoConfigure` uses Access by Ranks to a The use of Access by Ranks prevents the need for `/ranks autoConfigure` to generate any rank commands dealing with permissions. You may need to add them for your own needs. -**Critical:** It should be noted that the ideal conditions to running this command is without having any mines or ranks previously defined. If any are detected, this command will terminate and will not attempt to perform any actions. You can use the Option **force** to force the auto configure to run if there are ranks and mines already defined. If you do force it, keep in mind that it will skip over any rank or mine that it would otherwise try to generate. It will not add rank commands to existing ranks. It will not add blocks to existing mines. It will not hook up ranks to mines. Nor will it configure such features as Mine Access Permissions. If you decide to use **force** you do so at your own risks. That said, it's easy to delete the `plugins/Prison/` directory and start over (or just rename it). +**Critical:** It should be noted that the ideal conditions to running this command is without having any mines or ranks previously defined. If any are detected, this command will terminate and will not attempt to perform any actions. You can use the Option **force** to force the auto configure to run if there are ranks and mines already defined. If you do force it, keep in mind that it will skip over any rank or mine that it would otherwise try to generate. It will not add blocks to existing mines. It will not hook up ranks to mines. Nor will it configure such features as Mine Access Permissions. If you decide to use **force** you do so at your own risks. That said, it's easy to delete the `plugins/Prison/` directory and start over (or just rename it). Almost every command within prison has detailed help, and it can be activated by adding the `help` keyword to the end of the command. For example: @@ -239,339 +241,37 @@ The server that was created to run this example was using 9 core plugins: 9 core plugins -

Note: The following is from an older release of prison that generated rank commands that controlled the way prison worked.

+The generated log files can now be found in this document: -Sample of prison starting up for the first time and it's console messages: +[Prison Log File Examples - Starting Prison & auto configure](prison_docs_101_auto_configure_log_examples.md) -``` -[03:02:59 INFO]: [Prison] Enabling Prison v3.2.5-alpha.14 -[03:02:59 INFO]: [Prison] Using version adapter tech.mcprison.prison.spigot.compat.Spigot18 -[03:02:59 INFO]: | Prison | -[03:02:59 INFO]: | Prison | _____ _ -[03:02:59 INFO]: | Prison | | __ \ (_) -[03:02:59 INFO]: | Prison | | |__) | __ _ ___ ___ _ __ -[03:02:59 INFO]: | Prison | | ___/ '__| / __|/ _ \| '_ \ -[03:02:59 INFO]: | Prison | | | | | | \__ \ (_) | | | | -[03:02:59 INFO]: | Prison | |_| |_| |_|___/\___/|_| |_| -[03:02:59 INFO]: | Prison | -[03:02:59 INFO]: | Prison | Loading Prison version: 3.2.5-alpha.14 -[03:02:59 INFO]: | Prison | Running on platform: SpigotPlatform -[03:02:59 INFO]: | Prison | Minecraft version: git-Spigot-21fe707-e1ebe52 (MC: 1.8.8) -[03:02:59 INFO]: | Prison | -[03:02:59 INFO]: | Prison | Enabling and starting... -[03:02:59 INFO]: | Prison | Enabled Prison v3.2.5-alpha.14 in 223 milliseconds. -[03:02:59 INFO]: | Prison | There were 19 new values added to the GuiConfig.yml file located at C:\mc_servers\spigot-1.8.8-autoConfig_server\plugins\Prison\GuiConfig.yml -[03:02:59 INFO]: | Prison | There were 37 new values added for the language files used by the SellAllConfig.yml file located at C:\mc_servers\spigot-1.8.8-autoConfig_server\plugins\Prison\SellAllConfig.yml -[03:02:59 INFO]: | Prison | There were 37 new values added for the language files used by the SellAllConfig.yml file located at C:\mc_servers\spigot-1.8.8-autoConfig_server\plugins\Prison\SellAllConfig.yml -[03:02:59 INFO]: | Prison | There were 272 new values added for the language files used by the GuiConfig.yml file located at C:\mc_servers\spigot-1.8.8-autoConfig_server\plugins\Prison\module_conf\lang\en_US.yml -[03:02:59 INFO]: | Prison | Notice: AutoManager config file was just updated with 89 new entries. May need to be configured. File: autoFeaturesConfig.yml -[03:02:59 INFO]: | Prison | Notice: AutoManager config file was just created. You must configure it to use it. File: autoFeaturesConfig.yml -[03:02:59 INFO]: | Prison | ###--### AutoFeaturesFileConfig: test autoPickupBlockNameList: length = 2 value = [coal_block, iron_ore] -[03:02:59 INFO]: | Prison | ### VaultEconomyWrapper : vaultVersion = 1.5.6-b49 is pre1_4= false -[03:02:59 INFO]: | Prison | EssentialsEconomy is not directly enabled - Available as backup. -[03:02:59 INFO]: [PlaceholderAPI] Successfully registered expansion: prison -[03:02:59 INFO]: | Prison | Mines Module enablement starting... -[03:02:59 INFO]: | Prison | Mines Module enabled successfully in 152 milliseconds. -[03:02:59 INFO]: | Prison | Ranks Module enablement starting... -[03:03:00 INFO]: | Prison | Loaded 0 ranks. -[03:03:00 INFO]: | Prison | Loaded 2 ladders. -[03:03:00 INFO]: | Prison | Loaded 0 players. -[03:03:00 INFO]: | Prison | Ranks by ladders: -[03:03:00 INFO]: | Prison | default: -[03:03:00 INFO]: | Prison | prestiges: -[03:03:00 INFO]: | Prison | none: -[03:03:00 INFO]: | Prison | Ranks Module enabled successfully in 580 milliseconds. -[03:03:00 INFO]: | Prison | Utils Module enablement starting... -[03:03:00 INFO]: | Prison | Utils Module enabled successfully in 7 milliseconds. -[03:03:00 INFO]: | Prison | Loaded 0 mines and submitted with a 5000 millisecond offset timing for auto resets. -[03:03:00 INFO]: [PlaceholderAPI] Successfully registered expansion: prison -[03:03:00 INFO]: | Prison | Total placeholders generated: 122 -[03:03:00 INFO]: | Prison | PLAYER: 26 -[03:03:00 INFO]: | Prison | LADDERS: 48 -[03:03:00 INFO]: | Prison | PLAYERMINES: 48 -[03:03:00 INFO]: | Prison | ALIAS: 61 -[03:03:00 INFO]: | Prison | Total placeholders available to be Registered: 122 -[03:03:00 INFO]: | Prison | A total of 0 Mines and Ranks have been linked together. -[03:03:00 INFO]: | Prison | ------------- < /prison version > --------------- -[03:03:00 INFO]: | Prison | Prison Version: 3.2.5-alpha.14 -[03:03:00 INFO]: | Prison | Running on Platform: tech.mcprison.prison.spigot.SpigotPlatform -[03:03:00 INFO]: | Prison | Minecraft Version: git-Spigot-21fe707-e1ebe52 (MC: 1.8.8) -[03:03:00 INFO]: | Prison | -[03:03:00 INFO]: | Prison | Commands: /prison -[03:03:00 INFO]: | Prison | Module: Mines : Enabled -[03:03:00 INFO]: | Prison | . Base Commands: /mines -[03:03:00 INFO]: | Prison | Module: Ranks : Enabled -[03:03:00 INFO]: | Prison | . Base Commands: /ranks /rankup /rankupMax /prestige /prestiges -[03:03:00 INFO]: | Prison | Module: Utils : Enabled -[03:03:00 INFO]: | Prison | . Base Commands: /prison utils -[03:03:00 INFO]: | Prison | -[03:03:00 INFO]: | Prison | Integrations: -[03:03:00 INFO]: | Prison | Permissions: LuckPerms (Vault) -[03:03:00 INFO]: | Prison | Economy: Essentials Economy (Vault) -[03:03:00 INFO]: | Prison | Integration Type: ECONOMY -[03:03:00 INFO]: | Prison | Essentials Economy (Vault) [URL] -[03:03:00 INFO]: | Prison | Essentials (EssentialsX) (disabled) [URL] -[03:03:00 INFO]: | Prison | SaneEconomy (API v0.15.0) [URL] -[03:03:00 INFO]: | Prison | GemsEconomy [URL] -[03:03:00 INFO]: | Prison | Integration Type: PERMISSION -[03:03:00 INFO]: | Prison | LuckPerms (Vault) -[03:03:00 INFO]: | Prison | LuckPerms (LuckPermsV5) [URL] -[03:03:00 INFO]: | Prison | LuckPerms (LuckPerms-Legacy) [URL] -[03:03:00 INFO]: | Prison | Integration Type: PLACEHOLDER -[03:03:00 INFO]: | Prison | To list all or search for placeholders see: /prison placeholders -[03:03:00 INFO]: | Prison | MVdWPlaceholderAPI [URL] -[03:03:00 INFO]: | Prison | PlaceholderAPI [URL] -[03:03:00 INFO]: | Prison | MVdWPlaceholderAPI [URL] -[03:03:00 INFO]: | Prison | PlaceholderAPI [URL] -[03:03:00 INFO]: | Prison | Registered Plugins: -[03:03:00 INFO]: | Prison | LuckPerms (5.1.26), WorldEdit (6.1;no_git_id) -[03:03:00 INFO]: | Prison | Vault (1.5.6-b49), PlaceholderAPI (2.10.9) -[03:03:00 INFO]: | Prison | ProtocolLib (4.5.0), WorldGuard (6.1) -[03:03:00 INFO]: | Prison | Essentials (2.18.1.0), EssentialsChat (2.18.1.0) -[03:03:00 INFO]: | Prison | Prison (3.2.5-alpha.14) -[03:03:00 INFO]: | Prison | Prison - Finished loading. -``` -Running the command: -``` ->ranks autoConfigure help -[04:19:55 INFO]: Auto configures Ranks and Mines using single letters A through Z for both the rank and mine names. If both ranks and mines are generated, they will also be linked together automatically. To set the starting price use price=x. To set multiplier mult=x. Cannot autoConfigure if any ranks or mines are defined, but 'force' will attempt it but at your risk. Default values [full price=50000 mult=1.5] -[04:19:55 INFO]: /ranks autoConfigure [options] -[04:19:55 INFO]: [options | full] Options: [full ranks mines price=x mult=x force] -[04:19:55 INFO]: Permissions: -[04:19:55 INFO]: ranks.set ->ranks autoConfigure -[04:20:03 INFO]: | Info | Your new rank, 'A', was created in the ladder 'default', using the tag value of '[A]' -[04:20:03 INFO]: Virtual mine created: use command /mines set area to enable as a normal mine. -[04:20:04 INFO]: | Info | Your new rank, 'B', was created in the ladder 'default', using the tag value of '[B]' -[04:20:04 INFO]: Virtual mine created: use command /mines set area to enable as a normal mine. -[04:20:04 INFO]: | Info | Your new rank, 'C', was created in the ladder 'default', using the tag value of '[C]' -[04:20:04 INFO]: Virtual mine created: use command /mines set area to enable as a normal mine. -[04:20:04 INFO]: | Info | Your new rank, 'D', was created in the ladder 'default', using the tag value of '[D]' -[04:20:04 INFO]: Virtual mine created: use command /mines set area to enable as a normal mine. -[04:20:04 INFO]: | Info | Your new rank, 'E', was created in the ladder 'default', using the tag value of '[E]' -[04:20:04 INFO]: Virtual mine created: use command /mines set area to enable as a normal mine. -[04:20:04 INFO]: | Info | Your new rank, 'F', was created in the ladder 'default', using the tag value of '[F]' -[04:20:04 INFO]: Virtual mine created: use command /mines set area to enable as a normal mine. -[04:20:04 INFO]: | Info | Your new rank, 'G', was created in the ladder 'default', using the tag value of '[G]' -[04:20:04 INFO]: Virtual mine created: use command /mines set area to enable as a normal mine. -[04:20:04 INFO]: | Info | Your new rank, 'H', was created in the ladder 'default', using the tag value of '[H]' -[04:20:04 INFO]: Virtual mine created: use command /mines set area to enable as a normal mine. -[04:20:04 INFO]: | Info | Your new rank, 'I', was created in the ladder 'default', using the tag value of '[I]' -[04:20:04 INFO]: Virtual mine created: use command /mines set area to enable as a normal mine. -[04:20:04 INFO]: | Info | Your new rank, 'J', was created in the ladder 'default', using the tag value of '[J]' -[04:20:05 INFO]: Virtual mine created: use command /mines set area to enable as a normal mine. -[04:20:05 INFO]: | Info | Your new rank, 'K', was created in the ladder 'default', using the tag value of '[K]' -[04:20:05 INFO]: Virtual mine created: use command /mines set area to enable as a normal mine. -[04:20:05 INFO]: | Info | Your new rank, 'L', was created in the ladder 'default', using the tag value of '[L]' -[04:20:05 INFO]: Virtual mine created: use command /mines set area to enable as a normal mine. -[04:20:05 INFO]: | Info | Your new rank, 'M', was created in the ladder 'default', using the tag value of '[M]' -[04:20:05 INFO]: Virtual mine created: use command /mines set area to enable as a normal mine. -[04:20:05 INFO]: | Info | Your new rank, 'N', was created in the ladder 'default', using the tag value of '[N]' -[04:20:05 INFO]: Virtual mine created: use command /mines set area to enable as a normal mine. -[04:20:05 INFO]: | Info | Your new rank, 'O', was created in the ladder 'default', using the tag value of '[O]' -[04:20:05 INFO]: Virtual mine created: use command /mines set area to enable as a normal mine. -[04:20:05 INFO]: | Info | Your new rank, 'P', was created in the ladder 'default', using the tag value of '[P]' -[04:20:05 INFO]: Virtual mine created: use command /mines set area to enable as a normal mine. -[04:20:05 INFO]: | Info | Your new rank, 'Q', was created in the ladder 'default', using the tag value of '[Q]' -[04:20:05 INFO]: Virtual mine created: use command /mines set area to enable as a normal mine. -[04:20:05 INFO]: | Info | Your new rank, 'R', was created in the ladder 'default', using the tag value of '[R]' -[04:20:05 INFO]: Virtual mine created: use command /mines set area to enable as a normal mine. -[04:20:05 INFO]: | Info | Your new rank, 'S', was created in the ladder 'default', using the tag value of '[S]' -[04:20:05 INFO]: Virtual mine created: use command /mines set area to enable as a normal mine. -[04:20:05 INFO]: | Info | Your new rank, 'T', was created in the ladder 'default', using the tag value of '[T]' -[04:20:05 INFO]: Virtual mine created: use command /mines set area to enable as a normal mine. -[04:20:05 INFO]: | Info | Your new rank, 'U', was created in the ladder 'default', using the tag value of '[U]' -[04:20:05 INFO]: Virtual mine created: use command /mines set area to enable as a normal mine. -[04:20:05 INFO]: | Info | Your new rank, 'V', was created in the ladder 'default', using the tag value of '[V]' -[04:20:05 INFO]: Virtual mine created: use command /mines set area to enable as a normal mine. -[04:20:05 INFO]: | Info | Your new rank, 'W', was created in the ladder 'default', using the tag value of '[W]' -[04:20:05 INFO]: Virtual mine created: use command /mines set area to enable as a normal mine. -[04:20:05 INFO]: | Info | Your new rank, 'X', was created in the ladder 'default', using the tag value of '[X]' -[04:20:05 INFO]: Virtual mine created: use command /mines set area to enable as a normal mine. -[04:20:05 INFO]: | Info | Your new rank, 'Y', was created in the ladder 'default', using the tag value of '[Y]' -[04:20:05 INFO]: Virtual mine created: use command /mines set area to enable as a normal mine. -[04:20:05 INFO]: | Info | Your new rank, 'Z', was created in the ladder 'default', using the tag value of '[Z]' -[04:20:05 INFO]: Virtual mine created: use command /mines set area to enable as a normal mine. -``` -Note: The following are the messages generated while building the **sellall** shop with the default items: +Listing the generated ranks on all ladders using the `all` keyword: +`/ranks list all` -``` -[04:20:05 INFO]: Virtual mine created: use command /mines set area to enable as a normal mine. -[04:20:05 INFO]: | Prison | ITEM [COBBLESTONE, 4.0] added with success! -[04:20:05 INFO]: | Prison | ITEM [ANDESITE, 5.0] added with success! -[04:20:05 INFO]: | Prison | ITEM [DIORITE, 6.0] added with success! -[04:20:05 INFO]: | Prison | ITEM [COAL_ORE, 13.0] added with success! -[04:20:05 INFO]: | Prison | ITEM [GRANITE, 8.0] added with success! -[04:20:05 INFO]: | Prison | ITEM [STONE, 9.0] added with success! -[04:20:05 INFO]: | Prison | ITEM [IRON_ORE, 18.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [POLISHED_ANDESITE, 7.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [GOLD_ORE, 45.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [MOSSY_COBBLESTONE, 29.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [COAL_BLOCK, 135.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [IRON_BLOCK, 190.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [LAPIS_ORE, 100.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [REDSTONE_ORE, 45.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [DIAMOND_ORE, 200.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [EMERALD_ORE, 250.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [GOLD_BLOCK, 450.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [LAPIS_BLOCK, 950.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [REDSTONE_BLOCK, 405.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [DIAMOND_BLOCK, 2000.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [EMERALD_BLOCK, 2250.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [OBSIDIAN, 450.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [CLAY, 12.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [GRAVEL, 3.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [SAND, 6.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [DIRT, 4.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [COARSE_DIRT, 7.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [PODZOL, 6.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [RED_SAND, 9.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [BEDROCK, 500.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [SANDSTONE, 3.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [POLISHED_DIORITE, 8.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [POLISHED_GRANITE, 9.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [CHISELED_NETHER_BRICKS, 39.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [CHISELED_RED_SANDSTONE, 11.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [CHISELED_STONE_BRICKS, 11.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [CUT_RED_SANDSTONE, 13.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [CUT_SANDSTONE, 10.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [NETHER_QUARTZ_ORE, 34.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [QUARTZ, 34.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [QUARTZ_BLOCK, 136.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [QUARTZ_SLAB, 68.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [CHISELED_QUARTZ_BLOCK, 136.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [QUARTZ_BRICKS, 136.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [QUARTZ_PILLAR, 136.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [SMOOTH_QUARTZ, 136.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [SMOOTH_RED_SANDSTONE, 14.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [SMOOTH_SANDSTONE, 14.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [SMOOTH_STONE, 14.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [CHARCOAL, 16.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [CRACKED_NETHER_BRICKS, 16.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [CRACKED_STONE_BRICKS, 14.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [EMERALD, 14.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [END_STONE, 14.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [END_STONE_BRICKS, 14.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [FLINT, 9.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [LAPIS_LAZULI, 14.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [MOSSY_STONE_BRICKS, 14.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [PRISMARINE_SHARD, 13.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [PRISMARINE, 52.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [PRISMARINE_BRICKS, 52.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [PRISMARINE_BRICK_SLAB, 52.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [PRISMARINE_CRYSTALS, 37.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [DARK_PRISMARINE, 52.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [DARK_PRISMARINE_SLAB, 52.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [PURPUR_BLOCK, 14.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [PURPUR_PILLAR, 14.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [TERRACOTTA, 10.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [ACACIA_LOG, 7.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [BIRCH_LOG, 7.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [DARK_OAK_LOG, 7.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [JUNGLE_LOG, 7.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [OAK_LOG, 7.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [SPRUCE_LOG, 7.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [ACACIA_PLANKS, 28.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [BIRCH_PLANKS, 28.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [DARK_OAK_PLANKS, 28.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [JUNGLE_PLANKS, 28.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [OAK_PLANKS, 28.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [SPRUCE_PLANKS, 28.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [ACACIA_WOOD, 7.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [BIRCH_WOOD, 7.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [DARK_OAK_WOOD, 7.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [JUNGLE_WOOD, 7.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [OAK_WOOD, 7.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [SPRUCE_WOOD, 7.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [IRON_NUGGET, 3.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [IRON_INGOT, 27.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [GOLD_NUGGET, 12.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [GOLD_INGOT, 108.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [REDSTONE, 45.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [GLOWSTONE, 52.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [GLOWSTONE_DUST, 14.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [COAL, 15.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [DIAMOND, 200.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [SUGAR_CANE, 13.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [SUGAR, 13.0] added with success! -[04:20:06 INFO]: | Prison | ITEM [PAPER, 13.0] added with success! -``` - -The following are log entries from the generation and assignment of the blocks to all of the generated mines. - -``` -[04:20:06 INFO]: | Prison | Mine A: [ANDESITE 5.0, COBBLESTONE 95.0] -[04:20:06 INFO]: | Prison | Mine B: [DIORITE 5.0, ANDESITE 10.0, COBBLESTONE 85.0] -[04:20:06 INFO]: | Prison | Mine C: [COAL_ORE 5.0, DIORITE 10.0, ANDESITE 20.0, COBBLESTONE 65.0] -[04:20:06 INFO]: | Prison | Mine D: [GRANITE 5.0, COAL_ORE 10.0, DIORITE 20.0, ANDESITE 20.0, COBBLESTONE 45.0] -[04:20:06 INFO]: | Prison | Mine E: [STONE 5.0, GRANITE 10.0, COAL_ORE 20.0, DIORITE 20.0, ANDESITE 20.0, COBBLESTONE 25.0] -[04:20:06 INFO]: | Prison | Mine F: [IRON_ORE 5.0, STONE 10.0, GRANITE 20.0, COAL_ORE 20.0, DIORITE 20.0, ANDESITE 25.0] -[04:20:06 INFO]: | Prison | Mine G: [POLISHED_ANDESITE 5.0, IRON_ORE 10.0, STONE 20.0, GRANITE 20.0, COAL_ORE 20.0, DIORITE 25.0] -[04:20:06 INFO]: | Prison | Mine H: [GOLD_ORE 5.0, POLISHED_ANDESITE 10.0, IRON_ORE 20.0, STONE 20.0, GRANITE 20.0, COAL_ORE 25.0] -[04:20:06 INFO]: | Prison | Mine I: [MOSSY_COBBLESTONE 5.0, GOLD_ORE 10.0, POLISHED_ANDESITE 20.0, IRON_ORE 20.0, STONE 20.0, GRANITE 25.0] -[04:20:06 INFO]: | Prison | Mine J: [COAL_BLOCK 5.0, MOSSY_COBBLESTONE 10.0, GOLD_ORE 20.0, POLISHED_ANDESITE 20.0, IRON_ORE 20.0, STONE 25.0] -[04:20:06 INFO]: | Prison | Mine K: [NETHER_QUARTZ_ORE 5.0, COAL_BLOCK 10.0, MOSSY_COBBLESTONE 20.0, GOLD_ORE 20.0, POLISHED_ANDESITE 20.0, IRON_ORE 25.0] -[04:20:06 INFO]: | Prison | Mine L: [IRON_BLOCK 5.0, NETHER_QUARTZ_ORE 10.0, COAL_BLOCK 20.0, MOSSY_COBBLESTONE 20.0, GOLD_ORE 20.0, POLISHED_ANDESITE 25.0] -[04:20:06 INFO]: | Prison | Mine M: [LAPIS_ORE 5.0, IRON_BLOCK 10.0, NETHER_QUARTZ_ORE 20.0, COAL_BLOCK 20.0, MOSSY_COBBLESTONE 20.0, GOLD_ORE 25.0] -[04:20:06 INFO]: | Prison | Mine N: [REDSTONE_ORE 5.0, LAPIS_ORE 10.0, IRON_BLOCK 20.0, NETHER_QUARTZ_ORE 20.0, COAL_BLOCK 20.0, MOSSY_COBBLESTONE 25.0] -[04:20:06 INFO]: | Prison | Mine O: [DIAMOND_ORE 5.0, REDSTONE_ORE 10.0, LAPIS_ORE 20.0, IRON_BLOCK 20.0, NETHER_QUARTZ_ORE 20.0, COAL_BLOCK 25.0] -[04:20:06 INFO]: | Prison | Mine P: [QUARTZ_BLOCK 5.0, DIAMOND_ORE 10.0, REDSTONE_ORE 20.0, LAPIS_ORE 20.0, IRON_BLOCK 20.0, NETHER_QUARTZ_ORE 25.0] -[04:20:06 INFO]: | Prison | Mine Q: [EMERALD_ORE 5.0, QUARTZ_BLOCK 10.0, DIAMOND_ORE 20.0, REDSTONE_ORE 20.0, LAPIS_ORE 20.0, IRON_BLOCK 25.0] -[04:20:06 INFO]: | Prison | Mine R: [GOLD_BLOCK 5.0, EMERALD_ORE 10.0, QUARTZ_BLOCK 20.0, DIAMOND_ORE 20.0, REDSTONE_ORE 20.0, LAPIS_ORE 25.0] -[04:20:06 INFO]: | Prison | Mine S: [LAPIS_BLOCK 5.0, GOLD_BLOCK 10.0, EMERALD_ORE 20.0, QUARTZ_BLOCK 20.0, DIAMOND_ORE 20.0, REDSTONE_ORE 25.0] -[04:20:06 INFO]: | Prison | Mine T: [REDSTONE_BLOCK 5.0, LAPIS_BLOCK 10.0, GOLD_BLOCK 20.0, EMERALD_ORE 20.0, QUARTZ_BLOCK 20.0, DIAMOND_ORE 25.0] -[04:20:06 INFO]: | Prison | Mine U: [DIAMOND_BLOCK 5.0, REDSTONE_BLOCK 10.0, LAPIS_BLOCK 20.0, GOLD_BLOCK 20.0, EMERALD_ORE 20.0, QUARTZ_BLOCK 25.0] -[04:20:06 INFO]: | Prison | Mine V: [EMERALD_BLOCK 5.0, DIAMOND_BLOCK 10.0, REDSTONE_BLOCK 20.0, LAPIS_BLOCK 20.0, GOLD_BLOCK 20.0, EMERALD_ORE 25.0] -[04:20:07 INFO]: | Prison | Mine W: [EMERALD_BLOCK 10.0, DIAMOND_BLOCK 20.0, REDSTONE_BLOCK 20.0, LAPIS_BLOCK 20.0, GOLD_BLOCK 30.0] -[04:20:07 INFO]: | Prison | Mine X: [EMERALD_BLOCK 20.0, DIAMOND_BLOCK 20.0, REDSTONE_BLOCK 20.0, LAPIS_BLOCK 40.0] -[04:20:07 INFO]: | Prison | Mine Y: [EMERALD_BLOCK 20.0, DIAMOND_BLOCK 20.0, REDSTONE_BLOCK 60.0] -[04:20:07 INFO]: | Prison | Mine Z: [EMERALD_BLOCK 20.0, DIAMOND_BLOCK 80.0] -[04:20:07 INFO]: | Prison | Ranks autoConfigure: 26 ranks were created. -[04:20:07 INFO]: | Prison | Ranks autoConfigure: 26 rank commands were created. -[04:20:07 INFO]: | Prison | Ranks autoConfigure: The permission mines. and mines.tp. was created for each rank. Make sure you add every permission to your permission plugin or they may not work. -[04:20:07 INFO]: | Prison | Ranks autoConfigure: 26 mines were created. -[04:20:07 INFO]: | Prison | Ranks autoConfigure: 26 ranks and mines were linked. -[04:20:07 INFO]: | Prison | -``` - - - -Listing the generated ranks: - -`/ranks list` Listing all ranks -Listing the information on Rank A: +Listing the information on Rank A, including the ladder and rank commands.: -`/ranks info a` +`/ranks info a all` -`/ranks command list a` ranks info and command list for Rank A -Note: This list of commands for Rank A is how all the other ranks will look, but Rank A actually contains all the removals of all ranks now. This will allow Prestige to use the command `/ranks set rank` on a player, and then let these commands remove the permissions they should not have while at rank A. +Using the keyword `all` is the same as also running the command: `/ranks command list a` + -``` ->ranks command list a -[04:21:51 INFO]: ------- < RankUpCommand for [A] > --------- -[04:21:51 INFO]: Click a command to remove it. -[04:21:51 INFO]: * /lp user {player} permission set mines.a -[04:21:51 INFO]: * /lp user {player} permission set mines.tp.a -[04:21:51 INFO]: [+] Add -> -``` @@ -679,6 +379,23 @@ The other method is a little more controlled, and that's using prison wand to se +
+ +# A Quick Overview of the 'help' Keyword + +Prison has an advanced command handler that is able to do a lot of things. One of it's features is to provide more information on each command that it has registered. To activate this feature, just add the keyword `help` to the end of any command. Here are a few examples. + +``` +/mines info help +/ranks promote help +/ranks command add help +/prison support submit +/prison utils potionEffect help +``` + +The `help` keyword can be used on sub-command listings, which will display the list of commands at that level. The `help` keyword is applied automatically for sub-commands and is what actually triggers the command listings. + +
diff --git a/docs/prison_docs_101_auto_configure_log_example.md b/docs/prison_docs_101_auto_configure_log_example.md new file mode 100644 index 000000000..eed920298 --- /dev/null +++ b/docs/prison_docs_101_auto_configure_log_example.md @@ -0,0 +1,176 @@ + +### Prison Documentation +[Prison Documents - Table of Contents](prison_docs_000_toc.md) + +## Prison - Examples of Prison's Log Entries + +This document provides information on what log entries are generated when prison starts up for the first time, and while running the command `/ranks autoConfigure`. + +NOTE: Prison has been designed to behave the same under any version of bukkit/Spigot from 1.8 through 1.18. Therefore the spigot version in these logs are not important, and apply to all versions. The same applies for Java versions 1.8.x through Java 17. + +
+ +# Prison logs when starting for the first time + +When the prison jar file has been added for the first time to a server, you will see something similar to these startup logs. + + +``` +[13:14:48 INFO]: [Prison] Enabling Prison v3.2.11-alpha.11 +[13:14:49 INFO]: | Prison | -------------------- < > ----------------------- (3.2.11-alpha.11) +[13:14:49 INFO]: | Prison | +[13:14:49 INFO]: | Prison | _____ _ +[13:14:49 INFO]: | Prison | | __ \ (_) +[13:14:49 INFO]: | Prison | | |__) | __ _ ___ ___ _ __ +[13:14:49 INFO]: | Prison | | ___/ '__| / __|/ _ \| '_ \ +[13:14:49 INFO]: | Prison | | | | | | \__ \ (_) | | | | +[13:14:49 INFO]: | Prison | |_| |_| |_|___/\___/|_| |_| +[13:14:49 INFO]: | Prison | +[13:14:49 INFO]: | Prison | Loading Prison version: 3.2.11-alpha.11 +[13:14:49 INFO]: | Prison | Running on platform: SpigotPlatform +[13:14:49 INFO]: | Prison | Minecraft version: git-Spigot-21fe707-e1ebe52 (MC: 1.8.8) +[13:14:49 INFO]: | Prison | +[13:14:49 INFO]: | Prison | Server runtime: 0s +[13:14:49 INFO]: | Prison | Java Version: 1.8.0_291 Processor cores: 8 +[13:14:49 INFO]: | Prison | Memory Max: 3.556 GB Total: 1.054 GB Free: 674.204 MB Used: 405.296 MB +[13:14:49 INFO]: | Prison | Total Server Disk Space: 943.719 GB Usable: 689.799 GB Free: 689.799 GB Used: 253.919 GB +[13:14:49 INFO]: | Prison | Prison's File Count: 10 Folder Count: 5 Disk Space: 60.154 KB Other Objects: 0 +[13:14:49 INFO]: | Prison | Prison TPS Average: 0.00 Min: 20.00 Max: 20.00 Interval: 10 ticks Samples: 0 +[13:14:49 INFO]: | Prison | +[13:14:49 INFO]: | Prison | Enabling and starting... +[13:14:49 INFO]: | Prison | Enabled Prison v3.2.11-alpha.11 in 376 milliseconds. +[13:14:49 INFO]: | Prison | Using version adapter tech.mcprison.prison.spigot.compat.Spigot18 +[13:14:49 INFO]: | Prison | There were 21 new values added to the GuiConfig.yml file located at C:\mc_servers\spigot-1.8.8-basic_server\plugins\Prison\GuiConfig.yml +[13:14:49 INFO]: | Prison | SpigotListener: Trying to register events +[13:14:49 INFO]: | Prison | There were 41 new values added for the language files used by the SellAllConfig.yml file located at C:\mc_servers\spigot-1.8.8-basic_server\plugins\Prison\SellAllConfig.yml +[13:14:49 INFO]: | Prison | There were 41 new values added for the language files used by the SellAllConfig.yml file located at C:\mc_servers\spigot-1.8.8-basic_server\plugins\Prison\SellAllConfig.yml +[13:14:49 INFO]: | Prison | EssentialsEconomy is not directly enabled - Available as backup. +[13:14:49 INFO]: [PlaceholderAPI] Successfully registered expansion: prison +[13:14:49 INFO]: [PlaceholderAPI] Successfully registered expansion: PRISON +[13:14:49 INFO]: | Prison | Mines Module enablement starting... +[13:14:49 INFO]: | Prison | Mines Module enabled successfully in 271 milliseconds. +[13:14:49 INFO]: | Prison | Ranks Module enablement starting... +[13:14:50 INFO]: | Prison | Loaded 0 ranks. +[13:14:50 INFO]: | Prison | Loaded 2 ladders. +[13:14:50 INFO]: | Prison | Loaded 0 players. +[13:14:50 INFO]: | Prison | Ranks by ladders: +[13:14:50 INFO]: | Prison | default: +[13:14:50 INFO]: | Prison | prestiges: +[13:14:50 INFO]: | Prison | none: +[13:14:50 INFO]: | Prison | Ranks Module enabled successfully in 241 milliseconds. +[13:14:50 INFO]: | Prison | Utils Module enablement starting... +[13:14:50 INFO]: | Prison | Utils Module enabled successfully in 15 milliseconds. +[13:14:50 INFO]: | Prison | Loaded 0 mines and submitted with a 5000 millisecond offset timing for auto resets. +[13:14:50 INFO]: | Prison | Total placeholders generated: 197 +[13:14:50 INFO]: | Prison | PLAYER: 102 +[13:14:50 INFO]: | Prison | LADDERS: 64 +[13:14:50 INFO]: | Prison | MINEPLAYERS: 31 +[13:14:50 INFO]: | Prison | ALIAS: 99 +[13:14:50 INFO]: | Prison | Total placeholders available to be Registered: 197 +[13:14:50 INFO]: | Prison | A total of 0 Mines and Ranks have been linked together. +[13:14:50 INFO]: | Prison | Notice: AutoManager config file was just updated with 120 new entries. May need to be configured. File: autoFeaturesConfig.yml +[13:14:50 INFO]: | Prison | Notice: AutoManager config file was just created. You must configure it to use it. File: autoFeaturesConfig.yml +[13:14:50 INFO]: | Prison | AutoManager: AutoFeatures and the Mine module are enabled. Prison will register the selected block break listeners. +[13:14:50 INFO]: | Prison | AutoManager: Trying to register BlockBreakEvent +[13:14:50 INFO]: | Prison | ------------- < /prison version > --------------- (3.2.11-alpha.11) +[13:14:50 INFO]: | Prison | Prison Version: 3.2.11-alpha.11 +[13:14:50 INFO]: | Prison | Running on Platform: tech.mcprison.prison.spigot.SpigotPlatform +[13:14:50 INFO]: | Prison | Minecraft Version: git-Spigot-21fe707-e1ebe52 (MC: 1.8.8) +[13:14:50 INFO]: | Prison | +[13:14:50 INFO]: | Prison | Server runtime: 1s +[13:14:50 INFO]: | Prison | Java Version: 1.8.0_291 Processor cores: 8 +[13:14:50 INFO]: | Prison | Memory Max: 3.556 GB Total: 1.054 GB Free: 644.558 MB Used: 434.942 MB +[13:14:50 INFO]: | Prison | Total Server Disk Space: 943.719 GB Usable: 689.799 GB Free: 689.799 GB Used: 253.919 GB +[13:14:50 INFO]: | Prison | Prison's File Count: 28 Folder Count: 23 Disk Space: 174.540 KB Other Objects: 0 +[13:14:50 INFO]: | Prison | Prison TPS Average: 0.00 Min: 20.00 Max: 20.00 Interval: 10 ticks Samples: 0 +[13:14:50 INFO]: | Prison | +[13:14:50 INFO]: | Prison | Prison's root Command: /prison +[13:14:50 INFO]: | Prison | Module: Mines : Enabled +[13:14:50 INFO]: | Prison | Module: Ranks : Enabled +[13:14:50 INFO]: | Prison | Module: Utils : Enabled +[13:14:50 INFO]: | Prison | +[13:14:50 INFO]: | Prison | AutoManager Enabled: true +[13:14:50 INFO]: | Prison | . Apply Block Breaks through Sync Tasks: true +[13:14:50 INFO]: | Prison | . Cancel all Block Break Events: true +[13:14:50 INFO]: | Prison | . Cancel All Block Break Events Block Drops: false +[13:14:50 INFO]: | Prison | . 'org.bukkit.BlockBreakEvent' Priority: LOW +[13:14:50 INFO]: | Prison | . Auto Pickup: true +[13:14:50 INFO]: | Prison | . Auto Smelt: true +[13:14:50 INFO]: | Prison | . Auto Block: true +[13:14:50 INFO]: | Prison | +[13:14:50 INFO]: | Prison | . Calculate Fortune: true +[13:14:50 INFO]: | Prison | . . Extended Bukkit Fortune Enabled: true +[13:14:50 INFO]: | Prison | +[13:14:50 INFO]: | Prison | . Calculate XP: true +[13:14:50 INFO]: | Prison | . Drop XP as Orbs: false +[13:14:50 INFO]: | Prison | . Calculate Food Exhustion: true +[13:14:50 INFO]: | Prison | . Calculate Additional Items in Drop: true (like flint in gravel) +[13:14:50 INFO]: | Prison | Prestiges Enabled: true +[13:14:50 INFO]: | Prison | . Reset Money: true +[13:14:50 INFO]: | Prison | . Reset Default Ladder: true +[13:14:50 INFO]: | Prison | +[13:14:50 INFO]: | Prison | GUI Enabled: true +[13:14:50 INFO]: | Prison | Sellall Enabled: true +[13:14:50 INFO]: | Prison | Backpacks Enabled: false +[13:14:50 INFO]: | Prison | +[13:14:50 INFO]: | Prison | Integrations: +[13:14:50 INFO]: | Prison | . . Permissions: LuckPerms (Vault) +[13:14:50 INFO]: | Prison | . . Economy: Essentials Economy (Vault) +[13:14:50 INFO]: | Prison | Integration Type: ECONOMY +[13:14:50 INFO]: | Prison | . . Essentials Economy (Vault) [URL] +[13:14:50 INFO]: | Prison | Integration Type: PERMISSION +[13:14:50 INFO]: | Prison | . . LuckPerms (Vault) +[13:14:50 INFO]: | Prison | . . LuckPerms (LuckPermsV5) [URL] +[13:14:50 INFO]: | Prison | Integration Type: PLACEHOLDER +[13:14:50 INFO]: | Prison | . . To list all or search for placeholders see: /prison placeholders +[13:14:50 INFO]: | Prison | . . PlaceholderAPI [URL] +[13:14:50 INFO]: | Prison | +[13:14:50 INFO]: | Prison | Registered Plugins: +[13:14:50 INFO]: | Prison | CS-CoreLib (1.5.4 JavaSE_6) Essentials (2.18.2.0 JavaSE_8) +[13:14:50 INFO]: | Prison | EssentialsChat (2.18.2.0 JavaSE_8) HolographicDisplays (2.4.1 JavaSE_8) +[13:14:50 INFO]: | Prison | HolographicExtension (1.10.8 JavaSE_8) LuckPerms (5.1.26 JavaSE_8) +[13:14:50 INFO]: | Prison | PlaceholderAPI (2.10.10 JavaSE_8) Prison (3.2.11-alpha.11 JavaSE_8) +[13:14:50 INFO]: | Prison | ProtocolLib (4.5.0 JavaSE_8) Vault (1.5.6-b49 JavaSE_6) +[13:14:50 INFO]: | Prison | WorldEdit (6.1;no_git_id JavaSE_6) WorldGuard (6.1 JavaSE_6) +[13:14:50 INFO]: | Prison | Prison - Finished loading. +``` + + +
+ + +# Prison Information - Setting up a new Prison Server + + +When Prison detects that it has not ran on the server before, it will display the following message in the console, after waiting about 10 seconds for the other plugins to finish logging their startup information. + + +``` + +[13:14:55 INFO]: | Prison | ----- < Setting up a new Prison Server > -------- (3.2.11-alpha.11) +[13:14:55 INFO]: | Prison | Welcome to Prison! +[13:14:55 INFO]: | Prison | +[13:14:55 INFO]: | Prison | To quickly get started, it is suggested to use the following command which will setup Ranks, Mines, link the Mines to the Ranks, setup automatic Access by Ranks, auto assign blocks to the generated Mines in increasing value,Enable the auto features (auto pickup, smelt, and block), setup the sellall's default shop pricing on about 95 items, etc... +[13:14:55 INFO]: | Prison | . /ranks autoConfigure +[13:14:55 INFO]: | Prison | +[13:14:55 INFO]: | Prison | For more information on what to do next, after running autoConfigure, check out this document: +[13:14:55 INFO]: | Prison | . https://prisonteam.github.io/Prison/prison_docs_100_setting_up_auto_configure.html +[13:14:55 INFO]: | Prison | +[13:14:55 INFO]: | Prison | +[13:14:55 INFO]: | Prison | For more information on how to setup Prison, see our extensive documentation that is online: +[13:14:55 INFO]: | Prison | . https://prisonteam.github.io/Prison/prison_docs_000_toc.html +[13:14:55 INFO]: | Prison | +[13:14:55 INFO]: | Prison | Information on suggested plugins can be found here: +[13:14:55 INFO]: | Prison | . https://prisonteam.github.io/Prison/prison_docs_012_setting_up_prison_basics.html +[13:14:55 INFO]: | Prison | +[13:14:55 INFO]: | Prison | If you need help with setting up prison, please see our documentation. +[13:14:55 INFO]: | Prison | If you find an issue with Prison, or need help for things not in the documentation, then please visit our discord server: +[13:14:55 INFO]: | Prison | +[13:14:55 INFO]: | Prison | +> +``` + +
+ + + From 51fcbc31fba10b7e663b5789a43407d38de1321d Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sat, 11 Dec 2021 21:12:28 -0500 Subject: [PATCH 205/283] Start building the structure for the Top N rankings. --- docs/changelog_v3.3.x.md | 5 +- .../prison/cache/TopNBalancesComparator.java | 13 ++ .../prison/cache/TopNBlocksComparator.java | 14 +++ .../prison/cache/TopNRanksComparator.java | 52 ++++++++ .../tech/mcprison/prison/cache/TopNStats.java | 55 +++++++++ .../mcprison/prison/cache/TopNStatsData.java | 112 ++++++++++++++++++ .../prison/cache/TopNTokensComparator.java | 13 ++ 7 files changed, 263 insertions(+), 1 deletion(-) create mode 100644 prison-core/src/main/java/tech/mcprison/prison/cache/TopNBalancesComparator.java create mode 100644 prison-core/src/main/java/tech/mcprison/prison/cache/TopNBlocksComparator.java create mode 100644 prison-core/src/main/java/tech/mcprison/prison/cache/TopNRanksComparator.java create mode 100644 prison-core/src/main/java/tech/mcprison/prison/cache/TopNStats.java create mode 100644 prison-core/src/main/java/tech/mcprison/prison/cache/TopNStatsData.java create mode 100644 prison-core/src/main/java/tech/mcprison/prison/cache/TopNTokensComparator.java diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index d32cd341b..cee6b23e0 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,10 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.11 2021-12-10 +# 3.2.11-alpha.11 2021-12-11 + + +* **Start building the structure for the Top N rankings.** * **Mine Bombs: Noticed the player inventory was not be "updated" through bukkit.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/cache/TopNBalancesComparator.java b/prison-core/src/main/java/tech/mcprison/prison/cache/TopNBalancesComparator.java new file mode 100644 index 000000000..86a318877 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/cache/TopNBalancesComparator.java @@ -0,0 +1,13 @@ +package tech.mcprison.prison.cache; + +import java.util.Comparator; + +public class TopNBalancesComparator + implements Comparator +{ + + @Override + public int compare( TopNStatsData o1, TopNStatsData o2 ) { + return Double.compare( o1.getCurrentBalance(), o2.getCurrentBalance() ); + } +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/cache/TopNBlocksComparator.java b/prison-core/src/main/java/tech/mcprison/prison/cache/TopNBlocksComparator.java new file mode 100644 index 000000000..63b6cb9e7 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/cache/TopNBlocksComparator.java @@ -0,0 +1,14 @@ +package tech.mcprison.prison.cache; + +import java.util.Comparator; + +public class TopNBlocksComparator + implements Comparator +{ + + @Override + public int compare( TopNStatsData o1, TopNStatsData o2 ) { + return Long.compare( o1.getTotalBlocks(), o2.getTotalBlocks() ); + } + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/cache/TopNRanksComparator.java b/prison-core/src/main/java/tech/mcprison/prison/cache/TopNRanksComparator.java new file mode 100644 index 000000000..b54b83967 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/cache/TopNRanksComparator.java @@ -0,0 +1,52 @@ +package tech.mcprison.prison.cache; + +import java.util.Comparator; + +public class TopNRanksComparator + implements Comparator +{ + @Override + public int compare( TopNStatsData o1, TopNStatsData o2 ) { + + int results = 0; + + if ( o1.getTopRankPrestiges() == null && o2.getTopRankPrestiges() == null ) { + results = 0; + } + if ( o1.getTopRankPrestiges() == null ) { + return 1; + } + if ( o2.getTopRankPrestiges() == null ) { + return -1; + } + + if ( o1.getTopRankDefault() == null && o2.getTopRankDefault() == null ) { + return Double.compare( o1.getCurrentBalance(), o2.getCurrentBalance() ); + } + if ( o1.getTopRankDefault() == null ) { + return 1; + } + if ( o2.getTopRankDefault() == null ) { + return -1; + } + + results = Integer.compare( + o1.getTopRankPrestiges().getPosition(), + o2.getTopRankPrestiges().getPosition() ); + + if ( results == 0 ) { + + results = Integer.compare( + o1.getTopRankDefault().getPosition(), + o2.getTopRankDefault().getPosition() ); + + if ( results == 0 ) { + + results = Double.compare( o1.getCurrentBalance(), o2.getCurrentBalance() ); + } + + } + + return 0; + } +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/cache/TopNStats.java b/prison-core/src/main/java/tech/mcprison/prison/cache/TopNStats.java new file mode 100644 index 000000000..9b8f1ce92 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/cache/TopNStats.java @@ -0,0 +1,55 @@ +package tech.mcprison.prison.cache; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class TopNStats +{ + + private static TopNStats instance; + + List mainList; + + List topBlocksList; + List topTokensList; + List topBalancesList; + + List topRanksList; + + + + private TopNStats() { + super(); + + this.mainList = new ArrayList<>(); + } + + public static TopNStats getInstance() { + if ( instance == null ) { + synchronized ( TopNStats.class ) + { + if ( instance == null ) { + + instance = new TopNStats(); + } + } + } + return instance; + } + + + protected void sortAllLists() { + + Collections.sort( topBlocksList, new TopNBlocksComparator() ); + + Collections.sort( topTokensList, new TopNTokensComparator() ); + + Collections.sort( topBalancesList, new TopNBalancesComparator() ); + + Collections.sort( topRanksList, new TopNRanksComparator() ); + + } + + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/cache/TopNStatsData.java b/prison-core/src/main/java/tech/mcprison/prison/cache/TopNStatsData.java new file mode 100644 index 000000000..c4c08029a --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/cache/TopNStatsData.java @@ -0,0 +1,112 @@ +package tech.mcprison.prison.cache; + +import tech.mcprison.prison.ranks.data.Rank; + +public class TopNStatsData +{ + + private String playerUuid; + private String playerName; + + + private long totalBlocks; + + private long currentTokens; + private double currentBalance; + + + private String topRankPrestigesName; + private String topRankDefaultName; + + private transient Rank topRankPrestiges; + private transient Rank topRankDefault; + + + private long lastSeenDate; + + private long lastUpdateDate; + + + public TopNStatsData() { + super(); + + } + + public String getPlayerUuid() { + return playerUuid; + } + public void setPlayerUuid( String playerUuid ) { + this.playerUuid = playerUuid; + } + + public String getPlayerName() { + return playerName; + } + public void setPlayerName( String playerName ) { + this.playerName = playerName; + } + + public long getTotalBlocks() { + return totalBlocks; + } + public void setTotalBlocks( long totalBlocks ) { + this.totalBlocks = totalBlocks; + } + + public long getCurrentTokens() { + return currentTokens; + } + public void setCurrentTokens( long currentTokens ) { + this.currentTokens = currentTokens; + } + + public double getCurrentBalance() { + return currentBalance; + } + public void setCurrentBalance( double currentBalance ) { + this.currentBalance = currentBalance; + } + + public String getTopRankPrestigesName() { + return topRankPrestigesName; + } + public void setTopRankPrestigesName( String topRankPrestigesName ) { + this.topRankPrestigesName = topRankPrestigesName; + } + + public String getTopRankDefaultName() { + return topRankDefaultName; + } + public void setTopRankDefaultName( String topRankDefaultName ) { + this.topRankDefaultName = topRankDefaultName; + } + + public Rank getTopRankPrestiges() { + return topRankPrestiges; + } + public void setTopRankPrestiges( Rank topRankPrestiges ) { + this.topRankPrestiges = topRankPrestiges; + } + + public Rank getTopRankDefault() { + return topRankDefault; + } + public void setTopRankDefault( Rank topRankDefault ) { + this.topRankDefault = topRankDefault; + } + + public long getLastSeenDate() { + return lastSeenDate; + } + public void setLastSeenDate( long lastSeenDate ) { + this.lastSeenDate = lastSeenDate; + } + + public long getLastUpdateDate() { + return lastUpdateDate; + } + public void setLastUpdateDate( long lastUpdateDate ) { + this.lastUpdateDate = lastUpdateDate; + } + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/cache/TopNTokensComparator.java b/prison-core/src/main/java/tech/mcprison/prison/cache/TopNTokensComparator.java new file mode 100644 index 000000000..172e9f198 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/cache/TopNTokensComparator.java @@ -0,0 +1,13 @@ +package tech.mcprison.prison.cache; + +import java.util.Comparator; + +public class TopNTokensComparator + implements Comparator +{ + + @Override + public int compare( TopNStatsData o1, TopNStatsData o2 ) { + return Long.compare( o1.getCurrentTokens(), o2.getCurrentTokens() ); + } +} From 5c17fc6a5dec062df1cceb13dc634156556cf9ed Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 12 Dec 2021 02:33:37 -0500 Subject: [PATCH 206/283] Bug fix: Rankup on a ladder in which there is not already a rank was producing an error. Similar to prior problem... just did not fix it correctly for all situations. --- docs/changelog_v3.3.x.md | 6 +++++- .../prison/ranks/commands/RankUpCommand.java | 17 +++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index cee6b23e0..a278f668d 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,11 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.11 2021-12-11 +# 3.2.11-alpha.11 2021-12-12 + + +* **Bug fix: Rankup on a ladder in which there is not already a rank was producing an error.** +Similar to prior problem... just did not fix it correctly for all situations. * **Start building the structure for the Top N rankings.** diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RankUpCommand.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RankUpCommand.java index 52babb1d5..aabc18599 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RankUpCommand.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RankUpCommand.java @@ -164,11 +164,20 @@ private void rankUpPrivate(CommandSender sender, String ladder, RankupModes mode RankPlayer rankPlayer = getRankPlayer( sender, player.getUUID(), player.getName() ); PlayerRank playerRankCurrent = rankPlayerFactory.getRank( rankPlayer, ladder ); - Rank targetRank = playerRankCurrent == null ? targetLadder.getLowestRank().get() : - playerRankCurrent.getRank(); + PlayerRank playerRankTarget = null; + + // If the player does not have a rank on the current ladder, then assign the + // default rank for the ladder to be their next rank. + if ( playerRankCurrent == null ) { + + playerRankTarget = rankPlayerFactory.createPlayerRank( + targetLadder.getLowestRank().get() ); + } + else { + playerRankTarget = playerRankCurrent.getTargetPlayerRankForPlayer( rankPlayer, + playerRankCurrent.getRank() ); + } - PlayerRank playerRankTarget = - playerRankCurrent.getTargetPlayerRankForPlayer( rankPlayer, targetRank ); Output.get().logDebug( DebugTarget.rankup, From b42677d0bff051542367d854a6d56cf4e56927a0 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 12 Dec 2021 02:34:43 -0500 Subject: [PATCH 207/283] Some adjustments to admin token functions. --- docs/changelog_v3.3.x.md | 3 +++ .../tech/mcprison/prison/PrisonCommand.java | 25 ++++++++++++------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index a278f668d..7be0f54e2 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.11 2021-12-12 +* **Some adjustments to admin token functions.** + + * **Bug fix: Rankup on a ladder in which there is not already a rank was producing an error.** Similar to prior problem... just did not fix it correctly for all situations. diff --git a/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java b/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java index 2eb0e9039..1de51f158 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java +++ b/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java @@ -1551,7 +1551,7 @@ public void supportListenersDump(CommandSender sender, @Command(identifier = "prison tokens balance", description = "Prison tokens: a player's current balance.", - aliases = "bal", + aliases = "tokens bal", permissions = "tokens.bal", altPermissions = "tokens.bal.others" ) public void tokensBalance(CommandSender sender, @@ -1572,9 +1572,10 @@ public void tokensBalance(CommandSender sender, Output.get().logWarn( message ); return; } - else { + else + if ( playerName != null && !playerName.isEmpty() ){ - if ( playerName != null && !sender.isOp() && + if ( !sender.isOp() && !sender.hasPermission( "tokens.bal.others" ) ) { String message = "Prison Tokens: You do not have permission to view other " + "player's balances."; @@ -1582,7 +1583,11 @@ public void tokensBalance(CommandSender sender, return; } - player = getPlayer( playerName ); + Player tempPlayer = getPlayer( playerName ); + + if ( tempPlayer != null ) { + player = tempPlayer; + } } @@ -1590,9 +1595,11 @@ public void tokensBalance(CommandSender sender, DecimalFormat dFmt = new DecimalFormat("#,##0"); - String tokens = dFmt.format( player.getPlayerCachePlayerData().getTokens() ); + long tokens = player.getPlayerCachePlayerData().getTokens(); + + String tokensMsg = dFmt.format( tokens ); - String message = String.format( "&3%s has %s tokens.", player.getName(), tokens ); + String message = String.format( "&3%s has %s tokens.", player.getName(), tokensMsg ); sender.sendMessage( message ); } @@ -1642,7 +1649,7 @@ public void tokensAdd( CommandSender sender, sender.sendMessage( message ); // The player getting the tokens, if they are online: - if ( player.isOnline() ) { + if ( player.isOnline() && !player.getName().equalsIgnoreCase( sender.getName() ) ) { player.sendMessage( message ); } @@ -1696,7 +1703,7 @@ public void tokensRemove( CommandSender sender, sender.sendMessage( message ); // The player getting the tokens, if they are online: - if ( player.isOnline() ) { + if ( player.isOnline() && !player.getName().equalsIgnoreCase( sender.getName() ) ) { player.sendMessage( message ); } @@ -1745,7 +1752,7 @@ public void tokensSet( CommandSender sender, sender.sendMessage( message ); // The player getting the tokens, if they are online: - if ( player.isOnline() ) { + if ( player.isOnline() && !player.getName().equalsIgnoreCase( sender.getName() ) ) { player.sendMessage( message ); } From e0149ff24918e8f85ab806aac3ada9644384f3c1 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Sun, 12 Dec 2021 23:44:00 -0500 Subject: [PATCH 208/283] Update docs. --- ...son_docs_101_auto_configure_log_example.md | 176 +++++++++++++++++- 1 file changed, 174 insertions(+), 2 deletions(-) diff --git a/docs/prison_docs_101_auto_configure_log_example.md b/docs/prison_docs_101_auto_configure_log_example.md index eed920298..cecc7c657 100644 --- a/docs/prison_docs_101_auto_configure_log_example.md +++ b/docs/prison_docs_101_auto_configure_log_example.md @@ -8,6 +8,8 @@ This document provides information on what log entries are generated when prison NOTE: Prison has been designed to behave the same under any version of bukkit/Spigot from 1.8 through 1.18. Therefore the spigot version in these logs are not important, and apply to all versions. The same applies for Java versions 1.8.x through Java 17. +*Documented updated: 2021-12-11* +
# Prison logs when starting for the first time @@ -146,7 +148,6 @@ When Prison detects that it has not ran on the server before, it will display th ``` - [13:14:55 INFO]: | Prison | ----- < Setting up a new Prison Server > -------- (3.2.11-alpha.11) [13:14:55 INFO]: | Prison | Welcome to Prison! [13:14:55 INFO]: | Prison | @@ -168,9 +169,180 @@ When Prison detects that it has not ran on the server before, it will display th [13:14:55 INFO]: | Prison | [13:14:55 INFO]: | Prison | > -``` + +``` + +
+ + +# Running command: /ranks autoConfigure help + + +``` +>ranks autoConfigure help +[13:31:26 INFO]: ------- < Cmd: /ranks autoConfigure > --------- (3.2.11-alpha.11) +[13:31:26 INFO]: Auto configures Ranks and Mines using single letters A through Z for both the rank and mine names. Both ranks and mines are generated, they will also be linked together automatically. To set the starting price use price=x. To set multiplier mult=x. AutoConfigure will try to merge any preexsiting ranks and mines, but you must use the 'force' keyword in 'options'. Force will replace all blocks in preexisting mines. To keep preexisting blocks, use 'forceKeepBlocks' with the 'force' option. Default values [full price=50000 mult=1.5] +[13:31:26 INFO]: /ranks autoConfigure [options] +[13:31:26 INFO]: [options | full] Options: [full ranks mines price=x mult=x force forceKeepBlocks dontForceLinerWalls dontForceLinerBottoms] +[13:31:26 INFO]: Permissions: +[13:31:26 INFO]: ranks.set +[13:31:26 INFO]: Aliases: +[13:31:26 INFO]: [prison autoConfigure] +> +``` +
+# Running command: /ranks autoConfigure + + +``` +>ranks autoConfigure +[13:33:38 INFO]: Your new rank, 'A', was created in the ladder 'default', using the tag value of '[A]' +[13:33:38 INFO]: Virtual mine created: use command '/mines set area help' set an area within a world to enable as a normal mine. +[13:33:38 INFO]: Your new rank, 'B', was created in the ladder 'default', using the tag value of '[B]' +[13:33:38 INFO]: Virtual mine created: use command '/mines set area help' set an area within a world to enable as a normal mine. +[13:33:38 INFO]: Your new rank, 'C', was created in the ladder 'default', using the tag value of '[C]' +[13:33:38 INFO]: Virtual mine created: use command '/mines set area help' set an area within a world to enable as a normal mine. +[13:33:38 INFO]: Your new rank, 'D', was created in the ladder 'default', using the tag value of '[D]' +[13:33:38 INFO]: Virtual mine created: use command '/mines set area help' set an area within a world to enable as a normal mine. +[13:33:38 INFO]: Your new rank, 'E', was created in the ladder 'default', using the tag value of '[E]' +[13:33:38 INFO]: Virtual mine created: use command '/mines set area help' set an area within a world to enable as a normal mine. +[13:33:38 INFO]: Your new rank, 'F', was created in the ladder 'default', using the tag value of '[F]' +[13:33:38 INFO]: Virtual mine created: use command '/mines set area help' set an area within a world to enable as a normal mine. +[13:33:38 INFO]: Your new rank, 'G', was created in the ladder 'default', using the tag value of '[G]' +[13:33:38 INFO]: Virtual mine created: use command '/mines set area help' set an area within a world to enable as a normal mine. +[13:33:38 INFO]: Your new rank, 'H', was created in the ladder 'default', using the tag value of '[H]' +[13:33:38 INFO]: Virtual mine created: use command '/mines set area help' set an area within a world to enable as a normal mine. +[13:33:38 INFO]: Your new rank, 'I', was created in the ladder 'default', using the tag value of '[I]' +[13:33:38 INFO]: Virtual mine created: use command '/mines set area help' set an area within a world to enable as a normal mine. +[13:33:38 INFO]: Your new rank, 'J', was created in the ladder 'default', using the tag value of '[J]' +[13:33:38 INFO]: Virtual mine created: use command '/mines set area help' set an area within a world to enable as a normal mine. +[13:33:38 INFO]: Your new rank, 'K', was created in the ladder 'default', using the tag value of '[K]' +[13:33:38 INFO]: Virtual mine created: use command '/mines set area help' set an area within a world to enable as a normal mine. +[13:33:38 INFO]: Your new rank, 'L', was created in the ladder 'default', using the tag value of '[L]' +[13:33:38 INFO]: Virtual mine created: use command '/mines set area help' set an area within a world to enable as a normal mine. +[13:33:38 INFO]: Your new rank, 'M', was created in the ladder 'default', using the tag value of '[M]' +[13:33:39 INFO]: Virtual mine created: use command '/mines set area help' set an area within a world to enable as a normal mine. +[13:33:39 INFO]: Your new rank, 'N', was created in the ladder 'default', using the tag value of '[N]' +[13:33:39 INFO]: Virtual mine created: use command '/mines set area help' set an area within a world to enable as a normal mine. +[13:33:39 INFO]: Your new rank, 'O', was created in the ladder 'default', using the tag value of '[O]' +[13:33:39 INFO]: Virtual mine created: use command '/mines set area help' set an area within a world to enable as a normal mine. +[13:33:39 INFO]: Your new rank, 'P', was created in the ladder 'default', using the tag value of '[P]' +[13:33:39 INFO]: Virtual mine created: use command '/mines set area help' set an area within a world to enable as a normal mine. +[13:33:39 INFO]: Your new rank, 'Q', was created in the ladder 'default', using the tag value of '[Q]' +[13:33:39 INFO]: Virtual mine created: use command '/mines set area help' set an area within a world to enable as a normal mine. +[13:33:39 INFO]: Your new rank, 'R', was created in the ladder 'default', using the tag value of '[R]' +[13:33:39 INFO]: Virtual mine created: use command '/mines set area help' set an area within a world to enable as a normal mine. +[13:33:39 INFO]: Your new rank, 'S', was created in the ladder 'default', using the tag value of '[S]' +[13:33:39 INFO]: Virtual mine created: use command '/mines set area help' set an area within a world to enable as a normal mine. +[13:33:39 INFO]: Your new rank, 'T', was created in the ladder 'default', using the tag value of '[T]' +[13:33:39 INFO]: Virtual mine created: use command '/mines set area help' set an area within a world to enable as a normal mine. +[13:33:39 INFO]: Your new rank, 'U', was created in the ladder 'default', using the tag value of '[U]' +[13:33:39 INFO]: Virtual mine created: use command '/mines set area help' set an area within a world to enable as a normal mine. +[13:33:39 INFO]: Your new rank, 'V', was created in the ladder 'default', using the tag value of '[V]' +[13:33:39 INFO]: Virtual mine created: use command '/mines set area help' set an area within a world to enable as a normal mine. +[13:33:39 INFO]: Your new rank, 'W', was created in the ladder 'default', using the tag value of '[W]' +[13:33:39 INFO]: Virtual mine created: use command '/mines set area help' set an area within a world to enable as a normal mine. +[13:33:39 INFO]: Your new rank, 'X', was created in the ladder 'default', using the tag value of '[X]' +[13:33:39 INFO]: Virtual mine created: use command '/mines set area help' set an area within a world to enable as a normal mine. +[13:33:39 INFO]: Your new rank, 'Y', was created in the ladder 'default', using the tag value of '[Y]' +[13:33:39 INFO]: Virtual mine created: use command '/mines set area help' set an area within a world to enable as a normal mine. +[13:33:39 INFO]: Your new rank, 'Z', was created in the ladder 'default', using the tag value of '[Z]' +[13:33:39 INFO]: Virtual mine created: use command '/mines set area help' set an area within a world to enable as a normal mine. +[13:33:39 INFO]: Your new rank, 'P1', was created in the ladder 'prestiges', using the tag value of '[+]' +[13:33:39 INFO]: Your new rank, 'P2', was created in the ladder 'prestiges', using the tag value of '[+2]' +[13:33:39 INFO]: Your new rank, 'P3', was created in the ladder 'prestiges', using the tag value of '[+3]' +[13:33:39 INFO]: Your new rank, 'P4', was created in the ladder 'prestiges', using the tag value of '[+4]' +[13:33:39 INFO]: Your new rank, 'P5', was created in the ladder 'prestiges', using the tag value of '[+5]' +[13:33:39 INFO]: Your new rank, 'P6', was created in the ladder 'prestiges', using the tag value of '[+6]' +[13:33:39 INFO]: Your new rank, 'P7', was created in the ladder 'prestiges', using the tag value of '[+7]' +[13:33:39 INFO]: Your new rank, 'P8', was created in the ladder 'prestiges', using the tag value of '[+8]' +[13:33:39 INFO]: Your new rank, 'P9', was created in the ladder 'prestiges', using the tag value of '[+9]' +[13:33:39 INFO]: Your new rank, 'P10', was created in the ladder 'prestiges', using the tag value of '[+10]' +[13:33:40 INFO]: | Prison | Mine A: [minecraft: andesite 5.0, minecraft: cobblestone 95.0] +[13:33:40 INFO]: | Prison | Mine B: [minecraft: diorite 5.0, minecraft: andesite 10.0, minecraft: cobblestone 85.0] +[13:33:40 INFO]: | Prison | Mine C: [minecraft: coal_ore 5.0, minecraft: diorite 10.0, minecraft: andesite 20.0, minecraft: cobblestone 65.0] +[13:33:40 INFO]: | Prison | Mine D: [minecraft: granite 5.0, minecraft: coal_ore 10.0, minecraft: diorite 20.0, minecraft: andesite 20.0, minecraft: cobblestone 45.0] +[13:33:40 INFO]: | Prison | Mine E: [minecraft: stone 5.0, minecraft: granite 10.0, minecraft: coal_ore 20.0, minecraft: diorite 20.0, minecraft: andesite 20.0, minecraft: cobblestone 25.0] +[13:33:40 INFO]: | Prison | Mine F: [minecraft: iron_ore 5.0, minecraft: stone 10.0, minecraft: granite 20.0, minecraft: coal_ore 20.0, minecraft: diorite 20.0, minecraft: andesite 25.0] +[13:33:40 INFO]: | Prison | Mine G: [minecraft: polished_andesite 5.0, minecraft: iron_ore 10.0, minecraft: stone 20.0, minecraft: granite 20.0, minecraft: coal_ore 20.0, minecraft: diorite 25.0] +[13:33:40 INFO]: | Prison | Mine H: [minecraft: gold_ore 5.0, minecraft: polished_andesite 10.0, minecraft: iron_ore 20.0, minecraft: stone 20.0, minecraft: granite 20.0, minecraft: coal_ore 25.0] +[13:33:40 INFO]: | Prison | Mine I: [minecraft: mossy_cobblestone 5.0, minecraft: gold_ore 10.0, minecraft: polished_andesite 20.0, minecraft: iron_ore 20.0, minecraft: stone 20.0, minecraft: granite 25.0] +[13:33:40 INFO]: | Prison | Mine J: [minecraft: coal_block 5.0, minecraft: mossy_cobblestone 10.0, minecraft: gold_ore 20.0, minecraft: polished_andesite 20.0, minecraft: iron_ore 20.0, minecraft: stone 25.0] +[13:33:40 INFO]: | Prison | Mine K: [minecraft: nether_quartz_ore 5.0, minecraft: coal_block 10.0, minecraft: mossy_cobblestone 20.0, minecraft: gold_ore 20.0, minecraft: polished_andesite 20.0, minecraft: iron_ore 25.0] +[13:33:40 INFO]: | Prison | Mine L: [minecraft: lapis_ore 5.0, minecraft: nether_quartz_ore 10.0, minecraft: coal_block 20.0, minecraft: mossy_cobblestone 20.0, minecraft: gold_ore 20.0, minecraft: polished_andesite 25.0] +[13:33:40 INFO]: | Prison | Mine M: [minecraft: end_stone 5.0, minecraft: lapis_ore 10.0, minecraft: nether_quartz_ore 20.0, minecraft: coal_block 20.0, minecraft: mossy_cobblestone 20.0, minecraft: gold_ore 25.0] +[13:33:40 INFO]: | Prison | Mine N: [minecraft: iron_block 5.0, minecraft: end_stone 10.0, minecraft: lapis_ore 20.0, minecraft: nether_quartz_ore 20.0, minecraft: coal_block 20.0, minecraft: mossy_cobblestone 25.0] +[13:33:40 INFO]: | Prison | Mine O: [minecraft: redstone_ore 5.0, minecraft: iron_block 10.0, minecraft: end_stone 20.0, minecraft: lapis_ore 20.0, minecraft: nether_quartz_ore 20.0, minecraft: coal_block 25.0] +[13:33:40 INFO]: | Prison | Mine P: [minecraft: diamond_ore 5.0, minecraft: redstone_ore 10.0, minecraft: iron_block 20.0, minecraft: end_stone 20.0, minecraft: lapis_ore 20.0, minecraft: nether_quartz_ore 25.0] +[13:33:40 INFO]: | Prison | Mine Q: [minecraft: quartz_block 5.0, minecraft: diamond_ore 10.0, minecraft: redstone_ore 20.0, minecraft: iron_block 20.0, minecraft: end_stone 20.0, minecraft: lapis_ore 25.0] +[13:33:40 INFO]: | Prison | Mine R: [minecraft: emerald_ore 5.0, minecraft: quartz_block 10.0, minecraft: diamond_ore 20.0, minecraft: redstone_ore 20.0, minecraft: iron_block 20.0, minecraft: end_stone 25.0] +[13:33:40 INFO]: | Prison | Mine S: [minecraft: gold_block 5.0, minecraft: emerald_ore 10.0, minecraft: quartz_block 20.0, minecraft: diamond_ore 20.0, minecraft: redstone_ore 20.0, minecraft: iron_block 25.0] +[13:33:40 INFO]: | Prison | Mine T: [minecraft: prismarine 5.0, minecraft: gold_block 10.0, minecraft: emerald_ore 20.0, minecraft: quartz_block 20.0, minecraft: diamond_ore 20.0, minecraft: redstone_ore 25.0] +[13:33:40 INFO]: | Prison | Mine U: [minecraft: lapis_block 5.0, minecraft: prismarine 10.0, minecraft: gold_block 20.0, minecraft: emerald_ore 20.0, minecraft: quartz_block 20.0, minecraft: diamond_ore 25.0] +[13:33:40 INFO]: | Prison | Mine V: [minecraft: redstone_block 5.0, minecraft: lapis_block 10.0, minecraft: prismarine 20.0, minecraft: gold_block 20.0, minecraft: emerald_ore 20.0, minecraft: quartz_block 25.0] +[13:33:40 INFO]: | Prison | Mine W: [minecraft: obsidian 5.0, minecraft: redstone_block 10.0, minecraft: lapis_block 20.0, minecraft: prismarine 20.0, minecraft: gold_block 20.0, minecraft: emerald_ore 25.0] +[13:33:40 INFO]: | Prison | Mine X: [minecraft: diamond_block 5.0, minecraft: obsidian 10.0, minecraft: redstone_block 20.0, minecraft: lapis_block 20.0, minecraft: prismarine 20.0, minecraft: gold_block 25.0] +[13:33:40 INFO]: | Prison | Mine Y: [minecraft: dark_prismarine 5.0, minecraft: diamond_block 10.0, minecraft: obsidian 20.0, minecraft: redstone_block 20.0, minecraft: lapis_block 20.0, minecraft: prismarine 25.0] +[13:33:40 INFO]: | Prison | Mine Z: [minecraft: emerald_block 5.0, minecraft: dark_prismarine 10.0, minecraft: diamond_block 20.0, minecraft: obsidian 20.0, minecraft: redstone_block 20.0, minecraft: lapis_block 25.0] +[13:33:40 INFO]: | Prison | Mine Liner status: A (Created) : walls:bricked:forced,bottom:bedrock:forced,ladderType:normal +[13:33:41 INFO]: | Prison | Mine Liner status: B (Created) : walls:darkForest:forced,bottom:glowstone:forced,ladderType:normal +[13:33:41 INFO]: | Prison | Mine Liner status: C (Created) : walls:blackAndWhite:forced,bottom:glowingPlanks:forced,ladderType:normal +[13:33:41 INFO]: | Prison | Mine Liner status: D (Created) : walls:glowstone:forced,bottom:bedrock:forced,ladderType:normal +[13:33:41 INFO]: | Prison | Mine Liner status: E (Created) : walls:obby:forced,bottom:glowstone:forced,ladderType:normal +[13:33:41 INFO]: | Prison | Mine Liner status: F (Created) : walls:bricked:forced,bottom:bright:forced,ladderType:normal +[13:33:41 INFO]: | Prison | Mine Liner status: G (Created) : walls:darkForest:forced,bottom:glowingPlanks:forced,ladderType:normal +[13:33:41 INFO]: | Prison | Mine Liner status: H (Created) : walls:bedrock:forced,bottom:beacon:forced,ladderType:normal +[13:33:41 INFO]: | Prison | Mine Liner status: I (Created) : walls:beacon:forced,bottom:glowstone:forced,ladderType:normal +[13:33:41 INFO]: | Prison | Mine Liner status: J (Created) : walls:seaEchos:forced,bottom:bricked:forced,ladderType:normal +[13:33:41 INFO]: | Prison | Mine Liner status: K (Created) : walls:blackAndWhite:forced,bottom:glowingPlanks:forced,ladderType:normal +[13:33:41 INFO]: | Prison | Mine Liner status: L (Created) : walls:bricked:forced,bottom:bricked:forced,ladderType:normal +[13:33:41 INFO]: | Prison | Mine Liner status: M (Created) : walls:glowingPlanks:forced,bottom:glowingPlanks:forced,ladderType:normal +[13:33:41 INFO]: | Prison | Mine Liner status: N (Created) : walls:beacon:forced,bottom:blackAndWhite:forced,ladderType:normal +[13:33:41 INFO]: | Prison | Mine Liner status: O (Created) : walls:darkOakPrismarine:forced,bottom:glowstone:forced,ladderType:normal +[13:33:41 INFO]: | Prison | Mine Liner status: P (Created) : walls:bricked:forced,bottom:glowingPlanks:forced,ladderType:normal +[13:33:41 INFO]: | Prison | Mine Liner status: Q (Created) : walls:bright:forced,bottom:beacon:forced,ladderType:normal +[13:33:41 INFO]: | Prison | Mine Liner status: R (Created) : walls:glowstone:forced,bottom:obby:forced,ladderType:normal +[13:33:41 INFO]: | Prison | Mine Liner status: S (Created) : walls:darkForest:forced,bottom:darkOakPrismarine:forced,ladderType:normal +[13:33:41 INFO]: | Prison | Mine Liner status: T (Created) : walls:obby:forced,bottom:glowingPlanks:forced,ladderType:normal +[13:33:41 INFO]: | Prison | Mine Liner status: U (Created) : walls:bricked:forced,bottom:obby:forced,ladderType:normal +[13:33:41 INFO]: | Prison | Mine Liner status: V (Created) : walls:beacon:forced,bottom:darkForest:forced,ladderType:normal +[13:33:41 INFO]: | Prison | Mine Liner status: W (Created) : walls:bricked:forced,bottom:obby:forced,ladderType:normal +[13:33:41 INFO]: | Prison | Mine Liner status: X (Created) : walls:darkOakPrismarine:forced,bottom:beacon:forced,ladderType:normal +[13:33:41 INFO]: | Prison | Mine Liner status: Y (Created) : walls:darkOakPrismarine:forced,bottom:seaEchos:forced,ladderType:normal +[13:33:41 INFO]: | Prison | Mine Liner status: Z (Created) : walls:white:forced,bottom:darkForest:forced,ladderType:normal +[13:33:41 INFO]: The 'prestiges' ladder has been enabled to apply a Base Rank Cost Multiplier of 0.1000 that will be applied to 'all' rank costs. This multiplier will be increased with each rank on the ladder. +[13:33:41 INFO]: The Base Rank Cost Multiplier can be adjusted, or disabled, with the command: '/ranks ladder rankCostMultiplier +[13:33:41 INFO]: Ranks autoConfigure: 26 ranks were created. +[13:33:41 INFO]: Ranks autoConfigure: No rank commands were created. +[13:33:41 INFO]: | Prison | Total placeholders generated: 1419 +[13:33:41 INFO]: | Prison | PLAYER: 102 +[13:33:41 INFO]: | Prison | LADDERS: 64 +[13:33:41 INFO]: | Prison | MINES: 832 +[13:33:41 INFO]: | Prison | MINEPLAYERS: 57 +[13:33:41 INFO]: | Prison | STATSMINES: 364 +[13:33:41 INFO]: | Prison | ALIAS: 697 +[13:33:41 INFO]: | Prison | Total placeholders available to be Registered: 1419 +[13:33:41 INFO]: | Prison | AutoManagerEventsManager: unregistered a total of 2 event listeners. +[13:33:41 INFO]: | Prison | AutoManager: Trying to register BlockBreakEvent +[13:33:41 INFO]: | Prison | Welcome! RoyalBlueRanger just joined the server and was assigned the default ranks. +[13:33:41 INFO]: | Prison | Welcome! Myrqua just joined the server and was assigned the default ranks. +[13:33:41 INFO]: | Prison | Welcome! RoyalCoffeeBeans just joined the server and was assigned the default ranks. +[13:33:41 INFO]: Ranks autoConfigure: 26 mines were created. +[13:33:41 INFO]: Ranks autoConfigure: 26 ranks and mines were linked. +[13:33:41 INFO]: Created 10 prestige ranks (temp message). +[13:33:41 INFO]: | Prison | +> + + +``` + +
+ + + + From 4f1735fbf460659c9e49f4e28e2a4bb3526f4349 Mon Sep 17 00:00:00 2001 From: AnonymousGCA Date: Wed, 15 Dec 2021 00:22:25 +0100 Subject: [PATCH 209/283] Changelogs: - You can't accidentally open the Ranks GUI if there're too many ranks which the GUI can't show. --- docs/changelog_v3.3.x.md | 3 +++ .../prison/spigot/gui/rank/SpigotPlayerRanksGUI.java | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 7be0f54e2..9d584ec2a 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.11 2021-12-12 +* **Ranks GUI Error.** Fixed an error with Ranks GUI. + + * **Some adjustments to admin token functions.** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerRanksGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerRanksGUI.java index 63d481874..f22583ffc 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerRanksGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerRanksGUI.java @@ -125,6 +125,11 @@ public void open() { // Create the inventory and set up the owner, dimensions or number of slots, and title int dimension = (int) (Math.ceil(ladder.getRanks().size() / 9D) * 9) + 9; + if (dimension > 54){ + Output.get().sendWarn(new SpigotPlayer(getPlayer()), messages.getString(MessagesConfig.StringID.spigot_message_gui_ranks_too_many)); + return; + } + // Get many parameters RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); Rank rank = ladder.getLowestRank().get(); From 7ed0feec0147eb7bf1fb80a69c441abc22f3928b Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Wed, 15 Dec 2021 04:04:39 -0500 Subject: [PATCH 210/283] Prison tokens: Add a few more prison tokens placeholders. Fixed the admin token commands to use longs and not integers. --- docs/changelog_v3.3.x.md | 8 +++- .../tech/mcprison/prison/PrisonCommand.java | 6 +-- .../placeholders/PlaceholderManager.java | 4 ++ .../prison/ranks/managers/PlayerManager.java | 47 ++++++++++++++++--- 4 files changed, 53 insertions(+), 12 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 9d584ec2a..fb37760d9 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,10 +13,14 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.11 2021-12-12 +# 3.2.11-alpha.11 2021-12-15 -* **Ranks GUI Error.** Fixed an error with Ranks GUI. +**Prison tokens: Add a few more prison tokens placeholders.** +Fixed the admin token commands to use longs and not integers. + + +* **Ranks GUI Error.** ~~Fixed an error with Ranks GUI.~~ This did not fix anything. * **Some adjustments to admin token functions.** diff --git a/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java b/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java index 1de51f158..0f2dd28bc 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java +++ b/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java @@ -1612,7 +1612,7 @@ public void tokensAdd( CommandSender sender, description = "Player to add the tokens to.") String playerName, @Arg(name = "amount", verifiers = "min[1]", - description = "The number of tokens to add to the player's account.") int amount + description = "The number of tokens to add to the player's account.") long amount ) { if ( playerName == null || playerName.isEmpty() ) { @@ -1666,7 +1666,7 @@ public void tokensRemove( CommandSender sender, @Arg(name = "amount", verifiers = "min[1]", description = "The number of tokens to remove from the player's account. " + - "This amount must be positive. ") int amount + "This amount must be positive. ") long amount ) { if ( playerName == null || playerName.isEmpty() ) { @@ -1721,7 +1721,7 @@ public void tokensSet( CommandSender sender, @Arg(name = "amount", description = "The number of tokens to set the player's account to. " + - "This amount must amount can be negative. ") int amount + "This amount must amount can be negative. ") long amount ) { if ( playerName == null || playerName.isEmpty() ) { diff --git a/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderManager.java b/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderManager.java index be4869909..0f1fb2e82 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderManager.java +++ b/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderManager.java @@ -260,8 +260,12 @@ public enum PrisonPlaceHolders { prison_ptb(PlaceholderFlags.PLAYER, PlaceholderFlags.ALIAS), prison_ptbf(PlaceholderFlags.PLAYER, PlaceholderFlags.ALIAS), + prison_ptbfm(PlaceholderFlags.PLAYER, PlaceholderFlags.ALIAS), + prison_ptbfk(PlaceholderFlags.PLAYER, PlaceholderFlags.ALIAS), prison_player_token_balance(prison_ptb, PlaceholderFlags.PLAYER), prison_player_token_balance_formatted(prison_ptbf, PlaceholderFlags.PLAYER), + prison_player_token_balance_formatted_metric(prison_ptbfm, PlaceholderFlags.PLAYER), + prison_player_token_balance_formatted_kmbt(prison_ptbfk, PlaceholderFlags.PLAYER), prison_ptb_epm(PlaceholderFlags.PLAYER, PlaceholderFlags.ALIAS), prison_ptb_epmf(PlaceholderFlags.PLAYER, PlaceholderFlags.ALIAS), diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/PlayerManager.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/PlayerManager.java index fca6337f0..018e56b40 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/PlayerManager.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/PlayerManager.java @@ -1025,7 +1025,7 @@ else if ( formatted ) { private String getPlayerTokenBalance( RankPlayer rankPlayer, - boolean formatted, PlaceholderAttribute attribute ) { + int formatMode, PlaceholderAttribute attribute ) { StringBuilder sb = new StringBuilder(); DecimalFormat dFmt = new DecimalFormat("#,##0"); @@ -1038,12 +1038,35 @@ private String getPlayerTokenBalance( RankPlayer rankPlayer, sb.append( attributeNF.format( tokens ) ); } - else if ( formatted ) { - sb.append( PlaceholdersUtil.formattedMetricSISize( tokens )); - } else { - sb.append( dFmt.format( tokens )); + switch ( formatMode ) + { + case 1: { + sb.append( dFmt.format( tokens )); + + break; + } + case 2: { + sb.append( PlaceholdersUtil.formattedMetricSISize( tokens )); + + break; + } + case 3: { + sb.append( PlaceholdersUtil.formattedKmbtSISize( tokens, dFmt, " " )); + + break; + } + default: + sb.append( Long.toString( tokens )); + } } + +// if ( formatted ) { +// sb.append( PlaceholdersUtil.formattedMetricSISize( tokens )); +// } +// else { +// sb.append( dFmt.format( tokens )); +// } return sb.toString(); } @@ -1453,14 +1476,24 @@ public String getTranslatePlayerPlaceHolder( UUID playerUuid, String playerName, case prison_ptb: case prison_player_token_balance: - results = getPlayerTokenBalance( rankPlayer, false, attribute ); + results = getPlayerTokenBalance( rankPlayer, 0, attribute ); break; case prison_ptbf: case prison_player_token_balance_formatted: - results = getPlayerTokenBalance( rankPlayer, true, attribute ); + results = getPlayerTokenBalance( rankPlayer, 1, attribute ); break; + case prison_ptbfm: + case prison_player_token_balance_formatted_metric: + results = getPlayerTokenBalance( rankPlayer, 2, attribute ); + break; + + case prison_ptbfk: + case prison_player_token_balance_formatted_kmbt: + results = getPlayerTokenBalance( rankPlayer, 3, attribute ); + break; + case prison_ptb_epm: case prison_player_token_balance_earnings_per_minute: From e78f6b00422f1bb43eaf18a8354ad2a3fde3b6d9 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Wed, 15 Dec 2021 04:05:38 -0500 Subject: [PATCH 211/283] Update XSeries to v8.5.0.1 to better support spigot 1.18. --- docs/changelog_v3.3.x.md | 3 +++ prison-spigot/build.gradle | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index fb37760d9..039bae2df 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.11 2021-12-15 +* **Update XSeries to v8.5.0.1 to better support spigot 1.18.** + + **Prison tokens: Add a few more prison tokens placeholders.** Fixed the admin token commands to use longs and not integers. diff --git a/prison-spigot/build.gradle b/prison-spigot/build.gradle index 72a955d71..733da3809 100644 --- a/prison-spigot/build.gradle +++ b/prison-spigot/build.gradle @@ -105,7 +105,7 @@ dependencies { // implementation 'com.github.cryptomorin:xseries:b95d195482' // https://mvnrepository.com/artifact/com.github.cryptomorin/XSeries - implementation 'com.github.cryptomorin:XSeries:8.5.0' + implementation 'com.github.cryptomorin:XSeries:8.5.0.1' @@ -187,7 +187,7 @@ shadowJar { include(dependency('me.clip:placeholderapi:2.10.9')) - include(dependency('com.github.cryptomorin:XSeries:8.5.0')) + include(dependency('com.github.cryptomorin:XSeries:8.5.0.1')) //include(dependency('org.inventivetalent.spiget-update:bukkit:1.4.2-SNAPSHOT')) //include(dependency('me.badbones69:crazyenchantments-plugin:1.8-Dev-Build-v8')) From 67472f508d1fbda6d641e7329b4fa744a397489e Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Wed, 15 Dec 2021 04:12:09 -0500 Subject: [PATCH 212/283] Bug fix: Fixed an incorrect use of XMaterial which prevented it from working properly with spigot 1.8 through 1.12. It was using XMaterial to get the Material value, which is wrong, since it's the item stack that contains the varients of the materials. So the change is to extract the item stack directly from XMaterial which solves the problem. Also there was another error where if amounts are greater than 64, setting them to 1 so the GUI will still work, but it will suppress the incorrect counts for the itemstack. --- docs/changelog_v3.3.x.md | 5 +++++ .../prison/spigot/gui/guiutility/Button.java | 15 ++++++++++++--- .../gui/guiutility/SpigotGUIComponents.java | 7 ++++++- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 039bae2df..69a7f975c 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,11 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.11 2021-12-15 +* **Bug fix: Fixed an incorrect use of XMaterial which prevented it from working properly with spigot 1.8 through 1.12.** +It was using XMaterial to get the Material value, which is wrong, since it's the item stack that contains the variants of the materials. So the change is to extract the item stack directly from XMaterial which solves the problem. +Also there was another error where if amounts are greater than 64, setting them to 1 so the GUI will still work, but it will suppress the incorrect counts for the itemstack. + + * **Update XSeries to v8.5.0.1 to better support spigot 1.18.** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/guiutility/Button.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/guiutility/Button.java index 10804cda3..452d2dfa7 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/guiutility/Button.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/guiutility/Button.java @@ -71,7 +71,7 @@ public Button(Integer position, XMaterial buttonItem, String title){ public Button(Integer position, XMaterial buttonItem, int amount, List lore, String title){ if (position == null || position < 54) { this.position = position; - this.buttonItem = createButton(buttonItem.parseMaterial(), amount, lore, SpigotPrison.format(title)); + this.buttonItem = createButton(buttonItem.parseItem(), amount, lore, SpigotPrison.format(title)); } } @@ -97,9 +97,12 @@ public Button(Integer position, ItemStack buttonItem){ * @param title - String. * */ public Button(Integer position, XMaterial buttonMaterial, int amount, String title){ + if ( amount > 64 ) { + amount = 1; + } if ((position == null || position < 54) && amount <= 64) { this.position = position; - this.buttonItem = createButton(buttonMaterial.parseMaterial(), amount, null, SpigotPrison.format(title)); + this.buttonItem = createButton(buttonMaterial.parseItem(), amount, null, SpigotPrison.format(title)); } } @@ -112,6 +115,9 @@ public Button(Integer position, XMaterial buttonMaterial, int amount, String tit * @param title - String. * */ public Button(Integer position, Material buttonMaterial, int amount, String title){ + if ( amount > 64 ) { + amount = 1; + } if ((position == null || position < 54) && amount <= 64) { this.position = position; this.buttonItem = createButton(buttonMaterial, amount, null, SpigotPrison.format(title)); @@ -128,9 +134,12 @@ public Button(Integer position, Material buttonMaterial, int amount, String titl * @param title - String. * */ public Button(Integer position, XMaterial buttonMaterial, int amount, ButtonLore lore, String title){ + if ( amount > 64 ) { + amount = 1; + } if (position == null || position < 54) { this.position = position; - this.buttonItem = createButton(buttonMaterial.parseMaterial(), amount, lore.getLore(), SpigotPrison.format(title)); + this.buttonItem = createButton(buttonMaterial.parseItem(), amount, lore.getLore(), SpigotPrison.format(title)); } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/guiutility/SpigotGUIComponents.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/guiutility/SpigotGUIComponents.java index 3e6cb0480..f5c470ec1 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/guiutility/SpigotGUIComponents.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/guiutility/SpigotGUIComponents.java @@ -54,6 +54,9 @@ protected ItemStack createButton(Material id, int amount, List lore, Str return getItemStack(item, lore, SpigotPrison.format(display), meta); } + protected ItemStack createButton(ItemStack item, List lore, String display) { + return createButton( item, 1, lore, display ); + } /** * Create a button for the GUI using ItemStack. * @@ -61,12 +64,14 @@ protected ItemStack createButton(Material id, int amount, List lore, Str * @param lore * @param display * */ - protected ItemStack createButton(ItemStack item, List lore, String display) { + protected ItemStack createButton(ItemStack item, int amount, List lore, String display) { if (item == null){ item = XMaterial.BARRIER.parseItem(); } + item.setAmount( amount ); + ItemMeta meta = item.getItemMeta(); if (meta == null){ From 32153f629a3d06db7d740404a36623f1da26cd33 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Wed, 15 Dec 2021 04:15:27 -0500 Subject: [PATCH 213/283] Found a bug in XMaterial where it was converting "melon" to melon_slice instead of the melon block. --- docs/changelog_v3.3.x.md | 3 +++ .../java/tech/mcprison/prison/spigot/block/SpigotBlock.java | 4 ++++ .../tech/mcprison/prison/spigot/compat/Spigot18Blocks.java | 5 +++++ 3 files changed, 12 insertions(+) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 69a7f975c..f17d6047c 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.11 2021-12-15 +* **Found a bug in XMaterial where it was converting "melon" to melon_slice instead of the melon block.** + + * **Bug fix: Fixed an incorrect use of XMaterial which prevented it from working properly with spigot 1.8 through 1.12.** It was using XMaterial to get the Material value, which is wrong, since it's the item stack that contains the variants of the materials. So the change is to extract the item stack directly from XMaterial which solves the problem. Also there was another error where if amounts are greater than 64, setting them to 1 so the GUI will still work, but it will suppress the incorrect counts for the itemstack. diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java index 9b21d95ae..25d705b07 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java @@ -168,6 +168,10 @@ public void setPrisonBlock( XMaterial xMat ) { public void setPrisonBlock( PrisonBlock prisonBlock ) { + if ( prisonBlock == null ) { + prisonBlock = PrisonBlock.AIR; + } + switch ( prisonBlock.getBlockType() ) { case minecraft: diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18Blocks.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18Blocks.java index c30a58e86..9bc18f372 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18Blocks.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot18Blocks.java @@ -265,6 +265,11 @@ public XMaterial getXMaterial( PrisonBlock prisonBlock ) { results = XMaterial.matchXMaterial( blockName ).orElse( null ); + if ( results == XMaterial.MELON_SLICE && + prisonBlock.getBlockName().equalsIgnoreCase( "melon" ) ) { + results = XMaterial.MELON; + } + putCachedXMaterial( prisonBlock, results ); } } From 5f7b465cd54370ed5e5acd19614e5ed738381eb4 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Wed, 15 Dec 2021 04:21:19 -0500 Subject: [PATCH 214/283] GUI Bug fix: If there are more than 45 ranks on a ladder, the GUI will NOW be able to provide paging capabilities to view all ranks. By default it will start off with page one, but this can handle an unlimited number of pages. This paging system can be expanded and easily used on other GUI lists with minimal changes to hook it up. --- docs/changelog_v3.3.x.md | 5 + .../commands/PrisonSpigotGUICommands.java | 12 +- .../spigot/gui/ListenersPrisonManager.java | 45 ++- .../spigot/gui/rank/SpigotGUIMenuTools.java | 278 ++++++++++++++++++ .../spigot/gui/rank/SpigotPlayerRanksGUI.java | 44 ++- 5 files changed, 362 insertions(+), 22 deletions(-) create mode 100644 prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotGUIMenuTools.java diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index f17d6047c..77ba3c6ed 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,11 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.11 2021-12-15 +* **GUI Bug fix: If there are more than 45 ranks on a ladder, the GUI will NOW be able to provide paging capabilities to view all ranks.** +By default it will start off with page one, but this can handle an unlimited number of pages. +This paging system can be expanded and easily used on other GUI lists with minimal changes to hook it up. + + * **Found a bug in XMaterial where it was converting "melon" to melon_slice instead of the melon block.** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotGUICommands.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotGUICommands.java index 65d94a4bd..7206ef467 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotGUICommands.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotGUICommands.java @@ -1,16 +1,16 @@ package tech.mcprison.prison.spigot.commands; -import org.bukkit.configuration.Configuration; import org.bukkit.entity.Player; import tech.mcprison.prison.Prison; +import tech.mcprison.prison.commands.Arg; import tech.mcprison.prison.commands.Command; import tech.mcprison.prison.internal.CommandSender; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.configs.MessagesConfig; -import tech.mcprison.prison.spigot.gui.guiutility.SpigotGUIComponents; import tech.mcprison.prison.spigot.gui.SpigotPrisonGUI; +import tech.mcprison.prison.spigot.gui.guiutility.SpigotGUIComponents; import tech.mcprison.prison.spigot.gui.mine.SpigotPlayerMinesGUI; import tech.mcprison.prison.spigot.gui.rank.SpigotPlayerPrestigesGUI; import tech.mcprison.prison.spigot.gui.rank.SpigotPlayerRanksGUI; @@ -120,7 +120,11 @@ private void prisonManagerMines(CommandSender sender) { @Command( identifier = "gui ranks", description = "GUI Ranks", onlyPlayers = true ) - private void prisonManagerRanks(CommandSender sender) { + private void prisonManagerRanks(CommandSender sender, + @Arg(name = "page", description = "If there are more than 45 ranks, then the " + + "ranks are shown on multiple pages. The page parameter starts with " + + "page 1.", def = "1" ) int page + ) { Player player = getSpigotPlayer(sender); @@ -146,7 +150,7 @@ private void prisonManagerRanks(CommandSender sender) { } } - SpigotPlayerRanksGUI gui = new SpigotPlayerRanksGUI( player ); + SpigotPlayerRanksGUI gui = new SpigotPlayerRanksGUI( player, page ); gui.open(); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java index aead713c0..51a7c5d13 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/ListenersPrisonManager.java @@ -22,6 +22,8 @@ import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.event.player.AsyncPlayerChatEvent; import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; import com.cryptomorin.xseries.XMaterial; @@ -65,6 +67,7 @@ import tech.mcprison.prison.spigot.gui.mine.SpigotMinesBlocksGUI; import tech.mcprison.prison.spigot.gui.mine.SpigotMinesConfirmGUI; import tech.mcprison.prison.spigot.gui.mine.SpigotMinesGUI; +import tech.mcprison.prison.spigot.gui.rank.SpigotGUIMenuTools; import tech.mcprison.prison.spigot.gui.rank.SpigotLaddersGUI; import tech.mcprison.prison.spigot.gui.rank.SpigotRankManagerGUI; import tech.mcprison.prison.spigot.gui.rank.SpigotRankPriceGUI; @@ -79,6 +82,7 @@ import tech.mcprison.prison.spigot.gui.sellall.SellAllPrestigesSetMultiplierGUI; import tech.mcprison.prison.spigot.gui.sellall.SellAllPriceGUI; import tech.mcprison.prison.spigot.sellall.SellAllUtil; +import tech.mcprison.prison.util.Text; /** * @author GABRYCA @@ -413,14 +417,20 @@ public void onClick(InventoryClickEvent e){ p.closeInventory(); return; } - + else if ( buttonNameMain.equalsIgnoreCase( SpigotGUIMenuTools.GUI_MENU_TOOLS_PAGE ) ) { + + processGUIPage( p, title, e.getCurrentItem() ); + return; + } + + String playerRanksTitle = guiConfig.getString("Options.Titles.PlayerRanksGUI").substring(2); String playerPrestigeTitle = guiConfig.getString("Options.Titles.PlayerPrestigesGUI").substring(2); String minesPlayerTitle = guiConfig.getString("Options.Titles.PlayerMinesGUI").substring(2); // Check if the GUI have the right title and do the actions. switch (title) { - + // Check the title and do the actions. case "PrisonManager": @@ -724,7 +734,36 @@ public void onClick(InventoryClickEvent e){ } } - private void sellAllPlayerGUI(InventoryClickEvent e, Player p, String[] parts) { + private void processGUIPage( Player p, String title, ItemStack currentItem ) { + + if ( currentItem != null && currentItem.hasItemMeta() ) { + + ItemMeta meta = currentItem.getItemMeta(); + + if ( meta.hasLore() ) { + + String command = null; + + List lores = meta.getLore(); + + for ( String lore : lores ) { + + if ( lore.contains( SpigotGUIMenuTools.GUI_MENU_TOOLS_COMMAND ) ) { + command = Text.stripColor( lore ).replace( SpigotGUIMenuTools.GUI_MENU_TOOLS_COMMAND, "" ).trim(); + break; + } + } + + if ( command != null ) { + Bukkit.dispatchCommand(p, command); + } + } + + } + + } + + private void sellAllPlayerGUI(InventoryClickEvent e, Player p, String[] parts) { if (parts[0].equalsIgnoreCase("Prior")){ SellAllPlayerGUI gui = new SellAllPlayerGUI(p, Integer.parseInt(parts[1])); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotGUIMenuTools.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotGUIMenuTools.java new file mode 100644 index 000000000..ea1f22f02 --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotGUIMenuTools.java @@ -0,0 +1,278 @@ +package tech.mcprison.prison.spigot.gui.rank; + +import com.cryptomorin.xseries.XMaterial; + +import tech.mcprison.prison.spigot.gui.guiutility.Button; +import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; +import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; + +public class SpigotGUIMenuTools +{ + + public static final String GUI_MENU_TOOLS_PAGE = "GUIPage"; + public static final String GUI_MENU_TOOLS_COMMAND = "Command: "; + + private static SpigotGUIMenuTools instance; + + private XMaterial menuStateOff; + private XMaterial menuStateOn; + +// private String loreCommand; + + private SpigotGUIMenuTools() { + super(); + + + this.menuStateOff = XMaterial.PINK_STAINED_GLASS_PANE; + this.menuStateOn = XMaterial.GREEN_STAINED_GLASS_PANE; + + } + + public static SpigotGUIMenuTools getInstance() { + if ( instance == null ) { + synchronized ( SpigotGUIMenuTools.class ) + { + if ( instance == null ) { + + instance = new SpigotGUIMenuTools(); + instance.internalInitalize(); + } + } + } + return instance; + } + + + + public class GUIMenuPageData { + + private int totalArraySize; + + private int pageSize = 45; + private int page; + + private int dimension; + + private int posStart; + private int posEnd; + + private int pagePrior = -1; + private int pageNext = -1; + + private String commandToRun; + + public GUIMenuPageData( int totalArraySize, int page, String commandToRun ) { + super(); + + this.pageSize = 45; + this.totalArraySize = totalArraySize; + this.page = page; + + + // Create the list of ranks for the selected page and setup the page details: + if ( (page - 1) * pageSize > totalArraySize || page < 1 ) { + // too high of a page number was selected, so use page 0: + page = 1; + } + + posStart = (page - 1) * pageSize; + posEnd = posStart + pageSize; +// posEnd = posStart + pageSize - 1; + + if ( posEnd > totalArraySize ) { + posEnd = totalArraySize; + } + pagePrior = page <= 1 ? -1 : page - 1; + pageNext = posEnd == totalArraySize ? -1 : page + 1; + + + // Create the inventory and set up the owner, dimensions or number of slots, and title + this.dimension = (int) (Math.ceil(( posEnd - posStart ) / 9d) * 9) + 9; + + if ( dimension > 54 ) { + dimension = 54; + } + + this.commandToRun = commandToRun; + + } + + public int getTotalArraySize() { + return totalArraySize; + } + public void setTotalArraySize( int totalArraySize ) { + this.totalArraySize = totalArraySize; + } + + public int getPageSize() { + return pageSize; + } + public void setPageSize( int pageSize ) { + this.pageSize = pageSize; + } + + public int getPage() { + return page; + } + public void setPage( int page ) { + this.page = page; + } + + public int getDimension() { + return dimension; + } + public void setDimension( int dimension ) { + this.dimension = dimension; + } + + public int getPosStart() { + return posStart; + } + public void setPosStart( int posStart ) { + this.posStart = posStart; + } + + public int getPosEnd() { + return posEnd; + } + public void setPosEnd( int posEnd ) { + this.posEnd = posEnd; + } + + public int getPagePrior() { + return pagePrior; + } + public void setPagePrior( int pagePrior ) { + this.pagePrior = pagePrior; + } + + public int getPageNext() { + return pageNext; + } + public void setPageNext( int pageNext ) { + this.pageNext = pageNext; + } + + public String getCommandToRun() { + return commandToRun; + } + public void setCommandToRun( String commandToRun ) { + this.commandToRun = commandToRun; + } + } + + /** + *

This sets up version specific settings. + *

+ * + *

Glass panes are not working + */ + private void internalInitalize() { + + +// this.loreCommand = SpigotPrison.getInstance().getMessagesConfig() +// .getString(MessagesConfig.StringID.spigot_gui_lore_command); + + + +// String bukkitVersion = new BluesSpigetSemVerComparator().getBukkitVersion(); +// if ( bukkitVersion != null ) { +// +// BluesSemanticVersionData svData = new BluesSemanticVersionData( bukkitVersion ); +// +// // If Spigot version is < 1.9.0... ie 1.8... +// if ( svData.compareTo( new BluesSemanticVersionData( "1.9.0" ) ) < 0 ) { +// +//// // glass panes do not work well in 1.8 so setup alternatives: +//// +//// this.menuStateOff = XMaterial.PINK_STAINED_GLASS; +//// this.menuStateOn = XMaterial.GREEN_STAINED_GLASS; +// +// } +// } + + + } + + + + public GUIMenuPageData createGUIPageObject( int totalArraySize, int page, String commandToRun ) { + return new GUIMenuPageData( totalArraySize, page, commandToRun ); + } + + + public Button createButtonPagePrior( GUIMenuPageData pageData ) { + + boolean hasPage = pageData.getPagePrior() > 0; + + String message = !hasPage ? + "No prior page" : "Page " + pageData.getPagePrior(); + + ButtonLore buttonLore = new ButtonLore(); + buttonLore.addLineLoreDescription( message ); + + if ( hasPage ) { + buttonLore.addLineLoreDescription( + GUI_MENU_TOOLS_COMMAND + pageData.getCommandToRun() + " " + pageData.getPagePrior() ); + } + + int pos = pageData.getDimension() - 8; + + XMaterial xMat = !hasPage ? + menuStateOff : menuStateOn; + + int pageNumber = !hasPage ? + 1 : pageData.getPagePrior(); + + Button guiButton = new Button( pos, xMat, pageNumber, buttonLore, + (hasPage ? GUI_MENU_TOOLS_PAGE : message) ); + + return guiButton; + } + + public Button createButtonPageNext( GUIMenuPageData pageData ) { + + boolean hasPage = pageData.getPageNext() > 0; + + String message = !hasPage ? + "No next page" : "Page " + pageData.getPageNext(); + + ButtonLore buttonLore = new ButtonLore(); + buttonLore.addLineLoreDescription( message ); + + if ( hasPage ) { + buttonLore.addLineLoreDescription( + GUI_MENU_TOOLS_COMMAND + pageData.getCommandToRun() + " " + pageData.getPageNext() ); + } + + int pos = pageData.getDimension() - 2; + + XMaterial xMat = !hasPage ? + menuStateOff : menuStateOn; + + int pageNumber = !hasPage ? + 1 : pageData.getPageNext(); + + Button guiButton = new Button( pos, xMat, pageNumber, buttonLore, + (hasPage ? GUI_MENU_TOOLS_PAGE : message) ); + + //guiButton. + + return guiButton; + } + + + public void addMenuPageButtons( PrisonGUI gui, GUIMenuPageData pageData ) { + + gui.addButton( createButtonPagePrior( pageData ) ); + + gui.addButton( createButtonPageNext( pageData ) ); + } + + + + + +} + + diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerRanksGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerRanksGUI.java index f22583ffc..5c1d874f6 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerRanksGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerRanksGUI.java @@ -32,6 +32,7 @@ import tech.mcprison.prison.spigot.gui.guiutility.ButtonLore; import tech.mcprison.prison.spigot.gui.guiutility.PrisonGUI; import tech.mcprison.prison.spigot.gui.guiutility.SpigotGUIComponents; +import tech.mcprison.prison.spigot.gui.rank.SpigotGUIMenuTools.GUIMenuPageData; /** * @author GABRYCA @@ -45,9 +46,13 @@ public class SpigotPlayerRanksGUI extends SpigotGUIComponents { private RankPlayer rankPlayer; private final boolean placeholderAPINotNull = Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null || Bukkit.getPluginManager().getPlugin("PlaceholdersAPI") != null; private final List configCustomLore = guiConfig.getStringList("EditableLore.Ranks"); + + private int page = 0; - public SpigotPlayerRanksGUI(Player player) { + public SpigotPlayerRanksGUI(Player player, int page ) { this.player = player; + + this.page = page; Server server = SpigotPrison.getInstance().getServer(); PrisonRanks rankPlugin; @@ -121,23 +126,22 @@ public void open() { Output.get().sendWarn(new SpigotPlayer(getPlayer()), messages.getString(MessagesConfig.StringID.spigot_message_gui_ranks_empty)); return; } + + int totalArraySize = ladder.getRanks().size(); + GUIMenuPageData guiPageData = SpigotGUIMenuTools.getInstance().createGUIPageObject( totalArraySize, page, "gui ranks" ); - // Create the inventory and set up the owner, dimensions or number of slots, and title - int dimension = (int) (Math.ceil(ladder.getRanks().size() / 9D) * 9) + 9; - - if (dimension > 54){ - Output.get().sendWarn(new SpigotPlayer(getPlayer()), messages.getString(MessagesConfig.StringID.spigot_message_gui_ranks_too_many)); - return; - } + List ranksDisplay = ladder.getRanks().subList( guiPageData.getPosStart(), guiPageData.getPosEnd() ); + + // Get many parameters RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); - Rank rank = ladder.getLowestRank().get(); +// Rank rank = ladder.getLowestRank().get(); PlayerRank playerRankRank = rankPlayerFactory.getRank( getRankPlayer(), guiConfig.getString("Options.Ranks.Ladder")); Rank playerRank = playerRankRank == null ? null : playerRankRank.getRank(); - PrisonGUI gui = new PrisonGUI(getPlayer(), dimension, guiConfig.getString("Options.Titles.PlayerRanksGUI")); + PrisonGUI gui = new PrisonGUI(getPlayer(), guiPageData.getDimension(), guiConfig.getString("Options.Titles.PlayerRanksGUI")); // Not sure how you want to represent this: XMaterial materialHas = XMaterial.valueOf(guiConfig.getString("Options.Ranks.Item_gotten_rank")); @@ -146,15 +150,20 @@ public void open() { // Variables boolean playerHasThisRank = true; int hackyCounterEnchant = 0; - int amount = 1; + + + int amount = guiPageData.getPosStart(); +// int amount = 1; // Global booleans. boolean enchantmentEffectEnabled = getBoolean(guiConfig.getString("Options.Ranks.Enchantment_effect_current_rank")); // Decimal Rank cost format. DecimalFormat formatDecimal = new DecimalFormat("###,##0.00"); + boolean showNumber = getBoolean(guiConfig.getString("Options.Ranks.Number_of_Rank_Player_GUI")); - while (rank != null) { + for ( Rank rank : ranksDisplay ) + { ButtonLore ranksLore = new ButtonLore(); @@ -169,7 +178,6 @@ public void open() { ranksLore.setLoreAction(PlaceholderAPI.setPlaceholders(Bukkit.getOfflinePlayer(player.getUniqueId()), ranksLore.getLoreAction())); } - boolean showNumber = getBoolean(guiConfig.getString("Options.Ranks.Number_of_Rank_Player_GUI")); Button itemRank = new Button(null, playerHasThisRank ? materialHas : materialHasNot, showNumber ? amount : 1, ranksLore, SpigotPrison.format(rank.getTag())); amount++; @@ -188,14 +196,20 @@ public void open() { } gui.addButton(itemRank); - rank = rank.getRankNext(); + +// rank = rank.getRankNext(); } ButtonLore rankupLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_rankup), messages.getString(MessagesConfig.StringID.spigot_gui_lore_rankup_if_enough_money)); // Add button. - gui.addButton(new Button(dimension - 5, XMaterial.EMERALD_BLOCK, rankupLore, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_gui_lore_rankup)))); + gui.addButton(new Button( guiPageData.getDimension() - 5, XMaterial.EMERALD_BLOCK, rankupLore, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_gui_lore_rankup)))); + + // Add the page controls: + SpigotGUIMenuTools.getInstance().addMenuPageButtons( gui, guiPageData ); + + // Open GUI. gui.open(); } From 23ec4e8412608b02f72d9e6cd8293bcd2f1e60bd Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Thu, 16 Dec 2021 11:54:52 -0500 Subject: [PATCH 215/283] GUI Menu Tools - Added a first page and last page button. --- docs/changelog_v3.3.x.md | 5 +- .../spigot/gui/rank/SpigotGUIMenuTools.java | 115 +++++++++++++++++- 2 files changed, 113 insertions(+), 7 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 77ba3c6ed..5944f7c70 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,10 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.11 2021-12-15 +# 3.2.11-alpha.11 2021-12-16 + + +* **GUI Menu Tools - Added a first page and last page button.** * **GUI Bug fix: If there are more than 45 ranks on a ladder, the GUI will NOW be able to provide paging capabilities to view all ranks.** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotGUIMenuTools.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotGUIMenuTools.java index ea1f22f02..330504e55 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotGUIMenuTools.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotGUIMenuTools.java @@ -14,8 +14,11 @@ public class SpigotGUIMenuTools private static SpigotGUIMenuTools instance; - private XMaterial menuStateOff; - private XMaterial menuStateOn; + private XMaterial menuStateOn1; + private XMaterial menuStateOn2; + + private XMaterial menuStateOff1; + private XMaterial menuStateOff2; // private String loreCommand; @@ -23,8 +26,14 @@ private SpigotGUIMenuTools() { super(); - this.menuStateOff = XMaterial.PINK_STAINED_GLASS_PANE; - this.menuStateOn = XMaterial.GREEN_STAINED_GLASS_PANE; + this.menuStateOn1 = XMaterial.LIME_STAINED_GLASS_PANE; + this.menuStateOn2 = XMaterial.GREEN_STAINED_GLASS_PANE; + + this.menuStateOff1 = XMaterial.PINK_STAINED_GLASS_PANE; + this.menuStateOff2 = XMaterial.RED_STAINED_GLASS_PANE; + +// this.menuStateOff1 = XMaterial.WHITE_STAINED_GLASS_PANE; +// this.menuStateOff2 = XMaterial.BLACK_STAINED_GLASS_PANE; } @@ -58,6 +67,8 @@ public class GUIMenuPageData { private int pagePrior = -1; private int pageNext = -1; + + private int pageLast = 1; private String commandToRun; @@ -74,6 +85,11 @@ public GUIMenuPageData( int totalArraySize, int page, String commandToRun ) { // too high of a page number was selected, so use page 0: page = 1; } + + + pageLast = (totalArraySize / pageSize) + + (totalArraySize % pageSize == 0 ? 0 : 1); + posStart = (page - 1) * pageSize; posEnd = posStart + pageSize; @@ -153,6 +169,13 @@ public void setPageNext( int pageNext ) { this.pageNext = pageNext; } + public int getPageLast() { + return pageLast; + } + public void setPageLast( int pageLast ) { + this.pageLast = pageLast; + } + public String getCommandToRun() { return commandToRun; } @@ -201,6 +224,53 @@ public GUIMenuPageData createGUIPageObject( int totalArraySize, int page, String } +// private ButtonLore createButtonLore( boolean enabled, String message, GUIMenuPageData pageData, int page ) { +// +// ButtonLore buttonLore = new ButtonLore(); +// buttonLore.addLineLoreDescription( message ); +// +// if ( enabled ) { +// buttonLore.addLineLoreDescription( +// GUI_MENU_TOOLS_COMMAND + pageData.getCommandToRun() + " " + 1 ); +// } +// return buttonLore; +// } +// +// private Button createButton( ) { +// +// return null; +// } + + public Button createButtonPageOne( GUIMenuPageData pageData ) { + + boolean hasPage = pageData.getPage() > 1; + + String message = !hasPage ? + "Already on page 1" : "Page 1"; + +// ButtonLore buttonLore = createButtonLore( hasPage, message, pageData, 1 ); + + ButtonLore buttonLore = new ButtonLore(); + buttonLore.addLineLoreDescription( message ); + + if ( hasPage ) { + buttonLore.addLineLoreDescription( + GUI_MENU_TOOLS_COMMAND + pageData.getCommandToRun() + " " + 1 ); + } + + int pos = pageData.getDimension() - 9; + + XMaterial xMat = !hasPage ? + menuStateOff1 : menuStateOn1; + + int pageNumber = 1; + + Button guiButton = new Button( pos, xMat, pageNumber, buttonLore, + (hasPage ? GUI_MENU_TOOLS_PAGE : message) ); + + return guiButton; + } + public Button createButtonPagePrior( GUIMenuPageData pageData ) { boolean hasPage = pageData.getPagePrior() > 0; @@ -219,7 +289,7 @@ public Button createButtonPagePrior( GUIMenuPageData pageData ) { int pos = pageData.getDimension() - 8; XMaterial xMat = !hasPage ? - menuStateOff : menuStateOn; + menuStateOff2 : menuStateOn2; int pageNumber = !hasPage ? 1 : pageData.getPagePrior(); @@ -248,7 +318,7 @@ public Button createButtonPageNext( GUIMenuPageData pageData ) { int pos = pageData.getDimension() - 2; XMaterial xMat = !hasPage ? - menuStateOff : menuStateOn; + menuStateOff2 : menuStateOn2; int pageNumber = !hasPage ? 1 : pageData.getPageNext(); @@ -261,12 +331,45 @@ public Button createButtonPageNext( GUIMenuPageData pageData ) { return guiButton; } + public Button createButtonPageLast( GUIMenuPageData pageData ) { + + boolean hasPage = pageData.getPage() < pageData.getPageLast(); + + String message = !hasPage ? + "Already on last page" : "Page " + pageData.getPageNext(); + + ButtonLore buttonLore = new ButtonLore(); + buttonLore.addLineLoreDescription( message ); + + if ( hasPage ) { + buttonLore.addLineLoreDescription( + GUI_MENU_TOOLS_COMMAND + pageData.getCommandToRun() + " " + pageData.getPageLast() ); + } + + int pos = pageData.getDimension() - 1; + + XMaterial xMat = !hasPage ? + menuStateOff1 : menuStateOn1; + + int pageNumber = !hasPage ? + 1 : pageData.getPageLast(); + + Button guiButton = new Button( pos, xMat, pageNumber, buttonLore, + (hasPage ? GUI_MENU_TOOLS_PAGE : message) ); + + //guiButton. + + return guiButton; + } + public void addMenuPageButtons( PrisonGUI gui, GUIMenuPageData pageData ) { + gui.addButton( createButtonPageOne( pageData ) ); gui.addButton( createButtonPagePrior( pageData ) ); gui.addButton( createButtonPageNext( pageData ) ); + gui.addButton( createButtonPageLast( pageData ) ); } From 6af36814a75577c2234d1a93e045117a060c3094 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Thu, 16 Dec 2021 15:38:00 -0500 Subject: [PATCH 216/283] GUI Menu: a few minor changes before more radical changes to go with the final "idea". --- docs/changelog_v3.3.x.md | 3 + .../spigot/gui/rank/SpigotGUIMenuTools.java | 168 ++++++++++-------- .../spigot/gui/rank/SpigotPlayerRanksGUI.java | 12 +- 3 files changed, 101 insertions(+), 82 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 5944f7c70..5c734fd24 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.11 2021-12-16 +* **GUI Menu: a few minor changes before more radical changes to go with the final "idea".** + + * **GUI Menu Tools - Added a first page and last page button.** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotGUIMenuTools.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotGUIMenuTools.java index 330504e55..caf3cacd0 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotGUIMenuTools.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotGUIMenuTools.java @@ -19,6 +19,8 @@ public class SpigotGUIMenuTools private XMaterial menuStateOff1; private XMaterial menuStateOff2; + + private XMaterial menuBackground; // private String loreCommand; @@ -32,8 +34,10 @@ private SpigotGUIMenuTools() { this.menuStateOff1 = XMaterial.PINK_STAINED_GLASS_PANE; this.menuStateOff2 = XMaterial.RED_STAINED_GLASS_PANE; -// this.menuStateOff1 = XMaterial.WHITE_STAINED_GLASS_PANE; -// this.menuStateOff2 = XMaterial.BLACK_STAINED_GLASS_PANE; + this.menuBackground = XMaterial.BLACK_STAINED_GLASS_PANE; + +// this.menuStateOff1 = XMaterial.BLACK_STAINED_GLASS_PANE; +// this.menuStateOff2 = XMaterial.GRAY_STAINED_GLASS_PANE; } @@ -113,6 +117,10 @@ public GUIMenuPageData( int totalArraySize, int page, String commandToRun ) { } + public int getMenuPosition( int position ) { + return getDimension() - 10 + position; + } + public int getTotalArraySize() { return totalArraySize; } @@ -224,44 +232,35 @@ public GUIMenuPageData createGUIPageObject( int totalArraySize, int page, String } -// private ButtonLore createButtonLore( boolean enabled, String message, GUIMenuPageData pageData, int page ) { -// -// ButtonLore buttonLore = new ButtonLore(); -// buttonLore.addLineLoreDescription( message ); -// -// if ( enabled ) { -// buttonLore.addLineLoreDescription( -// GUI_MENU_TOOLS_COMMAND + pageData.getCommandToRun() + " " + 1 ); -// } -// return buttonLore; -// } -// -// private Button createButton( ) { -// -// return null; -// } + private ButtonLore createButtonLore( boolean enableCmd, String message, GUIMenuPageData pageData, int page ) { + + ButtonLore buttonLore = new ButtonLore(); + if ( message != null ) { + buttonLore.addLineLoreDescription( message ); + } + + + if ( enableCmd && pageData != null ) { + buttonLore.addLineLoreDescription( + GUI_MENU_TOOLS_COMMAND + pageData.getCommandToRun() + " " + page ); + } + return buttonLore; + } + - public Button createButtonPageOne( GUIMenuPageData pageData ) { + public Button createButtonPageOne( GUIMenuPageData pageData, int position ) { boolean hasPage = pageData.getPage() > 1; String message = !hasPage ? - "Already on page 1" : "Page 1"; + "Already on page 1" : "Page 1 of " + pageData.getPageLast(); -// ButtonLore buttonLore = createButtonLore( hasPage, message, pageData, 1 ); + ButtonLore buttonLore = createButtonLore( hasPage, message, pageData, 1 ); - ButtonLore buttonLore = new ButtonLore(); - buttonLore.addLineLoreDescription( message ); - - if ( hasPage ) { - buttonLore.addLineLoreDescription( - GUI_MENU_TOOLS_COMMAND + pageData.getCommandToRun() + " " + 1 ); - } - - int pos = pageData.getDimension() - 9; + int pos = pageData.getMenuPosition( position ); XMaterial xMat = !hasPage ? - menuStateOff1 : menuStateOn1; + menuStateOff2 : menuStateOn2; int pageNumber = 1; @@ -271,25 +270,19 @@ public Button createButtonPageOne( GUIMenuPageData pageData ) { return guiButton; } - public Button createButtonPagePrior( GUIMenuPageData pageData ) { + public Button createButtonPagePrior( GUIMenuPageData pageData, int position ) { boolean hasPage = pageData.getPagePrior() > 0; String message = !hasPage ? - "No prior page" : "Page " + pageData.getPagePrior(); - - ButtonLore buttonLore = new ButtonLore(); - buttonLore.addLineLoreDescription( message ); + "No prior page" : "Page " + pageData.getPagePrior() + " of " + pageData.getPageLast(); + + ButtonLore buttonLore = createButtonLore( hasPage, message, pageData, pageData.getPagePrior() ); - if ( hasPage ) { - buttonLore.addLineLoreDescription( - GUI_MENU_TOOLS_COMMAND + pageData.getCommandToRun() + " " + pageData.getPagePrior() ); - } - - int pos = pageData.getDimension() - 8; + int pos = pageData.getMenuPosition( position ); XMaterial xMat = !hasPage ? - menuStateOff2 : menuStateOn2; + menuStateOff1 : menuStateOn1; int pageNumber = !hasPage ? 1 : pageData.getPagePrior(); @@ -300,25 +293,36 @@ public Button createButtonPagePrior( GUIMenuPageData pageData ) { return guiButton; } - public Button createButtonPageNext( GUIMenuPageData pageData ) { + public Button createButtonPageCurrent( GUIMenuPageData pageData, int position ) { - boolean hasPage = pageData.getPageNext() > 0; + String message = "Page " + pageData.getPage() + " of " + pageData.getPageLast(); - String message = !hasPage ? - "No next page" : "Page " + pageData.getPageNext(); + ButtonLore buttonLore = createButtonLore( false, message, pageData, pageData.getPage() ); - ButtonLore buttonLore = new ButtonLore(); - buttonLore.addLineLoreDescription( message ); + int pos = pageData.getMenuPosition( position ); - if ( hasPage ) { - buttonLore.addLineLoreDescription( - GUI_MENU_TOOLS_COMMAND + pageData.getCommandToRun() + " " + pageData.getPageNext() ); - } + XMaterial xMat = XMaterial.COMPASS; + + int pageNumber = pageData.getPage(); - int pos = pageData.getDimension() - 2; + Button guiButton = new Button( pos, xMat, pageNumber, buttonLore, message ); + + return guiButton; + } + + public Button createButtonPageNext( GUIMenuPageData pageData, int position ) { + + boolean hasPage = pageData.getPageNext() > 0; + + String message = !hasPage ? + "No next page" : "Page " + pageData.getPageNext() + " of " + pageData.getPageLast(); + + ButtonLore buttonLore = createButtonLore( hasPage, message, pageData, pageData.getPageNext() ); + + int pos = pageData.getMenuPosition( position ); XMaterial xMat = !hasPage ? - menuStateOff2 : menuStateOn2; + menuStateOff1 : menuStateOn1; int pageNumber = !hasPage ? 1 : pageData.getPageNext(); @@ -326,30 +330,22 @@ public Button createButtonPageNext( GUIMenuPageData pageData ) { Button guiButton = new Button( pos, xMat, pageNumber, buttonLore, (hasPage ? GUI_MENU_TOOLS_PAGE : message) ); - //guiButton. - return guiButton; } - public Button createButtonPageLast( GUIMenuPageData pageData ) { + public Button createButtonPageLast( GUIMenuPageData pageData, int position ) { boolean hasPage = pageData.getPage() < pageData.getPageLast(); String message = !hasPage ? - "Already on last page" : "Page " + pageData.getPageNext(); + "Already on last page" : "Page " + pageData.getPageLast() + " of " + pageData.getPageLast(); - ButtonLore buttonLore = new ButtonLore(); - buttonLore.addLineLoreDescription( message ); - - if ( hasPage ) { - buttonLore.addLineLoreDescription( - GUI_MENU_TOOLS_COMMAND + pageData.getCommandToRun() + " " + pageData.getPageLast() ); - } + ButtonLore buttonLore = createButtonLore( hasPage, message, pageData, pageData.getPageLast() ); - int pos = pageData.getDimension() - 1; + int pos = pageData.getMenuPosition( position ); XMaterial xMat = !hasPage ? - menuStateOff1 : menuStateOn1; + menuStateOff2 : menuStateOn2; int pageNumber = !hasPage ? 1 : pageData.getPageLast(); @@ -357,25 +353,43 @@ public Button createButtonPageLast( GUIMenuPageData pageData ) { Button guiButton = new Button( pos, xMat, pageNumber, buttonLore, (hasPage ? GUI_MENU_TOOLS_PAGE : message) ); - //guiButton. + return guiButton; + } + + public Button createButtonMenuBackground( GUIMenuPageData pageData, int position ) { + + ButtonLore buttonLore = createButtonLore( false, null, null, 1 ); + + int pos = pageData.getMenuPosition( position ); + + XMaterial xMat = menuBackground; + + int pageNumber = 1; + + Button guiButton = new Button( pos, xMat, pageNumber, buttonLore, "" ); return guiButton; } - public void addMenuPageButtons( PrisonGUI gui, GUIMenuPageData pageData ) { + public void addMenuPageButtonsStandard( PrisonGUI gui, GUIMenuPageData pageData ) { - gui.addButton( createButtonPageOne( pageData ) ); - gui.addButton( createButtonPagePrior( pageData ) ); + gui.addButton( createButtonPageOne( pageData, 1 ) ); + gui.addButton( createButtonPagePrior( pageData, 2 ) ); + + gui.addButton( createButtonMenuBackground( pageData, 3 ) ); + gui.addButton( createButtonMenuBackground( pageData, 4 ) ); - gui.addButton( createButtonPageNext( pageData ) ); - gui.addButton( createButtonPageLast( pageData ) ); - } + gui.addButton( createButtonPageCurrent( pageData, 5 ) ); + + gui.addButton( createButtonMenuBackground( pageData, 6 ) ); + gui.addButton( createButtonMenuBackground( pageData, 7 ) ); + gui.addButton( createButtonPageNext( pageData, 8 ) ); + gui.addButton( createButtonPageLast( pageData, 9 ) ); + } - - } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerRanksGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerRanksGUI.java index 5c1d874f6..d8845231d 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerRanksGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerRanksGUI.java @@ -200,14 +200,16 @@ public void open() { // rank = rank.getRankNext(); } - ButtonLore rankupLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_rankup), messages.getString(MessagesConfig.StringID.spigot_gui_lore_rankup_if_enough_money)); + + // Add the page controls: + SpigotGUIMenuTools.getInstance().addMenuPageButtonsStandard( gui, guiPageData ); - // Add button. - gui.addButton(new Button( guiPageData.getDimension() - 5, XMaterial.EMERALD_BLOCK, rankupLore, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_gui_lore_rankup)))); + + // Add Rankup button: + ButtonLore rankupLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_rankup), messages.getString(MessagesConfig.StringID.spigot_gui_lore_rankup_if_enough_money)); + gui.addButton(new Button( guiPageData.getMenuPosition( 3 ), XMaterial.EMERALD_BLOCK, rankupLore, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_gui_lore_rankup)))); - // Add the page controls: - SpigotGUIMenuTools.getInstance().addMenuPageButtons( gui, guiPageData ); // Open GUI. From c72e383922d682e3bc546d13a5a5346aa3c933af Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Thu, 16 Dec 2021 22:28:13 -0500 Subject: [PATCH 217/283] Potential bug fix: There was a situation where with multiverse-core a delayed world loading resulted in the world not being found, and therefore it was preventing the loading of all locations tied to the mine. This now allows the locations to be loaded without a valid world. Then when the world is finally loaded, it will refresh the references to the world objects. --- docs/changelog_v3.3.x.md | 3 ++ .../tech/mcprison/prison/mines/data/Mine.java | 34 +++++++++++++------ .../prison/mines/managers/MineManager.java | 15 ++++++++ 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 5c734fd24..b2a7dcb1e 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.11 2021-12-16 +* **Potential bug fix: There was a situation where with multiverse-core a delayed world loading resulted in the world not being found**, and therefore it was preventing the loading of all locations tied to the mine. This now allows the locations to be loaded without a valid world. Then when the world is finally loaded, it will refresh the references to the world objects. + + * **GUI Menu: a few minor changes before more radical changes to go with the final "idea".** diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/Mine.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/Mine.java index aa4422b2a..f5a2b62b1 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/Mine.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/Mine.java @@ -682,21 +682,35 @@ public String toString() { return getName() + " " + getTotalBlocksMined(); } + /** + *

Even if world is null, it will allow you to create a location, but + * the location will be invalid. In order to use this location, + * the world will have to be set to a valid world. + *

+ * + * @param doc + * @param world + * @param x + * @param y + * @param z + * @return + */ private Location getLocation(Document doc, World world, String x, String y, String z) { Location results = null; - if ( world != null ) { - - Object xD = doc.get(x); - Object yD = doc.get(y); - Object zD = doc.get(z); - - if ( xD != null && yD != null && zD != null ) { - - results = new Location(world, (double) xD, (double) yD, (double) zD ); - } +// if ( world != null ) { +// +// +// } + Object xD = doc.get(x); + Object yD = doc.get(y); + Object zD = doc.get(z); + + if ( xD != null && yD != null && zD != null ) { + results = new Location(world, (double) xD, (double) yD, (double) zD ); } + return results; } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/managers/MineManager.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/managers/MineManager.java index 2c03605e0..2f65a323c 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/managers/MineManager.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/managers/MineManager.java @@ -643,6 +643,7 @@ public void assignAvailableWorld( String worldName ) { Optional worldOptional = Prison.get().getPlatform().getWorld(worldName); if ( worldOptional.isPresent() && getUnavailableWorlds().containsKey( worldName )) { + World world = worldOptional.get(); // Store this mine and the world in MineManager's unavailableWorld for later @@ -654,6 +655,20 @@ public void assignAvailableWorld( String worldName ) { for ( Mine mine : unenabledMines ) { if ( !mine.isEnabled() ) { mine.setWorld( world ); + + // Make sure world is hooked up properly to all locations. + // Since world is an object, it may already be auto hooked: + + + if ( mine.getBounds() != null ) { + mine.getBounds().setWorld( world ); + } + + + if ( mine.getSpawn() != null ) { + mine.getSpawn().setWorld( world ); + } + } // remove.add( mine ); } From b2ee72d69acc71d6249f24d96f9f7625321c2838 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 17 Dec 2021 13:04:49 -0500 Subject: [PATCH 218/283] Prison Tokens: Remove the alias so they will not cause conflict with other token plugins. --- docs/changelog_v3.3.x.md | 5 ++++- .../src/main/java/tech/mcprison/prison/PrisonCommand.java | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index b2a7dcb1e..ec14fdb4e 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -13,7 +13,10 @@ These build logs represent the work that has been going on within prison. *Will continue as v3.3.0-alpha.7 2021-06-?? in the near future.* -# 3.2.11-alpha.11 2021-12-16 +# 3.2.11-alpha.11 2021-12-17 + + +* **Prison Tokens: Remove the alias so they will not cause conflict with other token plugins.** * **Potential bug fix: There was a situation where with multiverse-core a delayed world loading resulted in the world not being found**, and therefore it was preventing the loading of all locations tied to the mine. This now allows the locations to be loaded without a valid world. Then when the world is finally loaded, it will refresh the references to the world objects. diff --git a/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java b/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java index 0f2dd28bc..ea12bb5aa 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java +++ b/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java @@ -1551,7 +1551,7 @@ public void supportListenersDump(CommandSender sender, @Command(identifier = "prison tokens balance", description = "Prison tokens: a player's current balance.", - aliases = "tokens bal", + // aliases = "tokens bal", permissions = "tokens.bal", altPermissions = "tokens.bal.others" ) public void tokensBalance(CommandSender sender, From 6a64cba1f69920081092275ca5928224dc5e0e45 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 17 Dec 2021 15:20:40 -0500 Subject: [PATCH 219/283] GUI menu tools update... --- docs/changelog_v3.3.x.md | 3 + .../spigot/gui/rank/SpigotGUIMenuTools.java | 156 ++++++++++++++---- .../spigot/gui/rank/SpigotPlayerRanksGUI.java | 4 +- 3 files changed, 134 insertions(+), 29 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index ec14fdb4e..5f4485bc1 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.11 2021-12-17 +* **GUI menu tools update...** + + * **Prison Tokens: Remove the alias so they will not cause conflict with other token plugins.** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotGUIMenuTools.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotGUIMenuTools.java index caf3cacd0..ebf9828a2 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotGUIMenuTools.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotGUIMenuTools.java @@ -11,6 +11,7 @@ public class SpigotGUIMenuTools public static final String GUI_MENU_TOOLS_PAGE = "GUIPage"; public static final String GUI_MENU_TOOLS_COMMAND = "Command: "; + public static final String GUI_MENU_TOOLS_COMMANDS_BACK = "CommandsBack: "; private static SpigotGUIMenuTools instance; @@ -22,11 +23,17 @@ public class SpigotGUIMenuTools private XMaterial menuBackground; + private XMaterial menuGoBack; + + private boolean useDisabledButtons; + + // private String loreCommand; private SpigotGUIMenuTools() { super(); + this.useDisabledButtons = false; this.menuStateOn1 = XMaterial.LIME_STAINED_GLASS_PANE; this.menuStateOn2 = XMaterial.GREEN_STAINED_GLASS_PANE; @@ -36,6 +43,8 @@ private SpigotGUIMenuTools() { this.menuBackground = XMaterial.BLACK_STAINED_GLASS_PANE; + this.menuGoBack = XMaterial.BARRIER; + // this.menuStateOff1 = XMaterial.BLACK_STAINED_GLASS_PANE; // this.menuStateOff2 = XMaterial.GRAY_STAINED_GLASS_PANE; @@ -76,6 +85,28 @@ public class GUIMenuPageData { private String commandToRun; + private String commandGoBack; + + /** + * + * @param totalArraySize + * @param page + * @param commandToRun Command to run for paging. The page number will be appended + * to this command. This command is ran as-is. + * @param commandGoBack Command to run to return to a prior menu, or another app. + * No page number is added, so if page number is important to return + * to the same "view" then it must be included with this command. + * This command is ran as-is. + */ + public GUIMenuPageData( int totalArraySize, int page, + String commandToRun, String commandGoBack ) { + this( totalArraySize, page, commandToRun ); + + if ( commandGoBack != null ) { + this.commandGoBack = commandGoBack; + } + } + public GUIMenuPageData( int totalArraySize, int page, String commandToRun ) { super(); @@ -117,6 +148,13 @@ public GUIMenuPageData( int totalArraySize, int page, String commandToRun ) { } + public GUIMenuPageData clone() { + GUIMenuPageData results = new GUIMenuPageData( totalArraySize, page, + getCommandToRun(), getCommandGoBack() ); + + return results; + } + public int getMenuPosition( int position ) { return getDimension() - 10 + position; } @@ -190,6 +228,13 @@ public String getCommandToRun() { public void setCommandToRun( String commandToRun ) { this.commandToRun = commandToRun; } + + public String getCommandGoBack() { + return commandGoBack; + } + public void setCommandGoBack( String commandGoBack ) { + this.commandGoBack = commandGoBack; + } } /** @@ -232,7 +277,8 @@ public GUIMenuPageData createGUIPageObject( int totalArraySize, int page, String } - private ButtonLore createButtonLore( boolean enableCmd, String message, GUIMenuPageData pageData, int page ) { + private ButtonLore createButtonLore( boolean enableCmd, String message, + GUIMenuPageData pageData, int page ) { ButtonLore buttonLore = new ButtonLore(); if ( message != null ) { @@ -241,54 +287,92 @@ private ButtonLore createButtonLore( boolean enableCmd, String message, GUIMenuP if ( enableCmd && pageData != null ) { - buttonLore.addLineLoreDescription( - GUI_MENU_TOOLS_COMMAND + pageData.getCommandToRun() + " " + page ); + + if ( pageData.getCommandToRun() != null ) { + buttonLore.addLineLoreDescription( "&0" + + GUI_MENU_TOOLS_COMMAND + pageData.getCommandToRun() + " " + page ); + } + +// if ( pageData.getCommandsBack() != null ) { +// buttonLore.addLineLoreDescription( "&0" + +// GUI_MENU_TOOLS_COMMANDS_BACK + pageData.getCommandsBack() ); +// } + } return buttonLore; } + public Button createButtonBack( GUIMenuPageData pageData, int position ) { + + if ( pageData.getCommandGoBack() == null ) { + + return createButtonMenuBackground( pageData, position ); + } + + boolean active = true; + + GUIMenuPageData newPageData = pageData.clone(); + newPageData.setCommandToRun( pageData.getCommandGoBack() ); + newPageData.setCommandGoBack( null ); + + String message = "Go Back"; + + ButtonLore buttonLore = createButtonLore( active, message, newPageData, 1 ); + + int pos = pageData.getMenuPosition( position ); + + XMaterial xMat = menuGoBack; + + int pageNumber = 1; + + Button guiButton = new Button( pos, xMat, pageNumber, buttonLore, + (active ? GUI_MENU_TOOLS_PAGE : message) ); + + return guiButton; + } + public Button createButtonPageOne( GUIMenuPageData pageData, int position ) { - boolean hasPage = pageData.getPage() > 1; + boolean active = !useDisabledButtons || pageData.getPage() > 1; - String message = !hasPage ? + String message = !active ? "Already on page 1" : "Page 1 of " + pageData.getPageLast(); - ButtonLore buttonLore = createButtonLore( hasPage, message, pageData, 1 ); + ButtonLore buttonLore = createButtonLore( active, message, pageData, 1 ); int pos = pageData.getMenuPosition( position ); - XMaterial xMat = !hasPage ? + XMaterial xMat = !active ? menuStateOff2 : menuStateOn2; int pageNumber = 1; Button guiButton = new Button( pos, xMat, pageNumber, buttonLore, - (hasPage ? GUI_MENU_TOOLS_PAGE : message) ); + (active ? GUI_MENU_TOOLS_PAGE : message) ); return guiButton; } public Button createButtonPagePrior( GUIMenuPageData pageData, int position ) { - boolean hasPage = pageData.getPagePrior() > 0; + boolean active = !useDisabledButtons ||pageData.getPagePrior() > 0; - String message = !hasPage ? + String message = !active ? "No prior page" : "Page " + pageData.getPagePrior() + " of " + pageData.getPageLast(); - ButtonLore buttonLore = createButtonLore( hasPage, message, pageData, pageData.getPagePrior() ); + ButtonLore buttonLore = createButtonLore( active, message, pageData, pageData.getPagePrior() ); int pos = pageData.getMenuPosition( position ); - XMaterial xMat = !hasPage ? + XMaterial xMat = !active ? menuStateOff1 : menuStateOn1; - int pageNumber = !hasPage ? + int pageNumber = !active || pageData.getPagePrior() < 1 ? 1 : pageData.getPagePrior(); Button guiButton = new Button( pos, xMat, pageNumber, buttonLore, - (hasPage ? GUI_MENU_TOOLS_PAGE : message) ); + (active ? GUI_MENU_TOOLS_PAGE : message) ); return guiButton; } @@ -312,46 +396,46 @@ public Button createButtonPageCurrent( GUIMenuPageData pageData, int position ) public Button createButtonPageNext( GUIMenuPageData pageData, int position ) { - boolean hasPage = pageData.getPageNext() > 0; + boolean active = !useDisabledButtons ||pageData.getPageNext() > 0; - String message = !hasPage ? + String message = !active ? "No next page" : "Page " + pageData.getPageNext() + " of " + pageData.getPageLast(); - ButtonLore buttonLore = createButtonLore( hasPage, message, pageData, pageData.getPageNext() ); + ButtonLore buttonLore = createButtonLore( active, message, pageData, pageData.getPageNext() ); int pos = pageData.getMenuPosition( position ); - XMaterial xMat = !hasPage ? + XMaterial xMat = !active ? menuStateOff1 : menuStateOn1; - int pageNumber = !hasPage ? + int pageNumber = !active || pageData.getPageNext() < 1 ? 1 : pageData.getPageNext(); Button guiButton = new Button( pos, xMat, pageNumber, buttonLore, - (hasPage ? GUI_MENU_TOOLS_PAGE : message) ); + (active ? GUI_MENU_TOOLS_PAGE : message) ); return guiButton; } public Button createButtonPageLast( GUIMenuPageData pageData, int position ) { - boolean hasPage = pageData.getPage() < pageData.getPageLast(); + boolean active = !useDisabledButtons ||pageData.getPage() < pageData.getPageLast(); - String message = !hasPage ? + String message = !active ? "Already on last page" : "Page " + pageData.getPageLast() + " of " + pageData.getPageLast(); - ButtonLore buttonLore = createButtonLore( hasPage, message, pageData, pageData.getPageLast() ); + ButtonLore buttonLore = createButtonLore( active, message, pageData, pageData.getPageLast() ); int pos = pageData.getMenuPosition( position ); - XMaterial xMat = !hasPage ? + XMaterial xMat = !active ? menuStateOff2 : menuStateOn2; - int pageNumber = !hasPage ? + int pageNumber = !active || pageData.getPageLast() < 1 ? 1 : pageData.getPageLast(); Button guiButton = new Button( pos, xMat, pageNumber, buttonLore, - (hasPage ? GUI_MENU_TOOLS_PAGE : message) ); + (active ? GUI_MENU_TOOLS_PAGE : message) ); return guiButton; } @@ -374,17 +458,33 @@ public Button createButtonMenuBackground( GUIMenuPageData pageData, int position public void addMenuPageButtonsStandard( PrisonGUI gui, GUIMenuPageData pageData ) { + gui.addButton( createButtonMenuBackground( pageData, 1 ) ); + gui.addButton( createButtonMenuBackground( pageData, 2 ) ); + gui.addButton( createButtonMenuBackground( pageData, 3 ) ); + + gui.addButton( createButtonPagePrior( pageData, 4 ) ); + gui.addButton( createButtonPageCurrent( pageData, 5 ) ); + gui.addButton( createButtonPageNext( pageData, 6 ) ); + + gui.addButton( createButtonMenuBackground( pageData, 7 ) ); + gui.addButton( createButtonMenuBackground( pageData, 8 ) ); + gui.addButton( createButtonMenuBackground( pageData, 9 ) ); + + } + + public void addMenuPageButtonsWideLayout( PrisonGUI gui, GUIMenuPageData pageData ) { + gui.addButton( createButtonPageOne( pageData, 1 ) ); gui.addButton( createButtonPagePrior( pageData, 2 ) ); gui.addButton( createButtonMenuBackground( pageData, 3 ) ); gui.addButton( createButtonMenuBackground( pageData, 4 ) ); - + gui.addButton( createButtonPageCurrent( pageData, 5 ) ); gui.addButton( createButtonMenuBackground( pageData, 6 ) ); gui.addButton( createButtonMenuBackground( pageData, 7 ) ); - + gui.addButton( createButtonPageNext( pageData, 8 ) ); gui.addButton( createButtonPageLast( pageData, 9 ) ); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerRanksGUI.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerRanksGUI.java index d8845231d..fccb4821f 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerRanksGUI.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotPlayerRanksGUI.java @@ -202,16 +202,18 @@ public void open() { // Add the page controls: + // The controls for the standard menu are in positions: 4, 5, and 6: SpigotGUIMenuTools.getInstance().addMenuPageButtonsStandard( gui, guiPageData ); // Add Rankup button: ButtonLore rankupLore = new ButtonLore(messages.getString(MessagesConfig.StringID.spigot_gui_lore_click_to_rankup), messages.getString(MessagesConfig.StringID.spigot_gui_lore_rankup_if_enough_money)); - gui.addButton(new Button( guiPageData.getMenuPosition( 3 ), XMaterial.EMERALD_BLOCK, rankupLore, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_gui_lore_rankup)))); + gui.addButton(new Button( guiPageData.getMenuPosition( 1 ), XMaterial.EMERALD_BLOCK, rankupLore, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_gui_lore_rankup)))); + // Open GUI. gui.open(); } From 93c9d0e87544430f8b734949df84c1d875d16523 Mon Sep 17 00:00:00 2001 From: RoyalBlueRanger <665978+rbluer@users.noreply.github.com> Date: Fri, 17 Dec 2021 18:15:43 -0500 Subject: [PATCH 220/283] More work on the GUI menu tools to not only get them to work better (correctly) but also add new capabilities... now supports adding a menu option and the tool auto assigns it to the next available slot. --- docs/changelog_v3.3.x.md | 3 + .../spigot/gui/rank/SpigotGUIMenuTools.java | 120 +++++++++++++----- 2 files changed, 89 insertions(+), 34 deletions(-) diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 5f4485bc1..c7ff141dc 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -16,6 +16,9 @@ These build logs represent the work that has been going on within prison. # 3.2.11-alpha.11 2021-12-17 +* **More work on the GUI menu tools to not only get them to work better (correctly) but also add new capabilities... now supports adding a menu option and the tool auto assigns it to the next available slot.** + + * **GUI menu tools update...** diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotGUIMenuTools.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotGUIMenuTools.java index ebf9828a2..9f15bed2a 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotGUIMenuTools.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/gui/rank/SpigotGUIMenuTools.java @@ -1,5 +1,8 @@ package tech.mcprison.prison.spigot.gui.rank; +import java.util.ArrayList; +import java.util.List; + import com.cryptomorin.xseries.XMaterial; import tech.mcprison.prison.spigot.gui.guiutility.Button; @@ -87,6 +90,8 @@ public class GUIMenuPageData { private String commandGoBack; + private List