From c0388a2a01d1d4c9129b5b24556158e00e85d9de Mon Sep 17 00:00:00 2001 From: LlmDl <llmdlio@gmail.com> Date: Wed, 18 Oct 2023 10:23:41 -0500 Subject: [PATCH 1/8] Simplify Town Trust command, add catchNPCResident and ResidentNPCException --- .../bukkit/towny/command/BaseCommand.java | 6 ++ .../bukkit/towny/command/TownCommand.java | 90 ++++++++++--------- .../exceptions/ResidentNPCException.java | 17 ++++ Towny/src/main/resources/lang/en-US.yml | 5 +- 4 files changed, 74 insertions(+), 44 deletions(-) create mode 100644 Towny/src/main/java/com/palmergames/bukkit/towny/exceptions/ResidentNPCException.java diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/command/BaseCommand.java b/Towny/src/main/java/com/palmergames/bukkit/towny/command/BaseCommand.java index d30d68b5d4..393b05d30c 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/command/BaseCommand.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/command/BaseCommand.java @@ -3,6 +3,7 @@ import com.palmergames.bukkit.towny.TownyAPI; import com.palmergames.bukkit.towny.TownyUniverse; import com.palmergames.bukkit.towny.exceptions.NoPermissionException; +import com.palmergames.bukkit.towny.exceptions.ResidentNPCException; import com.palmergames.bukkit.towny.exceptions.TownyException; import com.palmergames.bukkit.towny.object.Nation; import com.palmergames.bukkit.towny.object.Resident; @@ -384,4 +385,9 @@ public static void checkPermOrThrow(Permissible permissible, String node) throws public static void checkPermOrThrowWithMessage(Permissible permissible, String node, Translatable errormsg) throws NoPermissionException { TownyUniverse.getInstance().getPermissionSource().testPermissionOrThrow(permissible, node, errormsg); } + + public static void catchNPCResident(Resident resident) throws ResidentNPCException { + if (resident.isNPC()) + throw new ResidentNPCException(); + } } diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownCommand.java b/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownCommand.java index f412f5ac72..e67308bbb5 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownCommand.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownCommand.java @@ -3947,7 +3947,7 @@ private void parseTownTakeoverClaimCommand(Player player) throws TownyException Town town = getTownFromPlayerOrThrow(player); long ageRequirement = TownySettings.getOverclaimingTownAgeRequirement(); - if (ageRequirement > 0l) { + if (ageRequirement > 0L) { long ageNeeded = System.currentTimeMillis() - ageRequirement; if (ageNeeded < town.getRegistered()) throw new TownyException(Translatable.of("msg_err_your_town_is_not_old_enough_to_overclaim", TimeMgmt.getFormattedTimeValue(town.getRegistered() - ageNeeded))); @@ -4358,66 +4358,70 @@ private void townOutlawList(CommandSender sender, String[] args) throws TownyExc public static void parseTownTrustCommand(CommandSender sender, String[] args, @Nullable Town town) throws TownyException { - if (args.length < 1 - || args.length < 2 && (args[0].equalsIgnoreCase("add") || args[0].equalsIgnoreCase("remove")) - || args.length == 1 && !args[0].equalsIgnoreCase("list")) { + if (args.length < 1) { HelpMenu.TOWN_TRUST_HELP.send(sender); return; } - + if (town == null && sender instanceof Player player) town = getTownFromPlayerOrThrow(player); if (args[0].equalsIgnoreCase("list")) { - List<String> output = town.getTrustedResidents().isEmpty() - ? Collections.singletonList(Translatable.of("status_no_town").forLocale(sender)) // String which is "None". - : town.getTrustedResidents().stream().map(res -> res.getName()).collect(Collectors.toList()); - TownyMessaging.sendMessage(sender, TownyFormatter.getFormattedStrings(Translatable.of("status_trustedlist").forLocale(sender), output)); + parseTownTrustListCommand(sender, town); + return; + } + + if (args.length < 2) { + HelpMenu.TOWN_TRUST_HELP.send(sender); return; } checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_TRUST.getNode()); + Resident resident = getResidentOrThrow(args[1]); + catchNPCResident(resident); - Resident resident = TownyAPI.getInstance().getResident(args[1]); - if (resident == null || resident.isNPC()) { - TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_err_not_registered_1", args[1])); - return; + switch (args[0].toLowerCase(Locale.ROOT)) { + case "add" -> parseTownTrustAddCommand(sender, town, resident); + case "remove" -> parseTownTrustRemoveCommand(sender, town, resident); + default -> HelpMenu.TOWN_TRUST_HELP.send(sender); } - - if (args[0].equalsIgnoreCase("add")) { - if (town.hasTrustedResident(resident)) { - TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_already_trusted", resident.getName(), Translatable.of("town_sing"))); - return; - } + } - BukkitTools.ifCancelledThenThrow(new TownTrustAddEvent(sender, resident, town)); + private static void parseTownTrustListCommand(CommandSender sender, Town town) { + List<String> output = town.getTrustedResidents().isEmpty() + ? Collections.singletonList(Translatable.of("status_no_town").forLocale(sender)) // String which is "None". + : town.getTrustedResidents().stream().map(Resident::getName).collect(Collectors.toList()); + TownyMessaging.sendMessage(sender, TownyFormatter.getFormattedStrings(Translatable.of("status_trustedlist").forLocale(sender), output)); + } - town.addTrustedResident(resident); - plugin.deleteCache(resident); - - TownyMessaging.sendMsg(sender, Translatable.of("msg_trusted_added", resident.getName(), Translatable.of("town_sing"))); - if (BukkitTools.isOnline(resident.getName())) - TownyMessaging.sendMsg(resident.getPlayer(), Translatable.of("msg_trusted_added_2", sender instanceof Player player ? player.getName() : "Console", Translatable.of("town_sing"), town.getName())); - } else if (args[0].equalsIgnoreCase("remove")) { - if (!town.hasTrustedResident(resident)) { - TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_not_trusted", resident.getName(), Translatable.of("town_sing"))); - return; - } + private static void parseTownTrustAddCommand(CommandSender sender, Town town, Resident resident) throws TownyException { + if (town.hasTrustedResident(resident)) + throw new TownyException(Translatable.of("msg_already_trusted", resident.getName(), Translatable.of("town_sing"))); - BukkitTools.ifCancelledThenThrow(new TownTrustRemoveEvent(sender, resident, town)); + BukkitTools.ifCancelledThenThrow(new TownTrustAddEvent(sender, resident, town)); - town.removeTrustedResident(resident); - plugin.deleteCache(resident); - - TownyMessaging.sendMsg(sender, Translatable.of("msg_trusted_removed", resident.getName(), Translatable.of("town_sing"))); - if (BukkitTools.isOnline(resident.getName())) - TownyMessaging.sendMsg(resident.getPlayer(), Translatable.of("msg_trusted_removed_2", sender instanceof Player player ? player.getName() : "Console", Translatable.of("town_sing"), town.getName())); - } else { - TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_err_invalid_property", args[0])); - return; - } - + town.addTrustedResident(resident); + town.save(); + plugin.deleteCache(resident); + + TownyMessaging.sendMsg(sender, Translatable.of("msg_trusted_added", resident.getName(), Translatable.of("town_sing"))); + if (resident.isOnline()) + TownyMessaging.sendMsg(resident, Translatable.of("msg_trusted_added_2", sender instanceof Player player ? player.getName() : "Console", Translatable.of("town_sing"), town.getName())); + } + + private static void parseTownTrustRemoveCommand(CommandSender sender, Town town, Resident resident) throws TownyException { + if (!town.hasTrustedResident(resident)) + throw new TownyException(Translatable.of("msg_not_trusted", resident.getName(), Translatable.of("town_sing"))); + + BukkitTools.ifCancelledThenThrow(new TownTrustRemoveEvent(sender, resident, town)); + + town.removeTrustedResident(resident); town.save(); + plugin.deleteCache(resident); + + TownyMessaging.sendMsg(sender, Translatable.of("msg_trusted_removed", resident.getName(), Translatable.of("town_sing"))); + if (resident.isOnline()) + TownyMessaging.sendMsg(resident, Translatable.of("msg_trusted_removed_2", sender instanceof Player player ? player.getName() : "Console", Translatable.of("town_sing"), town.getName())); } public static void parseTownTrustTownCommand(CommandSender sender, String[] args, @Nullable Town town) throws TownyException { diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/exceptions/ResidentNPCException.java b/Towny/src/main/java/com/palmergames/bukkit/towny/exceptions/ResidentNPCException.java new file mode 100644 index 0000000000..dfc5e65ad7 --- /dev/null +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/exceptions/ResidentNPCException.java @@ -0,0 +1,17 @@ +package com.palmergames.bukkit.towny.exceptions; + +import com.palmergames.bukkit.towny.object.Translatable; + +public class ResidentNPCException extends TownyException { + + private static final long serialVersionUID = 6165509444120626464L; + + public ResidentNPCException() { + super(Translatable.of("msg_err_resident_is_npc")); + } + + public ResidentNPCException(Translatable errormsg) { + super(errormsg); + } + +} diff --git a/Towny/src/main/resources/lang/en-US.yml b/Towny/src/main/resources/lang/en-US.yml index 4bd2591318..09603cf207 100644 --- a/Towny/src/main/resources/lang/en-US.yml +++ b/Towny/src/main/resources/lang/en-US.yml @@ -2362,4 +2362,7 @@ town_say_format: "%s says: %s" msg_err_floodfill_not_in_wild: "You cannot use floodfill while standing in a claimed area." msg_err_floodfill_out_of_bounds: "Claim shape must be fully closed off in order to floodfill." -msg_err_floodfill_cannot_contain_towns: "Flood fill selection must not contain other towns." \ No newline at end of file +msg_err_floodfill_cannot_contain_towns: "Flood fill selection must not contain other towns." + +# Message shown when a resident is an NPC and is not allowed to do something. +msg_err_resident_is_npc: "You cannot do this to an NPC resident." \ No newline at end of file From feda1794929c9da894407caa508c03023b5f0fe4 Mon Sep 17 00:00:00 2001 From: LlmDl <llmdlio@gmail.com> Date: Wed, 18 Oct 2023 11:54:19 -0500 Subject: [PATCH 2/8] Simplify the tab completer. --- .../bukkit/towny/command/TownCommand.java | 483 +++++++++--------- 1 file changed, 235 insertions(+), 248 deletions(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownCommand.java b/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownCommand.java index e67308bbb5..ba55172ed0 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownCommand.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownCommand.java @@ -298,262 +298,238 @@ public TownCommand(Towny instance) { @Override public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) { - if (sender instanceof Player player) { - - switch (args[0].toLowerCase(Locale.ROOT)) { - case "online": - case "reslist": - case "outlawlist": - case "plots": - case "delete": - case "join": - case "merge": - case "plotgrouplist": - case "allylist": - case "enemylist": - case "baltop": - case "ranklist": - if (args.length == 2) - return getTownyStartingWith(args[1], "t"); - break; - case "deposit": - if (args.length == 3) - return getTownyStartingWith(args[2], "t"); - break; - case "spawn": - if (args.length == 2) { - List<String> townOrIgnore = getTownyStartingWith(args[1], "t"); - townOrIgnore.add("-ignore"); - return NameUtil.filterByStart(townOrIgnore, args[1]); - } - if (args.length == 3) { - return Collections.singletonList("-ignore"); - } - case "rank": - switch (args.length) { - case 2: - return NameUtil.filterByStart(townAddRemoveTabCompletes, args[1]); - case 3: - return getTownResidentNamesOfPlayerStartingWith(player, args[2]); - case 4: - switch (args[1].toLowerCase(Locale.ROOT)) { - case "add": - return NameUtil.filterByStart(TownyPerms.getTownRanks(), args[3]); - case "remove": { - Resident res = TownyUniverse.getInstance().getResident(args[2]); - if (res != null) - return res.getTownRanks().isEmpty() ? Collections.emptyList() : NameUtil.filterByStart(res.getTownRanks(), args[3]); - break; - } - default: - return Collections.emptyList(); - } - default: - return Collections.emptyList(); - } - case "jail": - if (args.length == 2) { - List<String> residentOrList = getTownResidentNamesOfPlayerStartingWith(player, args[1]); - residentOrList.add("list"); - return NameUtil.filterByStart(residentOrList, args[1]); - } - case "unjail": - if (args.length == 2) { - Town town = TownyAPI.getInstance().getTown(player); - if (town != null) { - List<String> jailedResidents = new ArrayList<>(); - TownyUniverse.getInstance().getJailedResidentMap().stream() - .filter(jailee -> jailee.hasJailTown(town.getName())) - .forEach(jailee -> jailedResidents.add(jailee.getName())); - return NameUtil.filterByStart(jailedResidents, args[1]); - } - } - case "outpost": - if (args.length == 2) - return Collections.singletonList("list"); - break; - case "outlaw": - case "ban": - switch (args.length) { - case 2: - return NameUtil.filterByStart(townAddRemoveTabCompletes, args[1]); - case 3: - switch (args[1].toLowerCase(Locale.ROOT)) { - case "add": - return getTownyStartingWith(args[2], "r"); - case "remove": { - Resident resident = TownyUniverse.getInstance().getResident(player.getUniqueId()); - if (resident != null) { - try { - return NameUtil.filterByStart(NameUtil.getNames(resident.getTown().getOutlaws()), args[2]); - } catch (TownyException ignore) { - } - } - } - default: - return Collections.emptyList(); - } - default: - return Collections.emptyList(); - } - case "claim": - switch (args.length) { - case 2: - return NameUtil.filterByStart(townClaimTabCompletes, args[1]); - case 3: - if (!args[1].equalsIgnoreCase("outpost")) { - return NameUtil.filterByStart(Collections.singletonList("auto"), args[2]); - } - default: - return Collections.emptyList(); - } - case "unclaim": - if (args.length == 2) - return NameUtil.filterByStart(townUnclaimTabCompletes, args[1]); - break; + if (!(sender instanceof Player player)) { + if (args.length == 1) + return filterByStartOrGetTownyStartingWith(townConsoleTabCompletes, args[0], "t"); + else + return Collections.emptyList(); + } + + Town town = TownyAPI.getInstance().getTown(player); + + switch (args[0].toLowerCase(Locale.ROOT)) { + case "online": + case "reslist": + case "outlawlist": + case "plots": + case "delete": + case "join": + case "merge": + case "plotgrouplist": + case "allylist": + case "enemylist": + case "baltop": + case "ranklist": + if (args.length == 2) + return getTownyStartingWith(args[1], "t"); + break; + case "deposit": + if (args.length == 3) + return getTownyStartingWith(args[2], "t"); + break; + case "spawn": + if (args.length == 2) { + List<String> townOrIgnore = getTownyStartingWith(args[1], "t"); + townOrIgnore.add("-ignore"); + return NameUtil.filterByStart(townOrIgnore, args[1]); + } + if (args.length == 3) + return Collections.singletonList("-ignore"); + break; + case "rank": + switch (args.length) { + case 2: + return NameUtil.filterByStart(townAddRemoveTabCompletes, args[1]); + case 3: + return getTownResidentNamesOfPlayerStartingWith(player, args[2]); + case 4: + switch (args[1].toLowerCase(Locale.ROOT)) { case "add": - if (args.length == 2) - return getVisibleResidentsForPlayerWithoutTownsStartingWith(args[1], sender); - break; - case "kick": - if (args.length == 2) - return getTownResidentNamesOfPlayerStartingWith(player, args[1]); - break; - case "set": - try { - Resident res = TownyUniverse.getInstance().getResident(player.getUniqueId()); - if (res != null) - return townSetTabComplete(sender, res.getTown(), args); - } catch (TownyException ignore) {} - return Collections.emptyList(); - case "invite": - switch (args.length) { - case 2: - List<String> returnValue = NameUtil.filterByStart(townInviteTabCompletes, args[1]); - if (returnValue.size() > 0) { - return returnValue; - } else { - if (args[1].startsWith("-")) { - Resident res = TownyUniverse.getInstance().getResident(player.getUniqueId()); - - if (res == null) - return null; - - try { - return NameUtil.filterByStart(res.getTown().getSentInvites() - // Get all sent invites - .stream() - .map(Invite::getReceiver) - .map(InviteReceiver::getName) - .collect(Collectors.toList()), args[1].substring(1)) - // Add the hyphen back to the front - .stream() - .map(e -> "-"+e) - .collect(Collectors.toList()); - } catch (TownyException ignore) {} - } else { - return getVisibleResidentsForPlayerWithoutTownsStartingWith(args[1], sender); - } - } - case 3: - switch (args[1].toLowerCase(Locale.ROOT)) { - case "accept": - case "deny": { - Resident res = TownyUniverse.getInstance().getResident(player.getUniqueId()); - if (res == null) - return null; - - try { - return NameUtil.filterByStart(res.getTown().getReceivedInvites() - // Get the names of all received invites - .stream() - .map(Invite::getSender) - .map(InviteSender::getName) - .collect(Collectors.toList()),args[2]); - } catch (TownyException ignore) { - } - } - default: - return Collections.emptyList(); - } - default: - return Collections.emptyList(); - } - case "buy": - if (args.length == 2) - return NameUtil.filterByStart(Collections.singletonList("bonus"), args[1]); + return NameUtil.filterByStart(TownyPerms.getTownRanks(), args[3]); + case "remove": { + Resident res = TownyUniverse.getInstance().getResident(args[2]); + if (res != null) + return res.getTownRanks().isEmpty() ? Collections.emptyList() : NameUtil.filterByStart(res.getTownRanks(), args[3]); break; - case "toggle": - switch (args.length) { - case 2: - return NameUtil.filterByStart(TownyCommandAddonAPI.getTabCompletes(CommandType.TOWN_TOGGLE, townToggleTabCompletes), args[1]); - case 3: - return NameUtil.filterByStart(BaseCommand.setOnOffCompletes, args[2]); - case 4: - return getTownResidentNamesOfPlayerStartingWith(player, args[3]); - default: - return Collections.emptyList(); - } - case "list": - switch (args.length) { - case 2: - return Collections.singletonList("by"); - case 3: - return NameUtil.filterByStart(townListTabCompletes, args[2]); - default: - return Collections.emptyList(); - } - case "trust": - switch (args.length) { - case 2: - return NameUtil.filterByStart(Arrays.asList("add", "remove", "list"), args[1]); - case 3: - if (args[1].equalsIgnoreCase("add") || args[1].equalsIgnoreCase("remove")) - return getTownyStartingWith(args[2], "r"); - else - return Collections.emptyList(); - default: - return Collections.emptyList(); - } - case "trusttown": - switch (args.length) { - case 2: - return NameUtil.filterByStart(Arrays.asList("add", "remove", "list"), args[1]); - case 3: - if (args[1].equalsIgnoreCase("add")) { - List<String> townsList = getTownyStartingWith(args[2], "t"); - townsList.removeAll(getTrustedTownsFromResident(player)); - return townsList; - } - if (args[1].equalsIgnoreCase("remove")) { - return NameUtil.filterByStart(getTrustedTownsFromResident(player), args[2]); - } - return Collections.emptyList(); - default: - return Collections.emptyList(); - } - - case "buytown": - if (args.length == 2) { - List<String> townsList = getTownyStartingWith(args[1], "t"); - townsList.removeIf(n -> !TownyAPI.getInstance().getTown(n).isForSale()); - return townsList; - } - + } default: - if (args.length == 1) - return filterByStartOrGetTownyStartingWith(TownyCommandAddonAPI.getTabCompletes(CommandType.TOWN, townTabCompletes), args[0], "t"); - else if (TownyCommandAddonAPI.hasCommand(CommandType.TOWN, args[0])) - return NameUtil.filterByStart(TownyCommandAddonAPI.getAddonCommand(CommandType.TOWN, args[0]).getTabCompletion(sender, args), args[args.length-1]); + return Collections.emptyList(); + } + default: + return Collections.emptyList(); + } + case "jail": + if (args.length == 2) { + List<String> residentOrList = getTownResidentNamesOfPlayerStartingWith(player, args[1]); + residentOrList.add("list"); + return NameUtil.filterByStart(residentOrList, args[1]); + } + break; + case "unjail": + if (args.length == 2 && town != null) { + List<String> jailedResidents = TownyUniverse.getInstance().getJailedResidentMap().stream() + .filter(jailee -> jailee.hasJailTown(town.getName())) + .map(jailee -> jailee.getName()) + .collect(Collectors.toList()); + return NameUtil.filterByStart(jailedResidents, args[1]); + } + break; + case "outpost": + if (args.length == 2) + return Collections.singletonList("list"); + break; + case "outlaw": + case "ban": + switch (args.length) { + case 2: + return NameUtil.filterByStart(townAddRemoveTabCompletes, args[1]); + case 3: + switch (args[1].toLowerCase(Locale.ROOT)) { + case "add": + return getTownyStartingWith(args[2], "r"); + case "remove": + if (town != null) + return NameUtil.filterByStart(NameUtil.getNames(town.getOutlaws()), args[2]); + } + default: + return Collections.emptyList(); + } + case "claim": + switch (args.length) { + case 2: + return NameUtil.filterByStart(townClaimTabCompletes, args[1]); + case 3: + if (!args[1].equalsIgnoreCase("outpost")) + return NameUtil.filterByStart(Collections.singletonList("auto"), args[2]); + default: + return Collections.emptyList(); + } + case "unclaim": + if (args.length == 2) + return NameUtil.filterByStart(townUnclaimTabCompletes, args[1]); + break; + case "add": + if (args.length == 2) + return getVisibleResidentsForPlayerWithoutTownsStartingWith(args[1], sender); + break; + case "kick": + if (args.length == 2) + return getTownResidentNamesOfPlayerStartingWith(player, args[1]); + break; + case "set": + return townSetTabComplete(sender, town, args); + case "invite": + return townInviteTabComplete(sender, args, player, town); + case "buy": + if (args.length == 2) + return NameUtil.filterByStart(Collections.singletonList("bonus"), args[1]); + break; + case "toggle": + return switch (args.length) { + case 2 -> NameUtil.filterByStart(TownyCommandAddonAPI.getTabCompletes(CommandType.TOWN_TOGGLE, townToggleTabCompletes), args[1]); + case 3 -> NameUtil.filterByStart(BaseCommand.setOnOffCompletes, args[2]); + case 4 -> getTownResidentNamesOfPlayerStartingWith(player, args[3]); + default -> Collections.emptyList(); + }; + case "list": + return switch (args.length) { + case 2 -> Collections.singletonList("by"); + case 3 -> NameUtil.filterByStart(townListTabCompletes, args[2]); + default -> Collections.emptyList(); + }; + case "trust": + switch (args.length) { + case 2: + return NameUtil.filterByStart(Arrays.asList("add", "remove", "list"), args[1]); + case 3: + if (args[1].equalsIgnoreCase("add")) { + List<String> resList = getTownyStartingWith(args[2], "r"); + resList.removeAll(getTrustedResidentsFromResident(player)); + return resList; + } + if (args[1].equalsIgnoreCase("remove")) + return NameUtil.filterByStart(getTrustedResidentsFromResident(player), args[2]); + return Collections.emptyList(); + default: + return Collections.emptyList(); + } + case "trusttown": + switch (args.length) { + case 2: + return NameUtil.filterByStart(Arrays.asList("add", "remove", "list"), args[1]); + case 3: + if (args[1].equalsIgnoreCase("add")) { + List<String> townsList = getTownyStartingWith(args[2], "t"); + townsList.removeAll(getTrustedTownsFromResident(player)); + return townsList; + } + if (args[1].equalsIgnoreCase("remove")) + return NameUtil.filterByStart(getTrustedTownsFromResident(player), args[2]); + return Collections.emptyList(); + default: + return Collections.emptyList(); + } + case "buytown": + if (args.length == 2) { + List<String> townsList = getTownyStartingWith(args[1], "t"); + townsList.removeIf(n -> !TownyAPI.getInstance().getTown(n).isForSale()); + return townsList; } - } else if (args.length == 1) { - return filterByStartOrGetTownyStartingWith(townConsoleTabCompletes, args[0], "t"); + break; + default: + if (args.length == 1) + return filterByStartOrGetTownyStartingWith(TownyCommandAddonAPI.getTabCompletes(CommandType.TOWN, townTabCompletes), args[0], "t"); + else if (TownyCommandAddonAPI.hasCommand(CommandType.TOWN, args[0])) + return NameUtil.filterByStart(TownyCommandAddonAPI.getAddonCommand(CommandType.TOWN, args[0]).getTabCompletion(sender, args), args[args.length-1]); } - return Collections.emptyList(); } + + private List<String> townInviteTabComplete(CommandSender sender, String[] args, Player player, Town town) { + if (town == null) + return Collections.emptyList(); + switch (args.length) { + case 2: + List<String> returnValue = NameUtil.filterByStart(townInviteTabCompletes, args[1]); + if (returnValue.size() > 0) { + return returnValue; + } else { + if (args[1].startsWith("-")) { + return NameUtil.filterByStart(town.getSentInvites() + // Get all sent invites + .stream() + .map(Invite::getReceiver) + .map(InviteReceiver::getName) + .collect(Collectors.toList()), args[1].substring(1)) + // Add the hyphen back to the front + .stream() + .map(e -> "-"+e) + .collect(Collectors.toList()); + } else { + return getVisibleResidentsForPlayerWithoutTownsStartingWith(args[1], sender); + } + } + case 3: + switch (args[1].toLowerCase(Locale.ROOT)) { + case "accept", "deny" -> { + return NameUtil.filterByStart(town.getReceivedInvites() + // Get the names of all received invites + .stream() + .map(Invite::getSender) + .map(InviteSender::getName) + .collect(Collectors.toList()),args[2]); + } + default -> Collections.emptyList(); + } + default: + return Collections.emptyList(); + } + } static List<String> townSetTabComplete(CommandSender sender, Town town, String[] args) { + if (town == null) + return Collections.emptyList(); + if (args.length == 2) { return NameUtil.filterByStart(TownyCommandAddonAPI.getTabCompletes(CommandType.TOWN_SET, townSetTabCompletes), args[1]); } else if (args.length > 2) { @@ -4480,7 +4456,18 @@ else if (town == trustTown) { town.save(); } - + + public static List<String> getTrustedResidentsFromResident(Player player){ + Resident res = TownyUniverse.getInstance().getResident(player.getUniqueId()); + + if (res != null && res.hasTown()) { + return res.getTownOrNull().getTrustedResidents().stream().map(TownyObject::getName) + .collect(Collectors.toList()); + } + + return Collections.emptyList(); + } + public static List<String> getTrustedTownsFromResident(Player player){ Resident res = TownyUniverse.getInstance().getResident(player.getUniqueId()); From 0e4be0a2c7c97ba96ddf2d711ee00ebd1cef387e Mon Sep 17 00:00:00 2001 From: LlmDl <llmdlio@gmail.com> Date: Wed, 18 Oct 2023 12:40:47 -0500 Subject: [PATCH 3/8] Simplify town merge command. --- .../bukkit/towny/command/TownCommand.java | 109 +++++++++++------- 1 file changed, 66 insertions(+), 43 deletions(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownCommand.java b/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownCommand.java index ba55172ed0..ae25d2f00f 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownCommand.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownCommand.java @@ -4003,7 +4003,7 @@ public static void parseTownMergeCommand(Player player, String[] args) throws To parseTownMergeCommand(player, args, getTownFromPlayerOrThrow(player), false); } - public static void parseTownMergeCommand(CommandSender sender, String[] args, @NotNull Town remainingTown, boolean admin) throws TownyException { + public static void parseTownMergeCommand(CommandSender sender, String[] args, @NotNull final Town remainingTown, boolean admin) throws TownyException { if (args.length <= 0) // /t merge throw new TownyException(Translatable.of("msg_specify_name")); @@ -4011,11 +4011,38 @@ public static void parseTownMergeCommand(CommandSender sender, String[] args, @N if (!admin && sender instanceof Player player && !getResidentOrThrow(player).isMayor()) throw new TownyException(Translatable.of("msg_town_merge_err_mayor_only")); - Town succumbingTown = getTownOrThrow(args[0]); + final Town succumbingTown = getTownOrThrow(args[0]); + vetTownsForMergeAndThrow(remainingTown, succumbingTown); + + // An array that keeps Merge costs separate, so the individual prices can be used later on in messaging. + final double[] mergeCost = getMergeCosts(remainingTown, succumbingTown, admin); + final double cost = Arrays.stream(mergeCost).sum(); + + if (cost > 0) { + TownyMessaging.sendMsg(sender, Translatable.of("msg_town_merge_warning", succumbingTown.getName(), prettyMoney(cost))); + if (mergeCost[2] > 0) // If the succumbing town was bankrupt. + TownyMessaging.sendMsg(sender, Translatable.of("msg_town_merge_debt_warning", succumbingTown.getName())); + TownyMessaging.sendMsg(sender, Translatable.of("msg_town_merge_cost_breakdown", + prettyMoney(mergeCost[0]), // Base Cost + prettyMoney(mergeCost[1]), // TownBlock Cost + prettyMoney(mergeCost[2]), // Bankruptcy Cost + prettyMoney(mergeCost[3]))); // Purchased BonusBlock Cost + + Confirmation.runOnAccept(() -> { + sendTownMergeRequest(sender, remainingTown, succumbingTown, cost); + }).runOnCancel(() -> { + TownyMessaging.sendMsg(sender, Translatable.of("msg_town_merge_cancelled")); + return; + }).sendTo(sender); + } else + sendTownMergeRequest(sender, remainingTown, succumbingTown, cost); + } + + private static void vetTownsForMergeAndThrow(Town remainingTown, Town succumbingTown) throws TownyException { // A lot of checks. if (succumbingTown.getName().equals(remainingTown.getName())) - throw new TownyException(Translatable.of("msg_err_invalid_name", args[0])); + throw new TownyException(Translatable.of("msg_err_invalid_name", succumbingTown.getName())); if (TownySettings.getMaxDistanceForTownMerge() > 0 && homeBlockDistance(remainingTown, succumbingTown) > TownySettings.getMaxDistanceForTownMerge()) throw new TownyException(Translatable.of("msg_town_merge_err_not_close", succumbingTown.getName(), TownySettings.getMaxDistanceForTownMerge())); @@ -4048,50 +4075,39 @@ public static void parseTownMergeCommand(CommandSender sender, String[] args, @N if (!BukkitTools.isOnline(succumbingTown.getMayor().getName()) || succumbingTown.getMayor().isNPC()) throw new TownyException(Translatable.of("msg_town_merge_other_offline", succumbingTown.getName(), succumbingTown.getMayor().getName())); + } - double baseCost = TownySettings.getBaseCostForTownMerge(); - double townblockCost = 0; - double bankruptcyCost = 0; - double purchasedBlockCost = 0; - double cost = 0; - if (!admin && TownyEconomyHandler.isActive()) { - // There is a configurable price that is applied as a percent, that the remaining town will pay. - townblockCost = remainingTown.getTownBlockCostN(succumbingTown.getNumTownBlocks()) * (TownySettings.getPercentageCostPerPlot() * 0.01); - - // Remaining town has to wipe out the succumbing town's debt if any is present. - if (succumbingTown.isBankrupt()) - bankruptcyCost = Math.abs(succumbingTown.getAccount().getHoldingBalance()); - - // When purchased bonus townblocks have a price increase we have to make sure the new town is able to pay the difference - // otherwise towns will farm small towns that buy up bonus blocks at a cheap rate, then merge. - if (succumbingTown.getPurchasedBlocks() > 0 && TownySettings.getPurchasedBonusBlocksIncreaseValue() != 1.0) { - int purchasedBlocks = succumbingTown.getPurchasedBlocks(); - double priceAlreadyPaid = MoneyUtil.returnPurchasedBlocksCost(0, purchasedBlocks, succumbingTown); - purchasedBlockCost = remainingTown.getBonusBlockCostN(purchasedBlocks) - priceAlreadyPaid; - } + private static double[] getMergeCosts(Town remainingTown, Town succumbingTown, boolean admin) throws TownyException { + // An array that keeps Merge costs separate, so the individual prices can be used later on in messaging. + double[] mergeCost = new double[] {TownySettings.getBaseCostForTownMerge(), // mergeCost[0] Base cost of merging. + 0, // mergeCost[1] TownblockCost + 0, // mergeCost[2] BankruptcyCost, + 0}; // mergeCost[3] Purchased BonusBlock costs. + + if (admin || !TownyEconomyHandler.isActive()) + return mergeCost; - cost = baseCost + townblockCost + bankruptcyCost + purchasedBlockCost; + // There is a configurable price that is applied as a percent, that the remaining town will pay. + mergeCost[1] = remainingTown.getTownBlockCostN(succumbingTown.getNumTownBlocks()) * (TownySettings.getPercentageCostPerPlot() * 0.01); - if (!remainingTown.getAccount().canPayFromHoldings(cost)) - throw new TownyException(Translatable.of("msg_town_merge_err_not_enough_money", prettyMoney(remainingTown.getAccount().getHoldingBalance()), prettyMoney(cost))); + // Remaining town has to wipe out the succumbing town's debt if any is present. + if (succumbingTown.isBankrupt()) + mergeCost[2] = Math.abs(succumbingTown.getAccount().getHoldingBalance()); + + // When purchased bonus townblocks have a price increase we have to make sure the new town is able to pay the difference + // otherwise towns will farm small towns that buy up bonus blocks at a cheap rate, then merge. + if (succumbingTown.getPurchasedBlocks() > 0 && TownySettings.getPurchasedBonusBlocksIncreaseValue() != 1.0) { + int purchasedBlocks = succumbingTown.getPurchasedBlocks(); + double priceAlreadyPaid = MoneyUtil.returnPurchasedBlocksCost(0, purchasedBlocks, succumbingTown); + mergeCost[3] = remainingTown.getBonusBlockCostN(purchasedBlocks) - priceAlreadyPaid; } - - if (cost > 0) { - TownyMessaging.sendMsg(sender, Translatable.of("msg_town_merge_warning", succumbingTown.getName(), prettyMoney(cost))); - if (bankruptcyCost > 0) - TownyMessaging.sendMsg(sender, Translatable.of("msg_town_merge_debt_warning", succumbingTown.getName())); - TownyMessaging.sendMsg(sender, Translatable.of("msg_town_merge_cost_breakdown", prettyMoney(baseCost), prettyMoney(townblockCost), prettyMoney(bankruptcyCost), prettyMoney(purchasedBlockCost))); - final Town finalSuccumbingTown = succumbingTown; - final Town finalRemainingTown = remainingTown; - final double finalCost = cost; - Confirmation.runOnAccept(() -> { - sendTownMergeRequest(sender, finalRemainingTown, finalSuccumbingTown, finalCost); - }).runOnCancel(() -> { - TownyMessaging.sendMsg(sender, Translatable.of("msg_town_merge_cancelled")); - return; - }).sendTo(sender); - } else - sendTownMergeRequest(sender, remainingTown, succumbingTown, cost); + + double cost = Arrays.stream(mergeCost).sum(); + + if (!remainingTown.getAccount().canPayFromHoldings(cost)) + throw new TownyException(Translatable.of("msg_town_merge_err_not_enough_money", prettyMoney(remainingTown.getAccount().getHoldingBalance()), prettyMoney(cost))); + + return mergeCost; } private static String prettyMoney(double cost) { @@ -4103,6 +4119,13 @@ private static void sendTownMergeRequest(CommandSender sender, Town remainingTow TownyMessaging.sendMsg(succumbingTown.getMayor(), Translatable.of("msg_town_merge_request_received", remainingTown.getName(), sender.getName(), remainingTown.getName())); Confirmation.runOnAccept(() -> { + try { + vetTownsForMergeAndThrow(remainingTown, succumbingTown); + } catch (TownyException e) { + TownyMessaging.sendErrorMsg(sender, e.getMessage(sender)); + return; + } + TownPreMergeEvent townPreMergeEvent = new TownPreMergeEvent(remainingTown, succumbingTown); if (BukkitTools.isEventCancelled(townPreMergeEvent)) { TownyMessaging.sendErrorMsg(succumbingTown.getMayor().getPlayer(), townPreMergeEvent.getCancelMessage()); From ad06cd26ad5d85a9206c3bef171c7daf01799040 Mon Sep 17 00:00:00 2001 From: LlmDl <llmdlio@gmail.com> Date: Wed, 18 Oct 2023 14:06:24 -0500 Subject: [PATCH 4/8] Simplify setTownPermissions method. --- .../bukkit/towny/command/TownCommand.java | 187 +++++++++--------- .../java/com/palmergames/util/StringMgmt.java | 2 +- 2 files changed, 90 insertions(+), 99 deletions(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownCommand.java b/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownCommand.java index ae25d2f00f..9c313f3a79 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownCommand.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownCommand.java @@ -3455,146 +3455,90 @@ public static void setTownBlockOwnerPermissions(CommandSender sender, TownBlockO public static void setTownBlockPermissions(CommandSender sender, TownBlockOwner townBlockOwner, TownyPermission perm, String[] split, boolean friend) { if (split.length == 0 || split[0].equalsIgnoreCase("?") || split.length > 3) { + displaySetPlotPermissionsHelp(sender, townBlockOwner); + return; + } - TownyMessaging.sendMessage(sender, ChatTools.formatTitle("/... set perm")); - if (townBlockOwner instanceof Town) - TownyMessaging.sendMessage(sender, ChatTools.formatCommand("Level", "[resident/nation/ally/outsider]", "", "")); - if (townBlockOwner instanceof Resident) - TownyMessaging.sendMessage(sender, ChatTools.formatCommand("Level", "[friend/town/ally/outsider]", "", "")); - TownyMessaging.sendMessage(sender, ChatTools.formatCommand("Type", "[build/destroy/switch/itemuse]", "", "")); - TownyMessaging.sendMessage(sender, ChatTools.formatCommand("", "set perm", "[on/off]", "Toggle all permissions")); - TownyMessaging.sendMessage(sender, ChatTools.formatCommand("", "set perm", "[level/type] [on/off]", "")); - TownyMessaging.sendMessage(sender, ChatTools.formatCommand("", "set perm", "[level] [type] [on/off]", "")); - TownyMessaging.sendMessage(sender, ChatTools.formatCommand("", "set perm", "reset", "")); - if (townBlockOwner instanceof Town) - TownyMessaging.sendMessage(sender, ChatTools.formatCommand("Eg", "/town set perm", "ally off", "")); - if (townBlockOwner instanceof Resident) - TownyMessaging.sendMessage(sender, ChatTools.formatCommand("Eg", "/resident set perm", "friend build on", "")); - + // /t set perm reset has been run. + if (split[0].equalsIgnoreCase("reset")) { + resetTownBlockOwnersTownBlocks(sender, townBlockOwner); return; } - // reset the friend to resident so the perm settings don't fail - if (friend && split[0].equalsIgnoreCase("friend")) + // Permissions commands for residents use Friend instead of Resident and Town + // instead of Nation, we must set these values to their "true" value for + // permissions to be set correctly. + if (split[0].equalsIgnoreCase("friend")) split[0] = "resident"; - // reset the town to nation so the perm settings don't fail - if (friend && split[0].equalsIgnoreCase("town")) + else if (split[0].equalsIgnoreCase("town")) split[0] = "nation"; - - TownyPermissionChange permChange; - - if (split.length == 1) { - - if (split[0].equalsIgnoreCase("reset")) { - - // reset all townBlock permissions (by town/resident) - for (TownBlock townBlock : townBlockOwner.getTownBlocks()) { - - if ((townBlockOwner instanceof Town && !townBlock.hasResident()) || - (townBlockOwner instanceof Resident && townBlock.hasResident())) { - - permChange = new TownyPermissionChange(TownyPermissionChange.Action.RESET, true, townBlock); - try { - BukkitTools.ifCancelledThenThrow(new TownBlockPermissionChangeEvent(townBlock, permChange)); - } catch (CancelledEventException e) { - sender.sendMessage(e.getCancelMessage()); - return; - } - // Reset permissions - townBlock.setType(townBlock.getType()); - townBlock.save(); - } - } - if (townBlockOwner instanceof Town) - TownyMessaging.sendMsg(sender, Translatable.of("msg_set_perms_reset", "Town owned")); - else - TownyMessaging.sendMsg(sender, Translatable.of("msg_set_perms_reset", "your")); - - // Reset all caches as this can affect everyone. - plugin.resetCache(); + if (split[0].equalsIgnoreCase("itemuse")) + split[0] = "item_use"; + if (split.length > 1 && split[1].equalsIgnoreCase("itemuse")) + split[1] = "item_use"; + + // A more complex command has been run for setting permissions. + TownyPermissionChange permChange = null; + switch (split.length) { + case 1: { // Set all perms to On or Off ie: /town set perm off' + try { + boolean b = StringMgmt.parseOnOff(split[0]); + permChange = new TownyPermissionChange(TownyPermissionChange.Action.ALL_PERMS, b); + perm.change(permChange); + } catch (Exception e) { + TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_err_invalid_input", "on/off.")); return; - - } else { - // Set all perms to On or Off - // '/town set perm off' - - try { - boolean b = StringMgmt.parseOnOff(split[0]); - permChange = new TownyPermissionChange(TownyPermissionChange.Action.ALL_PERMS, b); - perm.change(permChange); - } catch (Exception e) { - TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_town_set_perm_syntax_error")); - return; - } } - - } else if (split.length == 2) { + } + case 2: { // Either /t set perm PERMLEVEL on|off or /t set perm ACTIONTYPE on|off boolean b; - try { b = StringMgmt.parseOnOff(split[1]); } catch (Exception e) { - TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_town_set_perm_syntax_error")); + TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_err_invalid_input", "on/off.")); return; } - if (split[0].equalsIgnoreCase("friend")) - split[0] = "resident"; - else if (split[0].equalsIgnoreCase("town")) - split[0] = "nation"; - else if (split[0].equalsIgnoreCase("itemuse")) - split[0] = "item_use"; - // Check if it is a perm level first try { TownyPermission.PermLevel permLevel = TownyPermission.PermLevel.valueOf(split[0].toUpperCase(Locale.ROOT)); permChange = new TownyPermissionChange(TownyPermissionChange.Action.PERM_LEVEL, b, permLevel); perm.change(permChange); - } - catch (IllegalArgumentException permLevelException) { + } catch (IllegalArgumentException permLevelException) { // If it is not a perm level, then check if it is a action type try { TownyPermission.ActionType actionType = TownyPermission.ActionType.valueOf(split[0].toUpperCase(Locale.ROOT)); permChange = new TownyPermissionChange(TownyPermissionChange.Action.ACTION_TYPE, b, actionType); perm.change(permChange); } catch (IllegalArgumentException actionTypeException) { + // It isn't either perm level or action type, it's a syntax error. TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_town_set_perm_syntax_error")); return; } } - - } else { - // Reset the friend to resident so the perm settings don't fail - if (split[0].equalsIgnoreCase("friend")) - split[0] = "resident"; - // reset the town to nation so the perm settings don't fail - else if (split[0].equalsIgnoreCase("town")) - split[0] = "nation"; - if (split[1].equalsIgnoreCase("itemuse")) - split[1] = "item_use"; - + } + case 3: { // /t set perm PERMLEVEL ACTIONTYPE on|off TownyPermission.PermLevel permLevel; TownyPermission.ActionType actionType; try { permLevel = TownyPermission.PermLevel.valueOf(split[0].toUpperCase(Locale.ROOT)); actionType = TownyPermission.ActionType.valueOf(split[1].toUpperCase(Locale.ROOT)); - } catch (IllegalArgumentException ignore) { + } catch (IllegalArgumentException exception) { TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_town_set_perm_syntax_error")); return; } - + try { boolean b = StringMgmt.parseOnOff(split[2]); - permChange = new TownyPermissionChange(TownyPermissionChange.Action.SINGLE_PERM, b, permLevel, actionType); perm.change(permChange); - } catch (Exception e) { - TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_town_set_perm_syntax_error")); + TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_err_invalid_input", "on/off.")); return; } } + } // Propagate perms to all unchanged townblocks for (TownBlock townBlock : townBlockOwner.getTownBlocks()) { @@ -3605,7 +3549,7 @@ else if (split[0].equalsIgnoreCase("town")) try { BukkitTools.ifCancelledThenThrow(new TownBlockPermissionChangeEvent(townBlock, permChange)); } catch (CancelledEventException e) { - sender.sendMessage(e.getCancelMessage()); + TownyMessaging.sendErrorMsg(sender, e.getCancelMessage()); continue; } @@ -3621,16 +3565,63 @@ else if (split[0].equalsIgnoreCase("town")) Translator translator = Translator.locale(sender); TownyMessaging.sendMsg(sender, translator.of("msg_set_perms")); TownyMessaging.sendMessage(sender, (Colors.Green + translator.of("status_perm") + " " + ((townBlockOwner instanceof Resident) ? perm.getColourString().replace("n", "t") : perm.getColourString().replace("f", "r")))); - TownyMessaging.sendMessage(sender, Colors.Green + translator.of("status_pvp") + " " + (perm.pvp ? translator.of("status_on") : translator.of("status_off")) + " " + - Colors.Green + translator.of("explosions") + " " + (perm.explosion ? translator.of("status_on") : translator.of("status_off")) + " " + - Colors.Green + translator.of("firespread") + " " + (perm.fire ? translator.of("status_on") : translator.of("status_off")) + " " + - Colors.Green + translator.of("mobspawns") + " " + (perm.mobs ? translator.of("status_on") : translator.of("status_off"))); + String on = translator.of("status_on"); + String off = translator.of("status_off"); + TownyMessaging.sendMessage(sender, Colors.Green + translator.of("status_pvp") + " " + (perm.pvp ? on : off) + " " + + Colors.Green + translator.of("explosions") + " " + (perm.explosion ? on : off) + " " + + Colors.Green + translator.of("firespread") + " " + (perm.fire ? on : off) + " " + + Colors.Green + translator.of("mobspawns") + " " + (perm.mobs ? on : off)); // Reset all caches as this can affect everyone. plugin.resetCache(); } + private static void displaySetPlotPermissionsHelp(CommandSender sender, TownBlockOwner townBlockOwner) { + TownyMessaging.sendMessage(sender, ChatTools.formatTitle("/... set perm")); + if (townBlockOwner instanceof Town) + TownyMessaging.sendMessage(sender, ChatTools.formatCommand("Level", "[resident/nation/ally/outsider]", "", "")); + if (townBlockOwner instanceof Resident) + TownyMessaging.sendMessage(sender, ChatTools.formatCommand("Level", "[friend/town/ally/outsider]", "", "")); + TownyMessaging.sendMessage(sender, ChatTools.formatCommand("Type", "[build/destroy/switch/itemuse]", "", "")); + TownyMessaging.sendMessage(sender, ChatTools.formatCommand("", "set perm", "[on/off]", "Toggle all permissions")); + TownyMessaging.sendMessage(sender, ChatTools.formatCommand("", "set perm", "[level/type] [on/off]", "")); + TownyMessaging.sendMessage(sender, ChatTools.formatCommand("", "set perm", "[level] [type] [on/off]", "")); + TownyMessaging.sendMessage(sender, ChatTools.formatCommand("", "set perm", "reset", "")); + if (townBlockOwner instanceof Town) + TownyMessaging.sendMessage(sender, ChatTools.formatCommand("Eg", "/town set perm", "ally off", "")); + if (townBlockOwner instanceof Resident) + TownyMessaging.sendMessage(sender, ChatTools.formatCommand("Eg", "/resident set perm", "friend build on", "")); + } + + private static void resetTownBlockOwnersTownBlocks(CommandSender sender, TownBlockOwner townBlockOwner) { + // reset all townBlock permissions (by town/resident) + for (TownBlock townBlock : townBlockOwner.getTownBlocks()) { + + if ((townBlockOwner instanceof Town && !townBlock.hasResident()) || + (townBlockOwner instanceof Resident && townBlock.hasResident())) { + + TownyPermissionChange permChange = new TownyPermissionChange(TownyPermissionChange.Action.RESET, true, townBlock); + try { + BukkitTools.ifCancelledThenThrow(new TownBlockPermissionChangeEvent(townBlock, permChange)); + } catch (CancelledEventException e) { + TownyMessaging.sendErrorMsg(sender, e.getCancelMessage()); + return; + } + // Reset permissions + townBlock.setType(townBlock.getType()); + townBlock.save(); + } + } + if (townBlockOwner instanceof Town) + TownyMessaging.sendMsg(sender, Translatable.of("msg_set_perms_reset", "Town owned")); + else + TownyMessaging.sendMsg(sender, Translatable.of("msg_set_perms_reset", "your")); + + // Reset all caches as this can affect everyone. + plugin.resetCache(); + } + public static void parseTownClaimCommand(Player player, String[] split) throws TownyException { if (split.length == 1 && split[0].equalsIgnoreCase("?")) { diff --git a/Towny/src/main/java/com/palmergames/util/StringMgmt.java b/Towny/src/main/java/com/palmergames/util/StringMgmt.java index 70e263708a..3f9058d78e 100644 --- a/Towny/src/main/java/com/palmergames/util/StringMgmt.java +++ b/Towny/src/main/java/com/palmergames/util/StringMgmt.java @@ -209,7 +209,7 @@ public static boolean parseOnOff(String s) throws Exception { else if (s.equalsIgnoreCase("off")) return false; else - throw new Exception(Translation.of("msg_err_invalid_input", " on/off.")); + throw new Exception(Translation.of("msg_err_invalid_input", "on/off.")); } public static boolean isAllUpperCase(@NotNull String string) { From b4ab427bf3f8b86a66fe23201b357c19ceebada4 Mon Sep 17 00:00:00 2001 From: LlmDl <llmdlio@gmail.com> Date: Wed, 18 Oct 2023 15:45:21 -0500 Subject: [PATCH 5/8] Make the edgeblock tester smarter. --- .../bukkit/towny/command/TownCommand.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownCommand.java b/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownCommand.java index 9c313f3a79..e2623e103d 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownCommand.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownCommand.java @@ -3941,7 +3941,7 @@ private void parseTownTakeoverClaimCommand(Player player) throws TownyException throw new TownyException(Translatable.of("msg_err_not_enough_blocks")); // Not connected to the town stealing the land. - if (!isEdgeBlock(town, wc)) + if (!isEdgeBlock(town, wc, new ArrayList<>())) throw new TownyException(Translatable.of("msg_err_not_attached_edge")); // Prevent straight line claims if configured, and the town has enough townblocks claimed, and this is not an outpost. @@ -4147,20 +4147,26 @@ private static void sendTownMergeRequest(CommandSender sender, Town remainingTow public static boolean isEdgeBlock(TownBlockOwner owner, List<WorldCoord> worldCoords) { - // TODO: Better algorithm that doesn't duplicates checks. + List<WorldCoord> visited = new ArrayList<>(); for (WorldCoord worldCoord : worldCoords) - if (isEdgeBlock(owner, worldCoord)) + if (isEdgeBlock(owner, worldCoord, visited)) return true; return false; } - public static boolean isEdgeBlock(TownBlockOwner owner, WorldCoord worldCoord) { + public static boolean isEdgeBlock(TownBlockOwner owner, WorldCoord worldCoord, List<WorldCoord> visited) { for (WorldCoord wc : worldCoord.getCardinallyAdjacentWorldCoords()) { - if (wc.isWilderness()) + if (visited.contains(wc)) continue; - if (!wc.getTownBlockOrNull().isOwner(owner)) + if (wc.isWilderness()) { + visited.add(wc); continue; + } + if (!wc.getTownBlockOrNull().isOwner(owner)) { + visited.add(wc); + continue; + } return true; } return false; From 2cce1ad4fa02498b948d2325af1be3bdda918bd5 Mon Sep 17 00:00:00 2001 From: LlmDl <llmdlio@gmail.com> Date: Wed, 18 Oct 2023 16:24:39 -0500 Subject: [PATCH 6/8] Simplify the root Town command method. --- .../bukkit/towny/command/TownCommand.java | 436 ++++++++---------- 1 file changed, 190 insertions(+), 246 deletions(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownCommand.java b/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownCommand.java index e2623e103d..a7e9f9db3b 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownCommand.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownCommand.java @@ -104,6 +104,7 @@ import com.palmergames.bukkit.towny.utils.SpawnUtil; import com.palmergames.bukkit.towny.utils.TownRuinUtil; import com.palmergames.bukkit.towny.utils.TownUtil; +import com.palmergames.bukkit.towny.utils.TownyComponents; import com.palmergames.bukkit.util.BookFactory; import com.palmergames.bukkit.util.BukkitTools; import com.palmergames.bukkit.util.ChatTools; @@ -628,232 +629,63 @@ private void parseTownCommand(final Player player, String[] split) throws TownyE HelpMenu.TOWN_HELP.send(player); return; } - - Town town; + switch (split[0].toLowerCase(Locale.ROOT)) { - - case "mayor": - checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_MAYOR.getNode()); - HelpMenu.TOWN_MAYOR_HELP.send(player); - break; - case "here": - checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_HERE.getNode()); - town = TownyAPI.getInstance().getTown(player.getLocation()); - if (town == null) - throw new TownyException(Translatable.of("msg_not_claimed", Coord.parseCoord(player.getLocation()))); - townStatusScreen(player, town); - break; - case "list": - // Permission test is internal. - listTowns(player, split); - break; - case "new", "create": - checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_NEW.getNode()); - if (split.length == 1) { - throw new TownyException(Translatable.of("msg_specify_name")); - } else { - String townName = String.join("_", StringMgmt.remFirstArg(split)); - boolean noCharge = TownySettings.getNewTownPrice() == 0.0 || !TownyEconomyHandler.isActive(); - newTown(player, townName, getResidentOrThrow(player), noCharge); - } - break; - case "reclaim": - checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_RECLAIM.getNode()); - - if(!TownySettings.getTownRuinsReclaimEnabled()) - throw new TownyException(Translatable.of("msg_err_command_disable")); - - TownRuinUtil.processRuinedTownReclaimRequest(player); - break; - case "join": - checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_JOIN.getNode()); - parseTownJoin(player, StringMgmt.remFirstArg(split)); - break; - case "leave": - checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_LEAVE.getNode()); - townLeave(player); - break; - case "withdraw": - checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_WITHDRAW.getNode()); - TownyEconomyHandler.economyExecutor().execute(() -> townTransaction(player, StringMgmt.remFirstArg(split), true)); - break; - case "deposit": - checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_DEPOSIT.getNode()); - TownyEconomyHandler.economyExecutor().execute(() -> townTransaction(player, StringMgmt.remFirstArg(split), false)); - break; - case "plots": - checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_PLOTS.getNode()); - townPlots(player, split); - break; - case "reslist": - checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_RESLIST.getNode()); - townResList(player, split); - break; - case "plotgrouplist": - checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_PLOTGROUPLIST.getNode()); - townPlotGroupList(player, split); - break; - case "outlawlist": - townOutlawList(player, split); - break; - case "allylist": - townAllyList(player, split); - break; - case "enemylist": - townEnemyList(player, split); - break; - case "spawn": - // Permission test is internal. - boolean ignoreWarning = split.length > 2 && split[2].equals("-ignore"); - townSpawn(player, StringMgmt.remFirstArg(split), false, ignoreWarning); - break; - case "rank": - // Permission test is internal. - catchRuinedTown(player); - townRank(player, StringMgmt.remFirstArg(split)); - break; - case "set": - // Permission test is internal. - catchRuinedTown(player); - townSet(player, StringMgmt.remFirstArg(split), false, null); - break; - case "buy": - checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_BUY.getNode()); - catchRuinedTown(player); - townBuy(player, StringMgmt.remFirstArg(split), null, false); - break; - case "toggle": - // Permission test is internal. - catchRuinedTown(player); - townToggle(player, StringMgmt.remFirstArg(split), false, null); - break; - case "outpost": - // Permission test is internal. - catchRuinedTown(player); - townOutpost(player, StringMgmt.remFirstArg(split)); - break; - case "delete": - checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_DELETE.getNode()); - catchRuinedTown(player); - townDelete(player, StringMgmt.remFirstArg(split)); - break; - case "ranklist": - checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_RANKLIST.getNode()); - catchRuinedTown(player); - town = split.length > 1 ? getTownOrThrow(split[1]) : getTownFromPlayerOrThrow(player); - TownyMessaging.sendMessage(player, TownyFormatter.getRanksForTown(town, Translator.locale(player))); - break; - case "add": - checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_INVITE_ADD.getNode()); - catchRuinedTown(player); - townAdd(player, null, StringMgmt.remFirstArg(split)); - break; - case "invite", "invites": - // Permission test is internal. - catchRuinedTown(player); - parseInviteCommand(player, StringMgmt.remFirstArg(split)); - break; - case "kick": - checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_KICK.getNode()); - catchRuinedTown(player); - townKick(player, StringMgmt.remFirstArg(split)); - break; - case "claim": - // Permission test is internal. - catchRuinedTown(player); - parseTownClaimCommand(player, StringMgmt.remFirstArg(split)); - break; - case "unclaim": - checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_UNCLAIM.getNode()); - catchRuinedTown(player); - parseTownUnclaimCommand(player, StringMgmt.remFirstArg(split)); - break; - case "takeoverclaim": - catchRuinedTown(player); - parseTownTakeoverClaimCommand(player); - break; - case "online": - checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_ONLINE.getNode()); - catchRuinedTown(player); - parseTownOnlineCommand(player, StringMgmt.remFirstArg(split)); - break; - case "say": - checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_SAY.getNode()); - catchRuinedTown(player); - getTownFromPlayerOrThrow(player).playerBroadCastMessageToTown(player, StringMgmt.join(StringMgmt.remFirstArg(split))); - break; - case "outlaw", "ban": - checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_OUTLAW.getNode()); - catchRuinedTown(player); - parseTownOutlawCommand(player, StringMgmt.remFirstArg(split), false, getResidentOrThrow(player).getTown()); - break; - case "bankhistory": - checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_BANKHISTORY.getNode()); - catchRuinedTown(player); - int pages = 10; - if (split.length > 1) - pages = MathUtil.getIntOrThrow(split[1]); - getTownFromPlayerOrThrow(player).generateBankHistoryBook(player, pages); - break; - case "merge": - checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_MERGE.getNode()); - catchRuinedTown(player); - parseTownMergeCommand(player, StringMgmt.remFirstArg(split)); - break; - case "jail": - checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_JAIL.getNode()); - catchRuinedTown(player); - parseJailCommand(player, null, StringMgmt.remFirstArg(split), false); - break; - case "unjail": - checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_UNJAIL.getNode()); - catchRuinedTown(player); - parseUnJailCommand(player, null, StringMgmt.remFirstArg(split), false); - break; - case "purge": - checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_PURGE.getNode()); - catchRuinedTown(player); - parseTownPurgeCommand(player, StringMgmt.remFirstArg(split)); - break; - case "trust": - catchRuinedTown(player); - parseTownTrustCommand(player, StringMgmt.remFirstArg(split), null); - break; - case "trusttown": - catchRuinedTown(player); - parseTownTrustTownCommand(player, StringMgmt.remFirstArg(split), null); - break; - case "baltop": - catchRuinedTown(player); - town = split.length > 1 ? getTownOrThrow(split[1]) : getTownFromPlayerOrThrow(player); - parseTownBaltop(player, town); - break; - case "forsale": - case "fs": - checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_FORSALE.getNode()); - parseTownForSaleCommand(player, StringMgmt.remFirstArg(split)); - break; - case "notforsale": - case "nfs": - checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_NOTFORSALE.getNode()); - parseTownNotForSaleCommand(player); - break; - case "buytown": - checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_BUYTOWN.getNode()); - parseTownBuyTownCommand(player, StringMgmt.remFirstArg(split)); - break; - - default: + case "add"-> townAdd(player, null, StringMgmt.remFirstArg(split)); + case "allylist"-> townAllyList(player, split); + case "baltop"-> parseTownBaltop(player, split.length > 1 ? getTownOrThrow(split[1]) : getTownFromPlayerOrThrow(player)); + case "bankhistory"-> parseTownBankHistoryCommand(player, split); + case "buy"-> townBuy(player, StringMgmt.remFirstArg(split), null, false); + case "buytown"-> parseTownBuyTownCommand(player, StringMgmt.remFirstArg(split)); + case "claim"-> parseTownClaimCommand(player, StringMgmt.remFirstArg(split)); + case "delete"-> townDelete(player, StringMgmt.remFirstArg(split)); + case "deposit"-> parseTownDepositCommand(player, split); + case "enemylist"-> townEnemyList(player, split); + case "forsale", "fs"-> parseTownForSaleCommand(player, StringMgmt.remFirstArg(split)); + case "here" -> parseTownHereCommand(player); + case "invite", "invites"-> parseInviteCommand(player, StringMgmt.remFirstArg(split)); + case "jail"-> parseJailCommand(player, null, StringMgmt.remFirstArg(split), false); + case "join"-> parseTownJoin(player, StringMgmt.remFirstArg(split)); + case "kick"-> townKick(player, StringMgmt.remFirstArg(split)); + case "leave"-> townLeave(player); + case "list" -> listTowns(player, split); + case "mayor" -> parseTownyMayorCommand(player); + case "merge"-> parseTownMergeCommand(player, StringMgmt.remFirstArg(split)); + case "new", "create"-> parseTownNewCommand(player, split); + case "notforsale", "nfs"-> parseTownNotForSaleCommand(player); + case "online"-> parseTownOnlineCommand(player, StringMgmt.remFirstArg(split)); + case "outlaw", "ban"-> parseTownOutlawCommand(player, StringMgmt.remFirstArg(split), false, getResidentOrThrow(player).getTown()); + case "outlawlist"-> townOutlawList(player, split); + case "outpost"-> townOutpost(player, StringMgmt.remFirstArg(split)); + case "plotgrouplist"-> townPlotGroupList(player, split); + case "plots"-> townPlots(player, split); + case "purge"-> parseTownPurgeCommand(player, StringMgmt.remFirstArg(split)); + case "rank"-> townRank(player, StringMgmt.remFirstArg(split)); + case "ranklist"-> parseTownRanklistCommand(player, split); + case "reclaim"-> parseTownReclaimCommand(player); + case "reslist"-> townResList(player, split); + case "say"-> parseTownSayCommand(player, split); + case "set"-> townSet(player, StringMgmt.remFirstArg(split), false, null); + case "spawn"-> townSpawn(player, StringMgmt.remFirstArg(split), false, split.length > 2 && split[2].equals("-ignore")); + case "takeoverclaim"-> parseTownTakeoverClaimCommand(player); + case "toggle"-> townToggle(player, StringMgmt.remFirstArg(split), false, null); + case "trust"-> parseTownTrustCommand(player, StringMgmt.remFirstArg(split), null); + case "trusttown"-> parseTownTrustTownCommand(player, StringMgmt.remFirstArg(split), null); + case "unclaim"-> parseTownUnclaimCommand(player, StringMgmt.remFirstArg(split)); + case "unjail"-> parseUnJailCommand(player, null, StringMgmt.remFirstArg(split), false); + case "withdraw"-> parseTownWithdrawCommand(player, split); + default -> { // Test if this is an addon command if (tryTownAddonCommand(player, split)) return; // Test if this is a town status screen lookup. if (tryTownStatusScreen(player, split)) return; - + // Alert the player that the subcommand doesn't exist. throw new TownyException(Translatable.of("msg_err_invalid_sub")); } + } } private boolean tryTownStatusScreen(CommandSender sender, String[] split) throws NoPermissionException { @@ -876,11 +708,16 @@ private boolean tryTownAddonCommand(CommandSender sender, String[] split) { return false; } - private void catchRuinedTown(Player player) throws TownyException { + private static void catchRuinedTown(Player player) throws TownyException { if (TownRuinUtil.isPlayersTownRuined(player)) throw new TownyException(Translatable.of("msg_err_cannot_use_command_because_town_ruined")); } + private void parseTownyMayorCommand(final Player player) throws NoPermissionException { + checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_MAYOR.getNode()); + HelpMenu.TOWN_MAYOR_HELP.send(player); + } + private void townEnemyList(Player player, String[] split) throws TownyException { Town town = split.length == 1 ? getTownFromPlayerOrThrow(player) : getTownOrThrow(split[1]); @@ -908,7 +745,8 @@ private void parseTownPurgeCommand(Player player, String[] arg) throws TownyExce HelpMenu.TOWN_PURGE.send(player); return; } - + checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_PURGE.getNode()); + catchRuinedTown(player); Town town = getTownFromPlayerOrThrow(player); int days = MathUtil.getIntOrThrow(arg[0]); @@ -928,6 +766,7 @@ private void parseTownPurgeCommand(Player player, String[] arg) throws TownyExce } private void parseInviteCommand(Player player, String[] newSplit) throws TownyException { + catchRuinedTown(player); Resident resident = getResidentOrThrow(player); String received = Translatable.of("town_received_invites").forLocale(player) @@ -1096,9 +935,11 @@ public static void parseTownOutlawCommand(CommandSender sender, String[] split, if (split.length < 2) throw new TownyException(Translatable.of("msg_usage", "/town outlaw add/remove [name]")); - if (!admin) + if (!admin) { resident = getResidentOrThrow(sender.getName()); - else + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_OUTLAW.getNode()); + catchRuinedTown((Player) sender); + } else resident = town.getMayor(); // if this is an Admin-initiated command, dupe the action as if it were done by the mayor. target = townyUniverse.getResident(split[1]); @@ -1204,12 +1045,25 @@ public static void parseTownOutlawCommand(CommandSender sender, String[] split, } + private void parseTownWithdrawCommand(final Player player, String[] split) throws NoPermissionException { + checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_WITHDRAW.getNode()); + TownyEconomyHandler.economyExecutor().execute(() -> townTransaction(player, StringMgmt.remFirstArg(split), true)); + } + + private void parseTownDepositCommand(final Player player, String[] split) throws NoPermissionException { + checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_DEPOSIT.getNode()); + TownyEconomyHandler.economyExecutor().execute(() -> townTransaction(player, StringMgmt.remFirstArg(split), false)); + } + private void townPlots(CommandSender sender, String[] args) throws TownyException { Player player = null; if (sender instanceof Player) player = (Player) sender; - + + if (player != null) + checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_PLOTS.getNode()); + Town town; if (args.length == 1 && player != null) { catchRuinedTown(player); @@ -1252,6 +1106,8 @@ private void townPlots(CommandSender sender, String[] args) throws TownyExceptio } private void parseTownOnlineCommand(Player player, String[] split) throws TownyException { + checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_ONLINE.getNode()); + catchRuinedTown(player); Translator translator = Translator.locale(player); if (split.length > 0) { Town town = getTownOrThrow(split[0]); @@ -1267,6 +1123,15 @@ private void parseTownOnlineCommand(Player player, String[] split) throws TownyE } } + private void parseTownHereCommand(final Player player) throws NoPermissionException, TownyException { + Town town; + checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_HERE.getNode()); + town = TownyAPI.getInstance().getTown(player.getLocation()); + if (town == null) + throw new TownyException(Translatable.of("msg_not_claimed", Coord.parseCoord(player.getLocation()))); + townStatusScreen(player, town); + } + /** * Send a list of all towns in the universe to player Command: /town list * @@ -1385,6 +1250,7 @@ public static void townToggle(CommandSender sender, String[] split, boolean admi return; } if (!admin) { + catchRuinedTown((Player) sender); Resident resident = getResidentOrThrow(sender.getName()); town = resident.getTown(); checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_TOGGLE.getNode(split[0].toLowerCase(Locale.ROOT))); @@ -1648,8 +1514,11 @@ private static void townToggleNationZone(CommandSender sender, boolean admin, To private static void parseUnJailCommand(CommandSender sender, Town town, String[] split, boolean admin) throws TownyException { - if (!admin) + if (!admin) { town = getTownFromPlayerOrThrow((Player) sender); + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_UNJAIL.getNode()); + catchRuinedTown((Player) sender); + } if (split.length != 1) { HelpMenu.TOWN_UNJAIL.send(sender); @@ -1667,8 +1536,11 @@ private static void parseUnJailCommand(CommandSender sender, Town town, String[] private static void parseJailCommand(CommandSender sender, Town town, String[] split, boolean admin) throws TownyException { - if (!admin) + if (!admin) { town = getTownFromPlayerOrThrow((Player) sender); + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_JAIL.getNode()); + catchRuinedTown((Player) sender); + } if (!town.hasJails()) throw new TownyException(Translatable.of("msg_town_has_no_jails")); @@ -1894,7 +1766,7 @@ private static void toggleTest(Town town, String split) throws TownyException { } public void townRank(Player player, String[] split) throws TownyException { - + catchRuinedTown(player); if (split.length == 0) { // Help output. TownyMessaging.sendMessage(player, ChatTools.formatTitle("/town rank")); @@ -1978,6 +1850,13 @@ public void townRank(Player player, String[] split) throws TownyException { } + + private void parseTownSayCommand(final Player player, String[] split) throws NoPermissionException, TownyException { + checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_SAY.getNode()); + catchRuinedTown(player); + TownyMessaging.sendPrefixedTownMessage(getTownFromPlayerOrThrow(player), TownyComponents.stripClickTags(StringMgmt.join(StringMgmt.remFirstArg(split)))); + } + public static void townSet(CommandSender sender, String[] split, boolean admin, Town town) throws TownyException { if (split.length == 0) { @@ -1987,8 +1866,10 @@ public static void townSet(CommandSender sender, String[] split, boolean admin, Resident resident; Nation nation = null; Player player = null; - if (sender instanceof Player p) + if (sender instanceof Player p) { + catchRuinedTown(p); player = p; + } if (!admin && player != null) { resident = getResidentOrThrow(player); @@ -2621,7 +2502,8 @@ public static void townSetTaxPercent(CommandSender sender, String[] split, Town TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_town_set_tax_max_percent_amount", sender.getName(), TownyEconomyHandler.getFormattedBalance(town.getMaxPercentTaxAmount()))); } - private static void parseTownBaltop(Player player, Town town) { + private static void parseTownBaltop(Player player, Town town) throws TownyException { + catchRuinedTown(player); plugin.getScheduler().runAsync(() -> { StringBuilder sb = new StringBuilder(); List<Resident> residents = new ArrayList<>(town.getResidents()); @@ -2637,12 +2519,14 @@ private static void parseTownBaltop(Player player, Town town) { } public static void townBuy(CommandSender sender, String[] split, @Nullable Town town, boolean admin) throws TownyException { - if (!TownyEconomyHandler.isActive()) throw new TownyException(Translatable.of("msg_err_no_economy")); - if (town == null && sender instanceof Player player) + if (town == null && sender instanceof Player player) { + checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_BUY.getNode()); + catchRuinedTown(player); town = getTownFromPlayerOrThrow(player); + } if (!TownySettings.isSellingBonusBlocks(town) && !TownySettings.isBonusBlocksPerTownLevel()) throw new TownyException("Config.yml has bonus blocks diabled at max_purchased_blocks: '0' "); @@ -2707,6 +2591,17 @@ public static void townBuyBonusTownBlocks(Town town, int inputN, CommandSender s .sendTo(sender); } + private void parseTownNewCommand(final Player player, String[] split) throws NoPermissionException, TownyException { + checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_NEW.getNode()); + if (split.length == 1) { + throw new TownyException(Translatable.of("msg_specify_name")); + } else { + String townName = String.join("_", StringMgmt.remFirstArg(split)); + boolean noCharge = TownySettings.getNewTownPrice() == 0.0 || !TownyEconomyHandler.isActive(); + newTown(player, townName, getResidentOrThrow(player), noCharge); + } + } + /** * Create a new town. Command: /town new [town] * @@ -2942,7 +2837,7 @@ public static void townRename(CommandSender sender, Town town, String newName) { } public void townLeave(Player player) throws TownyException { - + checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_LEAVE.getNode()); Resident resident = getResidentOrThrow(player); Town town = getTownFromResidentOrThrow(resident); @@ -3003,6 +2898,8 @@ public static void townSpawn(Player player, String[] split, Boolean outpost, boo } public void townDelete(Player player, String[] split) throws TownyException { + checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_DELETE.getNode()); + catchRuinedTown(player); TownyUniverse townyUniverse = TownyUniverse.getInstance(); final Town town = split.length == 0 @@ -3040,18 +2937,13 @@ public void townDelete(Player player, String[] split) throws TownyException { * * @param player - Player who initiated the kick command. * @param names - List of names to kick. + * @throws TownyException on error. */ - public static void townKick(Player player, String[] names) { - - Resident resident; - Town town; - try { - resident = getResidentOrThrow(player); - town = resident.getTown(); - } catch (TownyException x) { - TownyMessaging.sendErrorMsg(player, x.getMessage(player)); - return; - } + public static void townKick(Player player, String[] names) throws TownyException { + checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_KICK.getNode()); + catchRuinedTown(player); + Resident resident = getResidentOrThrow(player); + Town town = resident.getTown(); townKickResidents(player, resident, town, ResidentUtil.getValidatedResidentsOfTown(player, town, names)); @@ -3266,6 +3158,23 @@ public static void checkTownResidents(Town town) { } } + private void parseTownRanklistCommand(final Player player, String[] split) + throws NoPermissionException, TownyException { + Town town; + checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_RANKLIST.getNode()); + catchRuinedTown(player); + town = split.length > 1 ? getTownOrThrow(split[1]) : getTownFromPlayerOrThrow(player); + TownyMessaging.sendMessage(player, TownyFormatter.getRanksForTown(town, Translator.locale(player))); + } + + private void parseTownReclaimCommand(final Player player) throws NoPermissionException, TownyException { + if (!TownySettings.getTownRuinsReclaimEnabled()) + throw new TownyException(Translatable.of("msg_err_command_disable")); + + checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_RECLAIM.getNode()); + TownRuinUtil.processRuinedTownReclaimRequest(player); + } + /** * If no arguments are given (or error), send usage of command. If sender is * a player: args = [town]. Elsewise: args = [resident] [town] @@ -3288,6 +3197,7 @@ public static void parseTownJoin(CommandSender sender, String[] args) { throw new TownyException(Translatable.of("msg_usage", "/town join [town]")); Player player = (Player) sender; + checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_JOIN.getNode()); residentName = player.getName(); townName = args[0]; contextualResidentName = "You"; @@ -3351,9 +3261,16 @@ public static void parseTownJoin(CommandSender sender, String[] args) { * @throws TownyException - General Exception, or if Town's spawn has not been set */ public static void townAdd(CommandSender sender, Town specifiedTown, String[] names) throws TownyException { - - String name = sender instanceof Player player ? player.getName() : "Console"; - boolean console = !(sender instanceof Player); + String name; + boolean console = false; + if (sender instanceof Player player) { + name = player.getName(); + checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_INVITE_ADD.getNode()); + catchRuinedTown(player); + } else { + name = "Console"; + console = true; + } Resident resident; Town town; @@ -3629,6 +3546,7 @@ public static void parseTownClaimCommand(Player player, String[] split) throws T return; } + catchRuinedTown(player); Resident resident = getResidentOrThrow(player); Town town = getTownFromResidentOrThrow(resident); @@ -3811,6 +3729,8 @@ public static void parseTownUnclaimCommand(Player player, String[] split) throws HelpMenu.TOWN_UNCLAIM.send(player); return; } + checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_UNCLAIM.getNode()); + catchRuinedTown(player); Resident resident = getResidentOrThrow(player); Town town = getTownFromResidentOrThrow(resident); @@ -3990,7 +3910,19 @@ private boolean takeoverWouldCutATownIntoTwoSections(WorldCoord worldCoord, Town return wildOr3rdPartyOwned > 0; } + private void parseTownBankHistoryCommand(final Player player, String[] split) + throws NoPermissionException, TownyException { + checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_BANKHISTORY.getNode()); + catchRuinedTown(player); + int pages = 10; + if (split.length > 1) + pages = MathUtil.getIntOrThrow(split[1]); + getTownFromPlayerOrThrow(player).generateBankHistoryBook(player, pages); + } + public static void parseTownMergeCommand(Player player, String[] args) throws TownyException { + checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_MERGE.getNode()); + catchRuinedTown(player); parseTownMergeCommand(player, args, getTownFromPlayerOrThrow(player), false); } @@ -4249,7 +4181,7 @@ private static void townTransaction(Player player, String[] args, boolean withdr } private static void townOutpost(Player player, String[] args) throws TownyException { - + catchRuinedTown(player); if (args.length >= 1) { if (args[0].equalsIgnoreCase("list")) { checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_OUTPOST_LIST.getNode()); @@ -4289,6 +4221,9 @@ private void townResList(CommandSender sender, String[] args) throws TownyExcept if (sender instanceof Player) player = (Player) sender; + if (player != null) + checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_RESLIST.getNode()); + Town town = null; if (args.length == 1 && player != null) { catchRuinedTown(player); @@ -4308,8 +4243,10 @@ private void townPlotGroupList(CommandSender sender, String[] args) throws Towny if (sender instanceof Player) player = (Player) sender; - if (player != null) + if (player != null) { + checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_PLOTGROUPLIST.getNode()); catchRuinedTown(player); + } Town town = null; if (args.length > 1) // not just /town plotgrouplist @@ -4359,8 +4296,10 @@ public static void parseTownTrustCommand(CommandSender sender, String[] args, @N return; } - if (town == null && sender instanceof Player player) + if (town == null && sender instanceof Player player) { town = getTownFromPlayerOrThrow(player); + catchRuinedTown(player); + } if (args[0].equalsIgnoreCase("list")) { parseTownTrustListCommand(sender, town); @@ -4431,6 +4370,7 @@ public static void parseTownTrustTownCommand(CommandSender sender, String[] args if (town == null && sender instanceof Player player) { town = getTownFromPlayerOrThrow(player); + catchRuinedTown(player); } if ("list".equalsIgnoreCase(args[0])) { TownyMessaging.sendMessage(sender, TownyFormatter.getFormattedTownyObjects(Translatable.of("status_trustedlist").forLocale(sender), new ArrayList<>(town.getTrustedTowns()))); @@ -4507,6 +4447,8 @@ private static int homeBlockDistance(Town town1, Town town2) { } private void parseTownForSaleCommand(Player player, String[] args) throws TownyException { + checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_FORSALE.getNode()); + if (args.length == 0) throw new TownyException(Translatable.of("msg_error_must_be_num")); @@ -4523,6 +4465,7 @@ private void parseTownForSaleCommand(Player player, String[] args) throws TownyE } private void parseTownNotForSaleCommand(Player player) throws TownyException { + checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_NOTFORSALE.getNode()); Town town = getTownFromPlayerOrThrow(player); if (!town.isForSale()) @@ -4550,6 +4493,7 @@ public static void setTownNotForSale(Town town, boolean admin) { private void parseTownBuyTownCommand(CommandSender sender, String[] args) throws TownyException { catchConsole(sender); Player player = (Player) sender; + checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_BUYTOWN.getNode()); if (args.length == 0) { throw new TownyException(Translatable.of("msg_specify_name")); From 67ee0e5214236225f3543ce61869f937ec744bd3 Mon Sep 17 00:00:00 2001 From: LlmDl <llmdlio@gmail.com> Date: Wed, 18 Oct 2023 16:46:09 -0500 Subject: [PATCH 7/8] Simplify invite command. --- .../bukkit/towny/command/TownCommand.java | 207 ++++++++---------- 1 file changed, 87 insertions(+), 120 deletions(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownCommand.java b/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownCommand.java index a7e9f9db3b..55eb86c04f 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownCommand.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownCommand.java @@ -765,7 +765,7 @@ private void parseTownPurgeCommand(Player player, String[] arg) throws TownyExce .sendTo(player); } - private void parseInviteCommand(Player player, String[] newSplit) throws TownyException { + private void parseInviteCommand(Player player, String[] args) throws TownyException { catchRuinedTown(player); Resident resident = getResidentOrThrow(player); @@ -776,143 +776,110 @@ private void parseInviteCommand(Player player, String[] newSplit) throws TownyEx .replace("%a", Integer.toString(resident.getTown().getSentInvites().size())) .replace("%m", Integer.toString(InviteHandler.getSentInvitesMaxAmount(resident.getTown()))); - if (newSplit.length == 0) { // (/town invite) + if (args.length == 0 || args[0].equalsIgnoreCase("help") || args[0].equalsIgnoreCase("?") ) { checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_INVITE_SEE_HOME.getNode()); - HelpMenu.TOWN_INVITE.send(player); TownyMessaging.sendMessage(player, sent); TownyMessaging.sendMessage(player, received); return; } - if (newSplit.length >= 1) { // /town invite [something] - if (newSplit[0].equalsIgnoreCase("help") || newSplit[0].equalsIgnoreCase("?")) { - HelpMenu.TOWN_INVITE.send(player); - return; - } - if (newSplit[0].equalsIgnoreCase("sent")) { // /invite(remfirstarg) sent args[1] - checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_INVITE_LIST_SENT.getNode()); + switch (args[0].toLowerCase(Locale.ROOT)) { + case "sent" -> parseTownInviteSentCommand(player, StringMgmt.remFirstArg(args), resident, sent); + case "received" -> parseTownInviteReceivedCommand(player, StringMgmt.remFirstArg(args), resident, received); + case "accept" -> parseTownInviteAcceptCommand(player, StringMgmt.remFirstArg(args), resident); + case "deny" -> parseTownInviteDenyCommand(player, StringMgmt.remFirstArg(args), resident); + case "add" -> parseTownInviteAddCommand(player, StringMgmt.remFirstArg(args)); + default -> throw new TownyException(Translatable.of("msg_err_invalid_sub")); + } + } - List<Invite> sentinvites = resident.getTown().getSentInvites(); - int page = 1; - if (newSplit.length >= 2) { - try { - page = Integer.parseInt(newSplit[1]); - } catch (NumberFormatException ignored) { - } - } - InviteCommand.sendInviteList(player, sentinvites, page, true); - TownyMessaging.sendMessage(player, sent); - return; - } - if (newSplit[0].equalsIgnoreCase("received")) { // /town invite received - checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_INVITE_LIST_RECEIVED.getNode()); + private void parseTownInviteSentCommand(Player player, String[] args, Resident resident, String sent) throws TownyException { + checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_INVITE_LIST_SENT.getNode()); - List<Invite> receivedinvites = resident.getTown().getReceivedInvites(); - int page = 1; - if (newSplit.length >= 2) { - try { - page = Integer.parseInt(newSplit[1]); - } catch (NumberFormatException ignored) { - } - } - InviteCommand.sendInviteList(player, receivedinvites, page, false); - TownyMessaging.sendMessage(player, received); + List<Invite> sentinvites = resident.getTown().getSentInvites(); + int page = args.length > 0 ? MathUtil.getPositiveIntOrThrow(args[0]) : 1; + InviteCommand.sendInviteList(player, sentinvites, page, true); + TownyMessaging.sendMessage(player, sent); + } + + private void parseTownInviteReceivedCommand(Player player, String[] args, Resident resident, String received) throws TownyException { + checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_INVITE_LIST_RECEIVED.getNode()); + + List<Invite> receivedinvites = resident.getTown().getReceivedInvites(); + int page = args.length > 0 ? MathUtil.getPositiveIntOrThrow(args[0]) : 1; + InviteCommand.sendInviteList(player, receivedinvites, page, false); + TownyMessaging.sendMessage(player, received); + } + + private void parseTownInviteAcceptCommand(Player player, String[] args, Resident resident) throws TownyException { + checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_INVITE_ACCEPT.getNode()); + Town town = resident.getTown(); + List<Invite> invites = town.getReceivedInvites(); + + if (invites.size() == 0) + throw new TownyException(Translatable.of("msg_err_town_no_invites")); + + if (args.length == 0) { // /invite accept + TownyMessaging.sendErrorMsg(player, Translatable.of("msg_err_town_specify_invite")); + InviteCommand.sendInviteList(player, invites, 1, false); + return; + } + + Nation nation = getNationOrThrow(args[0]); + Invite toAccept = null; + for (Invite invite : InviteHandler.getActiveInvites()) { + if (invite.getSender().equals(nation) && invite.getReceiver().equals(town)) { + toAccept = invite; + break; + } + } + if (toAccept != null) { + try { + InviteHandler.acceptInvite(toAccept); return; + } catch (TownyException | InvalidObjectException e) { + plugin.getLogger().log(Level.WARNING, "unknown exception occurred while accepting invite", e); } - if (newSplit[0].equalsIgnoreCase("accept")) { - checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_INVITE_ACCEPT.getNode()); - - // /town (gone) - // invite (gone) - // args[0] = accept = length = 1 - // args[1] = [Nation] = length = 2 - Town town = resident.getTown(); - Nation nation; - List<Invite> invites = town.getReceivedInvites(); - - if (invites.size() == 0) { - TownyMessaging.sendErrorMsg(player, Translatable.of("msg_err_town_no_invites")); - return; - } - if (newSplit.length >= 2) { // /invite deny args[1] - nation = TownyUniverse.getInstance().getNation(newSplit[1]); - - if (nation == null) { - TownyMessaging.sendErrorMsg(player, Translatable.of("msg_invalid_name")); - return; - } - } else { - TownyMessaging.sendErrorMsg(player, Translatable.of("msg_err_town_specify_invite")); - InviteCommand.sendInviteList(player, invites, 1, false); - return; - } + } + } - Invite toAccept = null; - for (Invite invite : InviteHandler.getActiveInvites()) { - if (invite.getSender().equals(nation) && invite.getReceiver().equals(town)) { - toAccept = invite; - break; - } - } - if (toAccept != null) { - try { - InviteHandler.acceptInvite(toAccept); - return; - } catch (TownyException | InvalidObjectException e) { - plugin.getLogger().log(Level.WARNING, "unknown exception occurred while accepting invite", e); - } - } - } - if (newSplit[0].equalsIgnoreCase("deny")) { // /town invite deny - checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_INVITE_DENY.getNode()); + private void parseTownInviteDenyCommand(Player player, String[] args, Resident resident) throws TownyException { + checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_INVITE_DENY.getNode()); + Town town = resident.getTown(); + List<Invite> invites = town.getReceivedInvites(); - Town town = resident.getTown(); - Nation nation; - List<Invite> invites = town.getReceivedInvites(); + if (invites.size() == 0) + throw new TownyException(Translatable.of("msg_err_town_no_invites")); - if (invites.size() == 0) { - TownyMessaging.sendErrorMsg(player, Translatable.of("msg_err_town_no_invites")); - return; - } - if (newSplit.length >= 2) { // /invite deny args[1] - nation = TownyUniverse.getInstance().getNation(newSplit[1]); - - if (nation == null) { - TownyMessaging.sendErrorMsg(player, Translatable.of("msg_invalid_name")); - return; - } - } else { - TownyMessaging.sendErrorMsg(player, Translatable.of("msg_err_town_specify_invite")); - InviteCommand.sendInviteList(player, invites, 1, false); - return; - } - - Invite toDecline = null; - - for (Invite invite : InviteHandler.getActiveInvites()) { - if (invite.getSender().equals(nation) && invite.getReceiver().equals(town)) { - toDecline = invite; - break; - } - } - if (toDecline != null) { - try { - InviteHandler.declineInvite(toDecline, false); - TownyMessaging.sendMsg(player, Translatable.of("successful_deny")); - } catch (InvalidObjectException e) { - plugin.getLogger().log(Level.WARNING, "unknown exception occurred while declining invite", e); // Shouldn't happen, however like i said a fallback - } - } - } else { - checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_INVITE_ADD.getNode()); + if (args.length == 0) { + TownyMessaging.sendErrorMsg(player, Translatable.of("msg_err_town_specify_invite")); + InviteCommand.sendInviteList(player, invites, 1, false); + return; + } - townAdd(player, null, newSplit); - // It's none of those 4 subcommands, so it's a playername, I just expect it to be ok. - // If it is invalid it is handled in townAdd() so, I'm good + Nation nation = getNationOrThrow(args[0]); + Invite toDecline = null; + for (Invite invite : InviteHandler.getActiveInvites()) { + if (invite.getSender().equals(nation) && invite.getReceiver().equals(town)) { + toDecline = invite; + break; + } + } + if (toDecline != null) { + try { + InviteHandler.declineInvite(toDecline, false); + TownyMessaging.sendMsg(player, Translatable.of("successful_deny")); + } catch (InvalidObjectException e) { + plugin.getLogger().log(Level.WARNING, "unknown exception occurred while declining invite", e); // Shouldn't happen, however like i said a fallback } } } + private void parseTownInviteAddCommand(Player player, String[] newSplit) throws TownyException { + checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_INVITE_ADD.getNode()); + townAdd(player, null, newSplit); + } + public static void parseTownOutlawCommand(CommandSender sender, String[] split, boolean admin, Town town) throws TownyException { TownyUniverse townyUniverse = TownyUniverse.getInstance(); From 14ba33ec493a6812f82cdffd20efc04119d6d0c5 Mon Sep 17 00:00:00 2001 From: LlmDl <llmdlio@gmail.com> Date: Wed, 18 Oct 2023 17:09:42 -0500 Subject: [PATCH 8/8] Simplify outlaw command. --- .../bukkit/towny/command/TownCommand.java | 192 ++++++++---------- 1 file changed, 83 insertions(+), 109 deletions(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownCommand.java b/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownCommand.java index 55eb86c04f..9d3a57d33c 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownCommand.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownCommand.java @@ -881,135 +881,109 @@ private void parseTownInviteAddCommand(Player player, String[] newSplit) throws } public static void parseTownOutlawCommand(CommandSender sender, String[] split, boolean admin, Town town) throws TownyException { - TownyUniverse townyUniverse = TownyUniverse.getInstance(); - if (split.length == 0) { // Help output. if (!admin) HelpMenu.TOWN_OUTLAW_HELP.send(sender); else HelpMenu.TA_TOWN_OUTLAW.send(sender); + return; + } - } else { + /* + * Does the command have enough arguments? + */ + if (split.length < 2) + throw new TownyException(Translatable.of("msg_usage", "/town outlaw add/remove [name]")); - Resident resident; - Resident target; - Town targetTown = null; + Resident resident; + if (!admin) { + resident = getResidentOrThrow(sender.getName()); + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_OUTLAW.getNode()); + catchRuinedTown((Player) sender); + } else + resident = town.getMayor(); // if this is an Admin-initiated command, dupe the action as if it were done by the mayor. - /* - * Does the command have enough arguments? - */ - if (split.length < 2) - throw new TownyException(Translatable.of("msg_usage", "/town outlaw add/remove [name]")); + Resident target = getResidentOrThrow(split[1]); - if (!admin) { - resident = getResidentOrThrow(sender.getName()); - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_OUTLAW.getNode()); - catchRuinedTown((Player) sender); - } else - resident = town.getMayor(); // if this is an Admin-initiated command, dupe the action as if it were done by the mayor. - - target = townyUniverse.getResident(split[1]); - - if (target == null) { - TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_err_invalid_name", split[1])); - return; - } + switch (split[0].toLowerCase(Locale.ROOT)) { + case "add" -> parseTownOutlawAddCommand(sender, admin, town, resident, target); + case "remove" -> parseTownOutlawRemoveCommand(sender, admin, town, target); + default -> throw new TownyException(Translatable.of("msg_err_invalid_property", split[0])); + } + } - if (split[0].equalsIgnoreCase("add")) { - try { - // Get the target resident's town if they have a town. - if (target.hasTown()) - targetTown = TownyAPI.getInstance().getResidentTownOrNull(target); - - // Don't allow a resident to outlaw their own mayor. - if (resident.getTown().getMayor().equals(target)) - return; - - // Call cancellable event. - BukkitTools.ifCancelledThenThrow(new TownOutlawAddEvent(sender, target, town)); - - // Kick outlaws from town if they are residents. - if (targetTown != null && targetTown.getUUID().equals(town.getUUID())) { - target.removeTown(); - Object outlawer = (admin ? Translatable.of("admin_sing") : sender.getName()); - TownyMessaging.sendMsg(target, Translatable.of("msg_kicked_by", outlawer)); - TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_kicked", outlawer, target.getName())); - } - - // Add the outlaw and save the town. - town.addOutlaw(target); - town.save(); - - // Send feedback messages. - if (target.getPlayer() != null && target.getPlayer().isOnline()) { - TownyMessaging.sendMsg(target, Translatable.of("msg_you_have_been_declared_outlaw", town.getName())); - Location loc = target.getPlayer().getLocation(); - - // If the newly-outlawed player is within the town's borders and is meant to be teleported away, - // send them using the outlaw teleport warmup time, potentially giving them the chance to escape - // the borders. - if (TownySettings.areNewOutlawsTeleportedAway() - && TownyAPI.getInstance().getTownBlock(loc) != null - && TownyAPI.getInstance().getTown(loc) == town) { - - OutlawTeleportEvent event = new OutlawTeleportEvent(target, town, loc); - if (BukkitTools.isEventCancelled(event)) - return; - - if (TownySettings.getOutlawTeleportWarmup() > 0) - TownyMessaging.sendMsg(target, Translatable.of("msg_outlaw_kick_cooldown", town, TimeMgmt.formatCountdownTime(TownySettings.getOutlawTeleportWarmup()))); - - final Resident outlawRes = target; - plugin.getScheduler().runLater(() -> { - if (TownyAPI.getInstance().getTown(loc) == town) - SpawnUtil.outlawTeleport(town, outlawRes); - }, TownySettings.getOutlawTeleportWarmup() * 20L); - } - } - TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_you_have_declared_an_outlaw", target.getName(), town.getName())); - if (admin) - TownyMessaging.sendMsg(sender, Translatable.of("msg_you_have_declared_an_outlaw", target.getName(), town.getName())); - } catch (AlreadyRegisteredException e) { - // Must already be an outlaw - TownyMessaging.sendMsg(sender, Translatable.of("msg_err_resident_already_an_outlaw")); - return; - } + private static void parseTownOutlawAddCommand(CommandSender sender, boolean admin, Town town, Resident resident, Resident target) throws TownyException { + // Don't allow a resident to outlaw their own mayor. + if (resident.getTown().getMayor().equals(target)) + return; - } else if (split[0].equalsIgnoreCase("remove")) { - if (town.hasOutlaw(target)) { + if (town.hasOutlaw(target)) + throw new TownyException(Translatable.of("msg_err_resident_already_an_outlaw")); - // Call cancellable event. - BukkitTools.ifCancelledThenThrow(new TownOutlawRemoveEvent(sender, target, town)); + // Call cancellable event. + BukkitTools.ifCancelledThenThrow(new TownOutlawAddEvent(sender, target, town)); - town.removeOutlaw(target); - town.save(); + // Kick outlaws from town if they are residents. + if (town.hasResident(target)) { + target.removeTown(); + Object outlawer = (admin ? Translatable.of("admin_sing") : sender.getName()); + TownyMessaging.sendMsg(target, Translatable.of("msg_kicked_by", outlawer)); + TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_kicked", outlawer, target.getName())); + } - // Send feedback messages. - if (target.getPlayer() != null && target.getPlayer().isOnline()) - TownyMessaging.sendMsg(target, Translatable.of("msg_you_have_been_undeclared_outlaw", town.getName())); - TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_you_have_undeclared_an_outlaw", target.getName(), town.getName())); - if (admin) - TownyMessaging.sendMsg(sender, Translatable.of("msg_you_have_undeclared_an_outlaw", target.getName(), town.getName())); - } else { - // Must already not be an outlaw - TownyMessaging.sendMsg(sender, Translatable.of("msg_err_player_not_an_outlaw")); - return; - } + // Add the outlaw and save the town. + try { + town.addOutlaw(target); + } catch (AlreadyRegisteredException ignored) {} + town.save(); - } else { - TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_err_invalid_property", split[0])); - return; + // Send feedback messages. + if (target.isOnline()) { + TownyMessaging.sendMsg(target, Translatable.of("msg_you_have_been_declared_outlaw", town.getName())); + Location loc = target.getPlayer().getLocation(); + + // If the newly-outlawed player is within the town's borders and is meant to be teleported away, + // send them using the outlaw teleport warmup time, potentially giving them the chance to escape + // the borders. + if (TownySettings.areNewOutlawsTeleportedAway() + && !TownyAPI.getInstance().isWilderness(loc) + && TownyAPI.getInstance().getTown(loc) == town) { + + OutlawTeleportEvent event = new OutlawTeleportEvent(target, town, loc); + if (BukkitTools.isEventCancelled(event)) + return; + + if (TownySettings.getOutlawTeleportWarmup() > 0) + TownyMessaging.sendMsg(target, Translatable.of("msg_outlaw_kick_cooldown", town, TimeMgmt.formatCountdownTime(TownySettings.getOutlawTeleportWarmup()))); + + plugin.getScheduler().runLater(() -> { + if (TownyAPI.getInstance().getTown(loc) == town) + SpawnUtil.outlawTeleport(town, target); + }, TownySettings.getOutlawTeleportWarmup() * 20L); } + } + TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_you_have_declared_an_outlaw", target.getName(), town.getName())); + if (admin) + TownyMessaging.sendMsg(sender, Translatable.of("msg_you_have_declared_an_outlaw", target.getName(), town.getName())); + } - /* - * If we got here we have made a change Save the altered resident - * data. - */ - town.save(); + private static void parseTownOutlawRemoveCommand(CommandSender sender, boolean admin, Town town, Resident target) throws TownyException { + if (!town.hasOutlaw(target)) + throw new TownyException(Translatable.of("msg_err_player_not_an_outlaw")); - } + // Call cancellable event. + BukkitTools.ifCancelledThenThrow(new TownOutlawRemoveEvent(sender, target, town)); + town.removeOutlaw(target); + town.save(); + + // Send feedback messages. + if (target.isOnline()) + TownyMessaging.sendMsg(target, Translatable.of("msg_you_have_been_undeclared_outlaw", town.getName())); + TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_you_have_undeclared_an_outlaw", target.getName(), town.getName())); + if (admin) + TownyMessaging.sendMsg(sender, Translatable.of("msg_you_have_undeclared_an_outlaw", target.getName(), town.getName())); } private void parseTownWithdrawCommand(final Player player, String[] split) throws NoPermissionException {