From 9376afb1798bf196aca8d63bb131084def7ed07c Mon Sep 17 00:00:00 2001 From: monst Date: Sun, 16 Aug 2020 14:19:46 -0500 Subject: [PATCH] Bug fixes and feature additions - Removed permissions related to bank info, as all bank info should be public - Various tweaks and code cleanup - Bank volume limits are now carried in long values for safety - Rehashed class structure of Guis (added new abstract superclasses SinglePageGui and MultiPageGui) for better polymorphism and inheritance - Hopefully Gui icon lore will now always be gray by default - Fixed error in Gui generics that prevented type safety - Added enum value GuiType.ACCOUNT_SHULKER_CONTENTS - Cleaned up and added some assertions to BankUtils - Tweaked message - Reworded some permission descriptions, added notes, changed defaults --- pom.xml | 4 +- .../java/com/monst/bankingplugin/Bank.java | 23 +++---- .../monst/bankingplugin/BankingPlugin.java | 4 +- .../commands/bank/BankCommandExecutor.java | 16 ++--- .../control/ControlCommandExecutor.java | 2 +- .../monst/bankingplugin/config/Config.java | 4 +- .../events/control/ReloadEvent.java | 2 +- .../external/WorldGuardBankingFlag.java | 7 +- .../bankingplugin/gui/AccountContentsGui.java | 12 ++-- .../monst/bankingplugin/gui/AccountGui.java | 14 ++-- .../bankingplugin/gui/AccountListGui.java | 55 +--------------- .../com/monst/bankingplugin/gui/BankGui.java | 40 ++++++------ .../java/com/monst/bankingplugin/gui/Gui.java | 64 ++++++------------- .../monst/bankingplugin/gui/MultiPageGui.java | 51 +++++++++++++++ .../bankingplugin/gui/SinglePageGui.java | 37 +++++++++++ .../com/monst/bankingplugin/sql/Database.java | 4 +- .../monst/bankingplugin/utils/BankUtils.java | 32 +++++----- .../monst/bankingplugin/utils/Messages.java | 2 +- .../bankingplugin/utils/Permissions.java | 3 - src/main/resources/config.yml | 2 +- src/main/resources/plugin.yml | 41 ++++++------ 21 files changed, 210 insertions(+), 209 deletions(-) create mode 100644 src/main/java/com/monst/bankingplugin/gui/MultiPageGui.java create mode 100644 src/main/java/com/monst/bankingplugin/gui/SinglePageGui.java diff --git a/pom.xml b/pom.xml index 70915a96..fd610d2d 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.monst BankingPlugin - 1.11.8-SNAPSHOT + 1.12.0-SNAPSHOT BankingPlugin Create bank accounts in bank vault chests and earn interest on your investments! @@ -84,7 +84,7 @@ com.sk89q.worldedit worldedit-bukkit - 7.1.0 + 7.2.0-SNAPSHOT provided diff --git a/src/main/java/com/monst/bankingplugin/Bank.java b/src/main/java/com/monst/bankingplugin/Bank.java index 89410ace..c3941b4e 100644 --- a/src/main/java/com/monst/bankingplugin/Bank.java +++ b/src/main/java/com/monst/bankingplugin/Bank.java @@ -293,10 +293,7 @@ public TextComponent getInfoButton(CommandSender sender) { @Override public TextComponent getInformation(CommandSender sender) { boolean isOwner = sender instanceof Player && isOwner((Player) sender); - boolean verbose = (sender instanceof Player && isTrusted((Player) sender)) - || (getType() == BankType.PLAYER && sender.hasPermission(Permissions.BANK_INFO_OTHER) - || (getType() == BankType.ADMIN && sender.hasPermission(Permissions.BANK_INFO_ADMIN))); - + TextComponent info = new TextComponent(); info.setColor(net.md_5.bungee.api.ChatColor.GRAY); @@ -312,17 +309,13 @@ public TextComponent getInformation(CommandSender sender) { info.addExtra("\n Offline payouts: " + ChatColor.AQUA + accountConfig.get(AccountConfig.Field.ALLOWED_OFFLINE_PAYOUTS)); info.addExtra(" (" + ChatColor.AQUA + accountConfig.get(AccountConfig.Field.ALLOWED_OFFLINE_PAYOUTS_BEFORE_RESET) + ChatColor.GRAY + " before multiplier reset)"); info.addExtra("\n Initial payout delay: " + ChatColor.AQUA + accountConfig.get(AccountConfig.Field.INITIAL_INTEREST_DELAY)); - double minBal = accountConfig.get(AccountConfig.Field.MINIMUM_BALANCE); - info.addExtra("\n Minimum balance: " + ChatColor.GREEN + "$" + Utils.format(minBal)); - if (minBal != 0) - info.addExtra(" (" + ChatColor.RED + "$" + accountConfig.getFormatted(AccountConfig.Field.LOW_BALANCE_FEE) + ChatColor.GRAY + " fee)"); - if (verbose) { - info.addExtra("\n Accounts: " + ChatColor.AQUA + accounts.size()); - info.addExtra("\n Total value: " + ChatColor.GREEN + "$" + Utils.format(getTotalValue())); - info.addExtra("\n Average account value: " + ChatColor.GREEN + "$" + Utils.format(getTotalValue().doubleValue() / accounts.size())); - info.addExtra("\n Equality score: "); - info.addExtra(BankUtils.getEqualityLore(this)); - } + info.addExtra("\n Minimum balance: " + ChatColor.GREEN + "$" + Utils.format((double) accountConfig.get(AccountConfig.Field.MINIMUM_BALANCE))); + info.addExtra(" (" + ChatColor.RED + "$" + accountConfig.getFormatted(AccountConfig.Field.LOW_BALANCE_FEE) + ChatColor.GRAY + " fee)"); + info.addExtra("\n Accounts: " + ChatColor.AQUA + accounts.size()); + info.addExtra("\n Total value: " + ChatColor.GREEN + "$" + Utils.format(getTotalValue())); + info.addExtra("\n Average account value: " + ChatColor.GREEN + "$" + Utils.format(getTotalValue().doubleValue() / accounts.size())); + info.addExtra("\n Equality score: "); + info.addExtra(BankUtils.getEqualityLore(this)); info.addExtra("\n Location: " + ChatColor.AQUA + getSelection().getCoordinates()); return info; diff --git a/src/main/java/com/monst/bankingplugin/BankingPlugin.java b/src/main/java/com/monst/bankingplugin/BankingPlugin.java index 784dd1cd..5bb63743 100644 --- a/src/main/java/com/monst/bankingplugin/BankingPlugin.java +++ b/src/main/java/com/monst/bankingplugin/BankingPlugin.java @@ -94,7 +94,7 @@ public void onLoad() { worldGuard = Bukkit.getServer().getPluginManager().getPlugin("WorldGuard"); if (worldGuard != null) { - WorldGuardBankingFlag.register(this); // Throws class error with worldedit:World.class + WorldGuardBankingFlag.register(this); } } @@ -176,7 +176,7 @@ public void onDisable() { for (Bank bank : bankUtils.getBanksCopy()) { bankUtils.removeBank(bank, false); - debug("Removed bank (\"" + bank.getName() + "\" (#" + bank.getID() + "))"); + debug("Removed bank \"" + bank.getName() + "\" (#" + bank.getID() + ")"); } if (database != null) { diff --git a/src/main/java/com/monst/bankingplugin/commands/bank/BankCommandExecutor.java b/src/main/java/com/monst/bankingplugin/commands/bank/BankCommandExecutor.java index bb49dbb5..25e01995 100644 --- a/src/main/java/com/monst/bankingplugin/commands/bank/BankCommandExecutor.java +++ b/src/main/java/com/monst/bankingplugin/commands/bank/BankCommandExecutor.java @@ -171,7 +171,7 @@ private boolean promptBankCreate(final Player p, String[] args) { return true; } long volume = selection.getVolume(); - int volumeLimit = bankUtils.getVolumeLimit(p); + long volumeLimit = bankUtils.getVolumeLimit(p); if (!isAdminBank && volumeLimit != -1 && volume > volumeLimit) { plugin.debug("Bank is too large (" + volume + " blocks, limit: " + volumeLimit + ")"); p.sendMessage(String.format(Messages.SELECTION_TOO_LARGE, volumeLimit, volume - volumeLimit)); @@ -258,7 +258,7 @@ private void promptBankRemove(final CommandSender sender, String[] args) { } else { bank = bankUtils.lookupBank(args[1]); if (bank == null) { - plugin.debug("No bank could be found under the identifier " + args[1]); + plugin.debug("No bank could be found with the name or ID \"" + args[1] + "\""); sender.sendMessage(String.format(Messages.BANK_NOT_FOUND, args[1])); return; } @@ -347,7 +347,7 @@ private void promptBankInfo(CommandSender sender, String[] args) { } else { bank = bankUtils.lookupBank(args[1]); if (bank == null) { - plugin.debug("No bank could be found under the identifier \"" + args[1] + "\""); + plugin.debug("No bank could be found with the name or ID \"" + args[1] + "\""); sender.sendMessage(String.format(Messages.BANK_NOT_FOUND, "\"" + args[1] + "\"")); return; } @@ -476,7 +476,7 @@ else if (args.length == 2) { bank = bankUtils.lookupBank(args[1]); if (bank == null) { - plugin.debug("No bank could be found under the identifier " + args[1]); + plugin.debug("No bank could be found with the name or ID \"" + args[1] + "\""); p.sendMessage(String.format(Messages.BANK_NOT_FOUND, args[1])); return true; } @@ -496,7 +496,7 @@ else if (args.length == 2) { return true; } long volume = selection.getVolume(); - int volumeLimit = bankUtils.getVolumeLimit(p); + long volumeLimit = bankUtils.getVolumeLimit(p); if (bank.isPlayerBank() && volumeLimit != -1 && volume > volumeLimit) { plugin.debug("Bank is too large (" + volume + " blocks, limit: " + volumeLimit + ")"); p.sendMessage(String.format(Messages.SELECTION_TOO_LARGE_RESIZE, volumeLimit, volume - volumeLimit)); @@ -631,7 +631,7 @@ private boolean promptBankSet(CommandSender sender, String[] args) { String value = sb.toString(); if (bank == null) { - plugin.debug("No bank could be found under the identifier " + args[1]); + plugin.debug("No bank could be found with the name or ID \"" + args[1] + "\""); sender.sendMessage(String.format(Messages.BANK_NOT_FOUND, args[1])); return true; } @@ -706,7 +706,7 @@ private void promptBankSelect(Player p, String[] args) { } else { bank = bankUtils.lookupBank(args[1]); if (bank == null) { - plugin.debug("No bank could be found under the identifier " + args[1]); + plugin.debug("No bank could be found with the name or ID \"" + args[1] + "\""); p.sendMessage(String.format(Messages.BANK_NOT_FOUND, args[1])); return; } @@ -756,7 +756,7 @@ private boolean promptBankTransfer(CommandSender sender, String[] args) { } else { bank = bankUtils.lookupBank(args[1]); if (bank == null) { - plugin.debug("No bank could be found under the identifier " + args[1]); + plugin.debug("No bank could be found with the name or ID \"" + args[1] + "\""); sender.sendMessage(String.format(Messages.BANK_NOT_FOUND, args[1])); return true; } diff --git a/src/main/java/com/monst/bankingplugin/commands/control/ControlCommandExecutor.java b/src/main/java/com/monst/bankingplugin/commands/control/ControlCommandExecutor.java index 908f1afd..83cd5bc8 100644 --- a/src/main/java/com/monst/bankingplugin/commands/control/ControlCommandExecutor.java +++ b/src/main/java/com/monst/bankingplugin/commands/control/ControlCommandExecutor.java @@ -176,7 +176,7 @@ private void checkUpdates(CommandSender sender) { // sender.sendMessage(Messages.UPDATE_CHECKING); - UpdateChecker uc = new UpdateChecker(BankingPlugin.getInstance()); + UpdateChecker uc = new UpdateChecker(plugin); UpdateChecker.UpdateCheckerResult result = uc.check(); if (result == UpdateChecker.UpdateCheckerResult.TRUE) { diff --git a/src/main/java/com/monst/bankingplugin/config/Config.java b/src/main/java/com/monst/bankingplugin/config/Config.java index 31b91a15..3c10128e 100644 --- a/src/main/java/com/monst/bankingplugin/config/Config.java +++ b/src/main/java/com/monst/bankingplugin/config/Config.java @@ -144,7 +144,7 @@ public class Config { * The default bank volume limit for players whose limit is not set via a * permission. */ - public static int maximumBankVolume; + public static long maximumBankVolume; /** * Whether a bank owner should be allowed to create an account at their own @@ -481,7 +481,7 @@ public void reload() { defaultBankLimit = config.getInt("default-limits.bank"); defaultAccountLimit = config.getInt("default-limits.account"); minimumBankVolume = Math.max(config.getInt("bank-size-limits.minimum"), 0); - maximumBankVolume = Math.max(config.getInt("bank-size-limits.maximum"), 0); + maximumBankVolume = Math.max(config.getLong("bank-size-limits.maximum"), 0); allowSelfBanking = config.getBoolean("allow-self-banking"); confirmOnRemove = config.getBoolean("confirm-on-remove"); confirmOnRemoveAll = config.getBoolean("confirm-on-removeall"); diff --git a/src/main/java/com/monst/bankingplugin/events/control/ReloadEvent.java b/src/main/java/com/monst/bankingplugin/events/control/ReloadEvent.java index 85e8069f..c55c7ee8 100644 --- a/src/main/java/com/monst/bankingplugin/events/control/ReloadEvent.java +++ b/src/main/java/com/monst/bankingplugin/events/control/ReloadEvent.java @@ -5,7 +5,7 @@ import org.bukkit.event.Cancellable; /** - * Called when a player reloads the shops + * Called when a player reloads the plugin */ public class ReloadEvent extends ControlEvent implements Cancellable { diff --git a/src/main/java/com/monst/bankingplugin/external/WorldGuardBankingFlag.java b/src/main/java/com/monst/bankingplugin/external/WorldGuardBankingFlag.java index 563115b8..8dcf79fb 100644 --- a/src/main/java/com/monst/bankingplugin/external/WorldGuardBankingFlag.java +++ b/src/main/java/com/monst/bankingplugin/external/WorldGuardBankingFlag.java @@ -11,10 +11,11 @@ public class WorldGuardBankingFlag { public static void register(final BankingPlugin plugin) { - WorldGuardWrapper wrapper = WorldGuardWrapper.getInstance(); - Optional> createBankFlag = wrapper.registerFlag("create-bank", WrappedState.class, - Config.wgAllowCreateBankDefault ? WrappedState.ALLOW : WrappedState.DENY); + Optional> createBankFlag = WorldGuardWrapper.getInstance() + .registerFlag("create-bank", WrappedState.class, Config.wgAllowCreateBankDefault + ? WrappedState.ALLOW + : WrappedState.DENY); plugin.debug("Flag create-bank: " + createBankFlag.isPresent()); } diff --git a/src/main/java/com/monst/bankingplugin/gui/AccountContentsGui.java b/src/main/java/com/monst/bankingplugin/gui/AccountContentsGui.java index 4a092ffb..9afae6a2 100644 --- a/src/main/java/com/monst/bankingplugin/gui/AccountContentsGui.java +++ b/src/main/java/com/monst/bankingplugin/gui/AccountContentsGui.java @@ -11,7 +11,7 @@ import org.ipvp.canvas.slot.Slot; import org.ipvp.canvas.type.ChestMenu; -public class AccountContentsGui extends Gui { +public class AccountContentsGui extends SinglePageGui { boolean canEdit; @@ -20,7 +20,7 @@ public AccountContentsGui(Account account) { } @Override - void createMenu() { + void initializeMenu() { menu = ChestMenu.builder(guiSubject.getSize() * 3).title(guiSubject.getColorizedName()).redraw(true).build(); } @@ -81,10 +81,10 @@ public ShulkerContentsGui(Account account, ShulkerBox shulkerBox) { } @Override - void createMenu() { + void initializeMenu() { menu = ChestMenu.builder(3).title( shulkerBox.getCustomName() != null - ? shulkerBox.getCustomName() + ? shulkerBox.getCustomName() // TODO: Figure out why always null : WordUtils.capitalizeFully(shulkerBox.getColor().toString()) + " Shulker Box" ).redraw(true).build(); } @@ -99,5 +99,9 @@ Slot.ClickHandler createClickHandler(int i) { return null; } + @Override + GuiType getType() { + return GuiType.ACCOUNT_SHULKER_CONTENTS; + } } } diff --git a/src/main/java/com/monst/bankingplugin/gui/AccountGui.java b/src/main/java/com/monst/bankingplugin/gui/AccountGui.java index c0378ec2..e0c707b7 100644 --- a/src/main/java/com/monst/bankingplugin/gui/AccountGui.java +++ b/src/main/java/com/monst/bankingplugin/gui/AccountGui.java @@ -21,7 +21,7 @@ import java.util.List; import java.util.stream.Collectors; -public class AccountGui extends Gui { +public class AccountGui extends SinglePageGui { boolean isTrusted; boolean canTP; @@ -31,7 +31,7 @@ public AccountGui(Account account) { } @Override - void createMenu() { + void initializeMenu() { menu = ChestMenu.builder(1).title(guiSubject.getColorizedName()).build(); } @@ -60,7 +60,7 @@ ItemStack createSlotItem(int i) { case 4: if (isTrusted) return createSlotItem(Material.NETHER_STAR, "Current Multiplier", Utils.getMultiplierLore(guiSubject)); - return createSlotItem(Material.NETHER_STAR, "Multipliers", Utils.getMultiplierLore(guiSubject.getBank())); + return createSlotItem(Material.NETHER_STAR, "Bank Multipliers", Utils.getMultiplierLore(guiSubject.getBank())); case 5: if (isTrusted) return createSlotItem(Material.IRON_BARS, "Account Restrictions", getAccountRestrictionsLore()); @@ -154,19 +154,19 @@ private List getAccountRestrictionsLore() { int untilReset = status.getRemainingOfflineUntilReset(); int offlineDecrement = guiSubject.getBank().getAccountConfig().get(AccountConfig.Field.OFFLINE_MULTIPLIER_DECREMENT); return Utils.wordWrapAll( - ChatColor.GRAY + (delay == 0 + (delay == 0 ? "Account will generate interest in the next payout cycle." : "Account will begin generating interest in " + ChatColor.AQUA + delay + ChatColor.GRAY + String.format(" payout cycle%s.", delay == 1 ? "" : "s")), - ChatColor.GRAY + "Account can generate interest for " + ChatColor.AQUA + remainingOffline + ChatColor.GRAY + String.format(" offline payout cycle%s.", remainingOffline == 1 ? "" : "s"), + "Account can generate interest for " + ChatColor.AQUA + remainingOffline + ChatColor.GRAY + String.format(" offline payout cycle%s.", remainingOffline == 1 ? "" : "s"), - ChatColor.GRAY + "Account multiplier will " + (untilReset < 0 + "Account multiplier will " + (untilReset < 0 ? "not reset while offline." : (untilReset == 0 ? "reset immediately on an offline payout." : "reset after " + ChatColor.AQUA + untilReset + ChatColor.GRAY + String.format(" offline payout cycle%s.", untilReset == 1 ? "" : "s"))), - ChatColor.GRAY + "Account multiplier will " + (offlineDecrement < 0 + "Account multiplier will " + (offlineDecrement < 0 ? "decrease by " + ChatColor.AQUA + offlineDecrement + ChatColor.GRAY + " stages for every offline payout." : (offlineDecrement == 0 ? " freeze while offline." : " reset")) ); diff --git a/src/main/java/com/monst/bankingplugin/gui/AccountListGui.java b/src/main/java/com/monst/bankingplugin/gui/AccountListGui.java index 3ee84294..a9cfddfa 100644 --- a/src/main/java/com/monst/bankingplugin/gui/AccountListGui.java +++ b/src/main/java/com/monst/bankingplugin/gui/AccountListGui.java @@ -3,7 +3,6 @@ import com.monst.bankingplugin.Account; import com.monst.bankingplugin.Bank; import org.bukkit.Material; -import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.ipvp.canvas.Menu; import org.ipvp.canvas.mask.BinaryMask; @@ -16,35 +15,15 @@ import org.ipvp.canvas.type.ChestMenu; import java.util.Collections; -import java.util.List; -public class AccountListGui extends Gui { - - private static final int PREV_SLOT = 18; - private static final int NEXT_SLOT = 26; - - private List pages; - private int currentPage = 0; +public class AccountListGui extends MultiPageGui { public AccountListGui(Bank bank) { - super(bank); + super(bank, 18, 26); } @Override - void open(Player player, boolean update) { - if (update) { - createMenu(); - setClickHandler(); - setCloseHandler(OPEN_PREVIOUS); - shortenGuiChain(); - } - if (pages.isEmpty()) - return; - pages.get(currentPage).open(player); - } - - @Override - void createMenu() { + void initializeMenu() { @SuppressWarnings("rawtypes") Menu.Builder pageTemplate = ChestMenu.builder(3).title("Account List").redraw(true); Mask itemSlots = BinaryMask.builder(pageTemplate.getDimensions()) @@ -66,34 +45,6 @@ void createMenu() { pages = builder.build(); } - private void setClickHandler() { - for (Menu page : pages) { - for (Slot slot : new Slot[]{page.getSlot(PREV_SLOT), page.getSlot(NEXT_SLOT)}) { - //noinspection SimplifyOptionalCallChains - Slot.ClickHandler prevHandler = slot.getClickHandler().orElse(null); - if (prevHandler != null) - slot.setClickHandler((player, info) -> { - prevHandler.click(player, info); - currentPage--; - }); - } - } - } - - @Override - void evaluateClearance(Player player) { - } - - @Override - ItemStack createSlotItem(int i) { - return null; - } - - @Override - Slot.ClickHandler createClickHandler(int i) { - return null; - } - @Override void setCloseHandler(Menu.CloseHandler handler) { pages.forEach(page -> page.setCloseHandler(handler)); diff --git a/src/main/java/com/monst/bankingplugin/gui/BankGui.java b/src/main/java/com/monst/bankingplugin/gui/BankGui.java index 176c671a..c31bd1c1 100644 --- a/src/main/java/com/monst/bankingplugin/gui/BankGui.java +++ b/src/main/java/com/monst/bankingplugin/gui/BankGui.java @@ -21,9 +21,8 @@ import java.util.List; import java.util.stream.Collectors; -public class BankGui extends Gui { +public class BankGui extends SinglePageGui { - boolean verbose; boolean canTP; boolean canListAccounts; @@ -32,15 +31,12 @@ public BankGui(Bank bank) { } @Override - void createMenu() { + void initializeMenu() { menu = ChestMenu.builder(2).title(guiSubject.getColorizedName()).build(); } @Override void evaluateClearance(Player player) { - verbose = guiSubject.isTrusted(player) - || (guiSubject.isAdminBank() && player.hasPermission(Permissions.BANK_INFO_ADMIN) - || (guiSubject.isPlayerBank() && player.hasPermission(Permissions.BANK_INFO_OTHER))); canTP = player.isOp() || player.hasPermission("minecraft.command.tp") || player.hasPermission("essentials.tp.position"); @@ -71,7 +67,7 @@ ItemStack createSlotItem(int i) { case 12: return createSlotItem(Material.LIGHT_BLUE_BED, "Offline Payouts", getOfflinePayoutsLore()); case 13: - return createSlotItem(Material.CLOCK, "Interest Delay", getInterestDelayLore()); + return createSlotItem(Material.COMPASS, "Interest Delay", getInterestDelayLore()); case 14: return createSlotItem(Material.BELL, "Withdrawal Policy", getWithdrawalPolicyLore()); case 15: @@ -124,7 +120,7 @@ private List getGeneralInfoLore() { : ChatColor.AQUA + guiSubject.getCoowners().stream().map(OfflinePlayer::getName) .collect(Collectors.joining(", ", "[ ", " ]"))) ); - lore.add(ChatColor.GRAY + "Location: " + ChatColor.AQUA + guiSubject.getSelection().getCoordinates()); + lore.add("Location: " + ChatColor.AQUA + guiSubject.getSelection().getCoordinates()); if (canTP) lore.add("Click to teleport to bank."); return Utils.wordWrapAll(lore); @@ -149,8 +145,8 @@ private List getCreationLore() { AccountConfig config = guiSubject.getAccountConfig(); boolean reimburse = config.get(AccountConfig.Field.REIMBURSE_ACCOUNT_CREATION); return Arrays.asList( - ChatColor.GRAY + "Fee: " + ChatColor.GREEN + "$" + config.getFormatted(AccountConfig.Field.ACCOUNT_CREATION_PRICE), - ChatColor.GRAY + "Reimbursed on removal: " + (reimburse ? ChatColor.GREEN + "Yes" : ChatColor.RED + "No") + "Fee: " + ChatColor.GREEN + "$" + config.getFormatted(AccountConfig.Field.ACCOUNT_CREATION_PRICE), + "Reimbursed on removal: " + (reimburse ? ChatColor.GREEN + "Yes" : ChatColor.RED + "No") ); } @@ -161,11 +157,11 @@ private List getBalanceRestrictionLore() { boolean strikethrough = minBalance == 0; boolean payOnLowBalance = config.get(AccountConfig.Field.PAY_ON_LOW_BALANCE); return Utils.wordWrapAll(38, - ChatColor.GRAY + "Minimum balance: " + ChatColor.GREEN + "$" + Utils.format(minBalance), - ChatColor.GRAY + "Low balance fee: " + ChatColor.RED + "Minimum balance: " + ChatColor.GREEN + "$" + Utils.format(minBalance), + "Low balance fee: " + ChatColor.RED + (strikethrough ? ChatColor.STRIKETHROUGH : "") + "$" + Utils.format(lowBalanceFee), "", - ChatColor.GRAY + "Interest " + (payOnLowBalance ? ChatColor.GREEN + "will" : ChatColor.RED + "will not") + "Interest " + (payOnLowBalance ? ChatColor.GREEN + "will" : ChatColor.RED + "will not") + " continue " + ChatColor.GRAY + "to be paid out when the account balance is low." ); } @@ -176,21 +172,21 @@ private List getOfflinePayoutsLore() { int offlineDecrement = config.get(AccountConfig.Field.OFFLINE_MULTIPLIER_DECREMENT); int beforeReset = config.get(AccountConfig.Field.ALLOWED_OFFLINE_PAYOUTS_BEFORE_RESET); List lore = new ArrayList<>(); - lore.add(ChatColor.GRAY + "Accounts will " + (offlinePayouts == 0 + lore.add("Accounts will " + (offlinePayouts == 0 ? ChatColor.RED + "not generate interest" + ChatColor.GRAY : "generate interest up to " + ChatColor.AQUA + offlinePayouts + ChatColor.GRAY + String.format(" time%s", offlinePayouts == 1 ? "" : "s")) + " while account holders are offline."); if (beforeReset != 0) { lore.add(""); - lore.add(ChatColor.GRAY + "Account multipliers will " + (offlineDecrement == 0 + lore.add("Account multipliers will " + (offlineDecrement == 0 ? ChatColor.AQUA + "freeze" + ChatColor.GRAY : "decrease by " + ChatColor.AQUA + offlineDecrement + ChatColor.GRAY + " for every payout") + " during this time."); } if (beforeReset > -1) { lore.add(""); - lore.add(ChatColor.GRAY + "Multipliers will reset " + (beforeReset == 0 + lore.add("Multipliers will reset " + (beforeReset == 0 ? ChatColor.RED + "before paying out interest" + ChatColor.GRAY : "after generating interest " + ChatColor.AQUA + beforeReset + ChatColor.GRAY + String.format(" time%s", beforeReset == 1 ? "" : "s")) + " while account holders are offline."); @@ -203,13 +199,13 @@ private List getInterestDelayLore() { int interestDelay = config.get(AccountConfig.Field.INITIAL_INTEREST_DELAY); boolean countOffline = config.get(AccountConfig.Field.COUNT_INTEREST_DELAY_OFFLINE); List lore = new ArrayList<>(); - lore.add(ChatColor.GRAY + "New accounts will begin to generate interest " + (interestDelay == 0 + lore.add("New accounts will begin to generate interest " + (interestDelay == 0 ? ChatColor.GREEN + "immediately" + ChatColor.GRAY + " after creation." : "after " + ChatColor.AQUA + interestDelay + ChatColor.GRAY + String.format(" preliminary interest cycle%s.", interestDelay == 1 ? "" : "s"))); if (interestDelay != 0) { lore.add(""); - lore.add(ChatColor.GRAY + "The account owner " + (countOffline + lore.add("The account owner " + (countOffline ? ChatColor.GREEN + "does not have to be online" : ChatColor.RED + "must be online") + ChatColor.GRAY + " for these cycles to be counted toward the delay."); @@ -220,7 +216,7 @@ private List getInterestDelayLore() { private List getWithdrawalPolicyLore() { int withdrawalDecrement = guiSubject.getAccountConfig().get(AccountConfig.Field.WITHDRAWAL_MULTIPLIER_DECREMENT); return Utils.wordWrapAll( - ChatColor.GRAY + "Account multipliers will " + (withdrawalDecrement == 0 + "Account multipliers will " + (withdrawalDecrement == 0 ? ChatColor.GREEN + "not be affected on" + ChatColor.GRAY : "decrease by " + ChatColor.AQUA + withdrawalDecrement + ChatColor.GRAY + String.format(" stage%s upon each", withdrawalDecrement == 1 ? "" : "s")) + " withdrawal." @@ -230,7 +226,7 @@ private List getWithdrawalPolicyLore() { private List getAccountLimitLore() { int accountLimit = guiSubject.getAccountConfig().get(AccountConfig.Field.PLAYER_BANK_ACCOUNT_LIMIT); return Utils.wordWrapAll( - ChatColor.GRAY + (accountLimit == 0 + (accountLimit == 0 ? "Account creation is currently " + ChatColor.RED + "disabled" + ChatColor.GRAY : "Players may create " + (accountLimit > 0 ? "up to " + ChatColor.AQUA + accountLimit @@ -243,11 +239,11 @@ private List getPayoutTimeLore() { List times = guiSubject.getAccountConfig().get(AccountConfig.Field.INTEREST_PAYOUT_TIMES); List lore = new ArrayList<>(); if (!times.isEmpty()) { - lore.add(ChatColor.GRAY + "Accounts will generate interest every day at: "); + lore.add("Accounts will generate interest every day at: "); for (LocalTime time : times) lore.add(ChatColor.GOLD + " - " + time.toString()); } else - lore.add(ChatColor.GRAY + "Accounts will not generate interest."); + lore.add("Accounts will not generate interest."); return Utils.wordWrapAll(lore); } } diff --git a/src/main/java/com/monst/bankingplugin/gui/Gui.java b/src/main/java/com/monst/bankingplugin/gui/Gui.java index e6fccf52..4a8179f2 100644 --- a/src/main/java/com/monst/bankingplugin/gui/Gui.java +++ b/src/main/java/com/monst/bankingplugin/gui/Gui.java @@ -2,7 +2,7 @@ import com.monst.bankingplugin.BankingPlugin; import com.monst.bankingplugin.utils.Ownable; -import net.md_5.bungee.api.ChatColor; +import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; @@ -11,7 +11,6 @@ import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.scheduler.BukkitRunnable; import org.ipvp.canvas.Menu; -import org.ipvp.canvas.slot.Slot.ClickHandler; import javax.annotation.Nullable; import java.util.Collections; @@ -23,8 +22,7 @@ abstract class Gui { static final BankingPlugin plugin = BankingPlugin.getInstance(); final T guiSubject; - Menu menu; - Gui prevGui; + Gui prevGui; boolean openInBackground = false; static final List NO_PERMISSION = Collections.singletonList("You do not have permission to view this."); @@ -46,42 +44,19 @@ public void open(Player player) { open(player, true); } - void open(Player player, boolean update) { - if (update) { - createMenu(); - setCloseHandler(OPEN_PREVIOUS); - shortenGuiChain(); - } - evaluateClearance(player); - for (int i = 0; i < menu.getDimensions().getArea(); i++) { - menu.getSlot(i).setItem(createSlotItem(i)); - menu.getSlot(i).setClickHandler(createClickHandler(i)); - } - menu.open(player); - } - - @SuppressWarnings({"rawtypes", "unchecked"}) - public Gui setPrevGui(@Nullable Gui prevGui) { - if (prevGui != null) - prevGui.openInBackground = true; - this.prevGui = prevGui; - return this; - } - - abstract void createMenu(); - - abstract void evaluateClearance(Player player); - - abstract ItemStack createSlotItem(int i); + abstract void open(Player player, boolean update); - abstract ClickHandler createClickHandler(int i); + abstract void initializeMenu(); abstract void setCloseHandler(Menu.CloseHandler handler); abstract GuiType getType(); - static ItemStack createSlotItem(Material material, String displayName, List lore) { - return createSlotItem(new ItemStack(material), displayName, lore); + public Gui setPrevGui(@Nullable Gui prevGui) { + if (prevGui != null) + prevGui.openInBackground = true; + this.prevGui = prevGui; + return this; } /** @@ -100,6 +75,10 @@ static ItemStack createSlotItem(OfflinePlayer owner, String displayName, List lore) { + return createSlotItem(new ItemStack(material), displayName, lore); + } + /** * Create an {@link ItemStack} to be placed in the Gui. * @param item the {@link ItemStack} that should be used for the item @@ -117,25 +96,24 @@ private static ItemStack createSlotItem(ItemStack item, String displayName, List return item; } + void shortenGuiChain() { + shortenGuiChain(this, EnumSet.noneOf(GuiType.class)); + } + /** * Descends down the list of previous open Guis, and severs the link when it * finds a Gui of a type it has seen before. This prevents the Gui chain * from becoming too long and unwieldy. */ - void shortenGuiChain() { - shortenGuiChain(this, EnumSet.noneOf(GuiType.class)); - } - - private void shortenGuiChain(Gui gui, EnumSet types) { - Gui previous = gui.prevGui; + private void shortenGuiChain(Gui gui, EnumSet types) { + Gui previous = gui.prevGui; if (previous == null) return; if (!types.contains(previous.getType())) { types.add(previous.getType()); shortenGuiChain(previous, types); - } else { + } else gui.prevGui = null; - } } boolean isOpenInBackground() { @@ -147,6 +125,6 @@ boolean isLinked() { } enum GuiType { - ACCOUNT, ACCOUNT_LIST, ACCOUNT_CONTENTS, BANK + ACCOUNT, ACCOUNT_LIST, ACCOUNT_CONTENTS, ACCOUNT_SHULKER_CONTENTS, BANK } } diff --git a/src/main/java/com/monst/bankingplugin/gui/MultiPageGui.java b/src/main/java/com/monst/bankingplugin/gui/MultiPageGui.java new file mode 100644 index 00000000..6dcb27fe --- /dev/null +++ b/src/main/java/com/monst/bankingplugin/gui/MultiPageGui.java @@ -0,0 +1,51 @@ +package com.monst.bankingplugin.gui; + +import com.monst.bankingplugin.utils.Ownable; +import org.bukkit.entity.Player; +import org.ipvp.canvas.Menu; +import org.ipvp.canvas.slot.Slot; + +import java.util.List; + +abstract class MultiPageGui extends Gui { + + final int PREV_SLOT; + final int NEXT_SLOT; + + List pages; + int currentPage = 0; + + MultiPageGui(T guiSubject, int prevSlot, int nextSlot) { + super(guiSubject); + PREV_SLOT = prevSlot; + NEXT_SLOT = nextSlot; + } + + @Override + void open(Player player, boolean update) { + if (update) { + initializeMenu(); + setClickHandler(); + setCloseHandler(OPEN_PREVIOUS); + shortenGuiChain(); + } + if (pages.isEmpty()) + return; + pages.get(currentPage).open(player); + } + + void setClickHandler() { + for (Menu page : pages) { + for (Slot slot : new Slot[]{page.getSlot(PREV_SLOT), page.getSlot(NEXT_SLOT)}) { + //noinspection SimplifyOptionalCallChains + Slot.ClickHandler prevHandler = slot.getClickHandler().orElse(null); + if (prevHandler != null) + slot.setClickHandler((player, info) -> { + prevHandler.click(player, info); + currentPage--; + }); + } + } + } + +} diff --git a/src/main/java/com/monst/bankingplugin/gui/SinglePageGui.java b/src/main/java/com/monst/bankingplugin/gui/SinglePageGui.java new file mode 100644 index 00000000..1cdf6a79 --- /dev/null +++ b/src/main/java/com/monst/bankingplugin/gui/SinglePageGui.java @@ -0,0 +1,37 @@ +package com.monst.bankingplugin.gui; + +import com.monst.bankingplugin.utils.Ownable; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.ipvp.canvas.Menu; +import org.ipvp.canvas.slot.Slot; + +abstract class SinglePageGui extends Gui { + + Menu menu; + + SinglePageGui(T guiSubject) { + super(guiSubject); + } + + void open(Player player, boolean update) { + if (update) { + initializeMenu(); + setCloseHandler(OPEN_PREVIOUS); + shortenGuiChain(); + } + evaluateClearance(player); + for (int i = 0; i < menu.getDimensions().getArea(); i++) { + menu.getSlot(i).setItem(createSlotItem(i)); + menu.getSlot(i).setClickHandler(createClickHandler(i)); + } + menu.open(player); + } + + abstract void evaluateClearance(Player player); + + abstract ItemStack createSlotItem(int i); + + abstract Slot.ClickHandler createClickHandler(int i); + +} diff --git a/src/main/java/com/monst/bankingplugin/sql/Database.java b/src/main/java/com/monst/bankingplugin/sql/Database.java index 3400b5a9..9476f8be 100644 --- a/src/main/java/com/monst/bankingplugin/sql/Database.java +++ b/src/main/java/com/monst/bankingplugin/sql/Database.java @@ -392,10 +392,8 @@ public void run() { ps.setString(i + 8, sb.toString()); } else { - plugin.getLogger() - .severe("Bank selection neither cuboid nor polygonal! (#" + bank.getID() + ")"); plugin.debug("Bank selection neither cuboid nor polygonal! (#" + bank.getID() + ")"); - return; // This should never happen + throw new IllegalStateException("Bank selection neither cuboid nor polygonal! (#" + bank.getID() + ")"); } AccountConfig config = bank.getAccountConfig(); diff --git a/src/main/java/com/monst/bankingplugin/utils/BankUtils.java b/src/main/java/com/monst/bankingplugin/utils/BankUtils.java index 08c5238d..50634f6e 100644 --- a/src/main/java/com/monst/bankingplugin/utils/BankUtils.java +++ b/src/main/java/com/monst/bankingplugin/utils/BankUtils.java @@ -113,9 +113,9 @@ public boolean isExclusiveSelectionWithoutThis(Selection sel, Bank bank) { } public void resizeBank(Bank bank, Selection newSel) { - bankSelectionMap.remove(bank.getSelection()); - bankSelectionMap.put(newSel, bank); + removeBank(bank, false); bank.setSelection(newSel); + addBank(bank, false); } public Selection parseCoordinates(String[] args, Location loc, int offset) throws NumberFormatException { @@ -187,16 +187,17 @@ public boolean containsAllAccounts(Bank bank, Selection sel) { * had or was given (as {@code int}) */ public void addBank(Bank bank, boolean addToDatabase, Callback callback) { - plugin.debug("Adding bank... (#" + bank.getID() + ")"); + plugin.debug("Adding/updating bank... (#" + bank.getID() + ")"); bankSelectionMap.put(bank.getSelection(), bank); - if (addToDatabase) { + if (bankSelectionMap.values().stream().filter(b -> b.equals(bank)).count() > 1) + plugin.debug("ERROR! Bank #" + bank.getID() + " entered more than once on bankSelMap"); + + if (addToDatabase) plugin.getDatabase().addBank(bank, callback); - } else { - if (callback != null) + else if (callback != null) callback.callSyncResult(bank.getID()); - } } @@ -223,11 +224,10 @@ public void removeBank(Bank bank, boolean removeFromDatabase, Callback cal bankSelectionMap.remove(bank.getSelection()); - if (removeFromDatabase) { + if (removeFromDatabase) plugin.getDatabase().removeBank(bank, callback); - } else { - if (callback != null) callback.callSyncResult(null); - } + else if (callback != null) + callback.callSyncResult(null); } /** @@ -285,11 +285,11 @@ public int getBankLimit(Player player) { } if (limit < -1) limit = -1; - return (useDefault ? Config.defaultBankLimit : limit); + return useDefault ? Config.defaultBankLimit : limit; } - public int getVolumeLimit(Player player) { - int limit = 0; + public long getVolumeLimit(Player player) { + long limit = 0; boolean useDefault = true; for (PermissionAttachmentInfo permInfo : player.getEffectivePermissions()) { @@ -304,7 +304,7 @@ public int getVolumeLimit(Player player) { if (spl.length > 1) { try { - int newLimit = Integer.parseInt(spl[1]); + long newLimit = Long.parseLong(spl[1]); if (newLimit < 0) { limit = -1; break; @@ -318,7 +318,7 @@ public int getVolumeLimit(Player player) { } if (limit < -1) limit = -1; - return (useDefault ? Config.maximumBankVolume : limit); + return useDefault ? Config.maximumBankVolume : limit; } /** diff --git a/src/main/java/com/monst/bankingplugin/utils/Messages.java b/src/main/java/com/monst/bankingplugin/utils/Messages.java index f6724fa1..357c9745 100644 --- a/src/main/java/com/monst/bankingplugin/utils/Messages.java +++ b/src/main/java/com/monst/bankingplugin/utils/Messages.java @@ -78,7 +78,7 @@ public class Messages { public static final String CHEST_NOT_IN_BANK = ChatColor.RED + "That chest is not located within a bank."; public static final String NOT_STANDING_IN_BANK = ChatColor.RED + "You must stand in or specify the name of a bank."; public static final String ACCOUNT_CREATE_INSUFFICIENT_FUNDS = ChatColor.RED + "You do not have sufficient funds to create an account at this bank."; - public static final String BANK_NOT_FOUND = ChatColor.RED + "No bank was found under the identifier \"%s\"."; + public static final String BANK_NOT_FOUND = ChatColor.RED + "No bank was found with the name or ID \"%s\"."; public static final String NO_ACCOUNTS_FOUND = ChatColor.RED + "There are no accounts to list."; public static final String NO_PLAYER_ACCOUNTS = ChatColor.RED + "That player does not own any accounts."; public static final String NO_BANK_ACCOUNTS = ChatColor.RED + "There are no accounts at that bank."; diff --git a/src/main/java/com/monst/bankingplugin/utils/Permissions.java b/src/main/java/com/monst/bankingplugin/utils/Permissions.java index d4f0a919..03465395 100644 --- a/src/main/java/com/monst/bankingplugin/utils/Permissions.java +++ b/src/main/java/com/monst/bankingplugin/utils/Permissions.java @@ -1,7 +1,6 @@ package com.monst.bankingplugin.utils; public class Permissions { - public static final String ACCOUNT_SET = "bankingplugin.account.set.*"; public static final String ACCOUNT_CREATE = "bankingplugin.account.create"; public static final String ACCOUNT_CREATE_OTHER = "bankingplugin.account.create.other"; @@ -30,8 +29,6 @@ public class Permissions { public static final String BANK_REMOVEALL = "bankingplugin.bank.removeall"; public static final String BANK_NO_LIMIT = "bankingplugin.bank.limit.*"; public static final String BANK_NO_SIZE_LIMIT = "bankingplugin.bank.size.*"; - public static final String BANK_INFO_OTHER = "bankingplugin.bank.info.other"; - public static final String BANK_INFO_ADMIN = "bankingplugin.bank.info.admin"; public static final String BANK_RESIZE_OTHER = "bankingplugin.bank.resize.other"; public static final String BANK_RESIZE_ADMIN = "bankingplugin.bank.resize.admin"; public static final String BANK_TRANSFER = "bankingplugin.bank.transfer"; diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index b63fc025..56870b2b 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -182,7 +182,7 @@ default-limits: # Set the volume limit for anyone who doesn't have a specific permission here. # The minimum volume cannot by bypassed by a permission. # Admin banks are exempt from these restrictions. -# Type: int +# Type: int, long bank-size-limits: minimum: 125 maximum: 100000 diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index f0739f8f..96b6c47c 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -62,8 +62,6 @@ permissions: bankingplugin.bank.removeall: true bankingplugin.bank.limit.*: true bankingplugin.bank.size.*: true - bankingplugin.bank.info.other: true - bankingplugin.bank.info.admin: true bankingplugin.bank.resize.other: true bankingplugin.bank.resize.admin: true bankingplugin.bank.transfer: true @@ -99,7 +97,7 @@ permissions: default: op bankingplugin.account.info-other: - description: View detailed information about another player's account. + description: View detailed information about another player's account as if you were owner or co-owner. default: op bankingplugin.account.list-other: @@ -117,13 +115,13 @@ permissions: bankingplugin.account.view-other: true bankingplugin.account.migrate.other: - description: Migrate another player's account chest to another chest. + description: Migrate the account chest of another player to a different chest. default: op children: bankingplugin.account.create: true bankingplugin.account.migrate.bank: - description: Migrate an account to another chest in a different bank. + description: Migrate an account to a chest in a different bank. default: op children: bankingplugin.account.create: true @@ -143,6 +141,9 @@ permissions: bankingplugin.account.extend-other: description: Extend another player's account chest. default: op + # NOTE: To extend another player's account chest on protected land, players need both of the following permissions: + # - bankingplugin.account.extend-other + # - bankingplugin.account.create.protected bankingplugin.account.limit.*: description: Create an unlimited number of accounts. @@ -163,7 +164,7 @@ permissions: # BANK # bankingplugin.bank.create: - description: Create, manage, and remove banks of your own. + description: Create, manage, and remove player banks under your own name. default: true bankingplugin.bank.create.admin: @@ -171,21 +172,22 @@ permissions: default: op bankingplugin.bank.remove.other: - description: Remove another player's bank and all associated accounts. + description: Remove another player's bank and all accounts at that bank. default: op children: bankingplugin.account.remove-other: true bankingplugin.bank.remove.admin: - description: Remove an admin bank and all associated accounts. + description: Remove an admin bank and all accounts at that bank. default: op children: - bankingplugin.bank.remove.other: true + bankingplugin.account.remove-other: true bankingplugin.bank.removeall: - description: Remove all banks and all accounts. + description: Remove all banks and all accounts on the server. default: op children: + bankingplugin.bank.remove.other: true bankingplugin.bank.remove.admin: true bankingplugin.bank.limit.*: @@ -196,14 +198,6 @@ permissions: description: Create a bank of unlimited volume. default: op - bankingplugin.bank.info.other: - description: View detailed information about another player's bank. - default: op - - bankingplugin.bank.info.admin: - description: View detailed information about an admin bank. - default: op - bankingplugin.bank.resize.other: description: Resize another player's bank. default: op @@ -214,11 +208,11 @@ permissions: description: Resize an admin bank. default: op children: - bankingplugin.bank.resize.other: true + bankingplugin.bank.create.admin: true bankingplugin.bank.transfer: description: Transfer ownership of your bank to another player. - default: true + default: op children: bankingplugin.bank.create: true @@ -233,6 +227,9 @@ permissions: default: op children: bankingplugin.bank.transfer.other: true + # NOTE: To turn a player bank into an admin bank, players need both of the following permissions: + # - bankingplugin.bank.transfer(.other) + # - bankingplugin.bank.create.admin bankingplugin.bank.set.other: description: Configure another player's bank. @@ -241,9 +238,7 @@ permissions: bankingplugin.bank.set.admin: description: Configure an admin bank. default: op - children: - bankingplugin.bank.set.other: true - + # CONTROL # bankingplugin.external-bypass: description: Bypass other plugins' attempts to selectively prevent functionality of this plugin.