From f977557a9cb2c82ee6f32595cefd12a97b58f511 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Thu, 4 Jan 2024 09:41:57 -0600 Subject: [PATCH 01/74] - Add option to prevent players depositing/withdrawing in their homeblocks when they have a bank plot available (all while deposit/withdraw is restricted to bank plots.) - Closes #7162. - New Config Option: bank.do_homeblocks_not_work_when_a_town_has_bank_plots - Default: false - If true, towns which have one or more bank plots will no longer be able to use their homeblock for withdraw/depositing. - Requires the above is_banking_limited_to_bank_plots to be true as well. --- .../bukkit/config/ConfigNodes.java | 6 ++++++ .../bukkit/towny/TownySettings.java | 4 ++++ .../bukkit/towny/utils/MoneyUtil.java | 19 +++++++++++++------ Towny/src/main/resources/ChangeLog.txt | 8 +++++++- 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/config/ConfigNodes.java b/Towny/src/main/java/com/palmergames/bukkit/config/ConfigNodes.java index 2ee5f6a316..a5a5350c85 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/config/ConfigNodes.java +++ b/Towny/src/main/java/com/palmergames/bukkit/config/ConfigNodes.java @@ -3025,6 +3025,12 @@ public enum ConfigNodes { "", "# If true players will only be able to use /t deposit, /t withdraw, /n deposit & /n withdraw while inside bank plots belonging to the town or nation capital respectively.", "# Home plots will also allow deposit and withdraw commands."), + BANK_BANK_PLOTS_STOP_HOME_BLOCK_BEING_USED( + "bank.do_homeblocks_not_work_when_a_town_has_bank_plots", + "false", + "", + "# If true, towns which have one or more bank plots will no longer be able to use their homeblock for withdraw/depositing.", + "# Requires the above is_banking_limited_to_bank_plots to be true as well."), TOWN_RUINING_HEADER("town_ruining", "", "", "", "############################################################", diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/TownySettings.java b/Towny/src/main/java/com/palmergames/bukkit/towny/TownySettings.java index bb0166424b..dbb6e0d52d 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/TownySettings.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/TownySettings.java @@ -3053,6 +3053,10 @@ public static boolean isBankActionLimitedToBankPlots() { return getBoolean(ConfigNodes.BANK_IS_LIMTED_TO_BANK_PLOTS); } + public static boolean doHomeblocksNoLongerWorkWhenATownHasBankPlots() { + return getBoolean(ConfigNodes.BANK_BANK_PLOTS_STOP_HOME_BLOCK_BEING_USED); + } + public static void SetNationBankAllowWithdrawls(boolean newSetting) { setProperty(ConfigNodes.ECO_BANK_NATION_ALLOW_WITHDRAWALS.getRoot(), newSetting); diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/MoneyUtil.java b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/MoneyUtil.java index 8df321bff8..fea5cb6404 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/MoneyUtil.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/MoneyUtil.java @@ -22,6 +22,7 @@ import com.palmergames.bukkit.towny.object.Town; import com.palmergames.bukkit.towny.object.TownBlock; import com.palmergames.bukkit.towny.object.TownBlockType; +import com.palmergames.bukkit.towny.object.TownBlockTypeCache.CacheType; import com.palmergames.bukkit.towny.object.Transaction; import com.palmergames.bukkit.towny.object.TransactionType; import com.palmergames.bukkit.util.BukkitTools; @@ -177,7 +178,7 @@ private static void commonTests(int amount, Resident resident, Town town, Locati throw new TownyException(Translatable.of("msg_err_deposit_capped", bankcap)); } - if (TownySettings.isBankActionLimitedToBankPlots() && isNotInBankPlot(town, loc)) + if (TownySettings.isBankActionLimitedToBankPlots() && !isInTownsBankPlotOrAllowedHomeBlock(town, loc)) throw new TownyException(Translatable.of("msg_err_unable_to_use_bank_outside_bank_plot")); if (TownySettings.isBankActionDisallowedOutsideTown() && isNotInOwnTown(town, loc)) { @@ -197,15 +198,21 @@ private static void commonTests(int amount, Resident resident, Town town, Locati } - private static boolean isNotInBankPlot(Town town, Location loc) { + private static boolean isInTownsBankPlotOrAllowedHomeBlock(Town town, Location loc) { if (isNotInOwnTown(town, loc)) - return true; - + return false; + TownBlock tb = TownyAPI.getInstance().getTownBlock(loc); - if (!tb.getType().equals(TownBlockType.BANK) && !tb.isHomeBlock()) + // TownBlock is a bank, we're good. + if (tb.getType().equals(TownBlockType.BANK)) return true; - return false; + // The config doesn't allow towns to use their homeblock after they have one or more bank plots. + if (TownySettings.doHomeblocksNoLongerWorkWhenATownHasBankPlots() && town.getTownBlockTypeCache().getNumTownBlocks(TownBlockType.BANK, CacheType.ALL) > 0) + return false; + + // The config does allow towns to use their homeblocks, or the town has no bank plots. + return tb.isHomeBlock(); } private static boolean isNotInOwnTown(Town town, Location loc) { diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index d1bd93c3ab..24e35b35d8 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9368,4 +9368,10 @@ v0.92.0.11: - Fix two nation command tab complete exceptions, courtesy of Warrior with PR #7158. - Make plot groups extend townyobject, courtesy of Warrior with PR #7141. - Closes #6092. - - Bump org.apache.logging.log4j:log4j-core from 2.22.0 to 2.22.1. \ No newline at end of file + - Bump org.apache.logging.log4j:log4j-core from 2.22.0 to 2.22.1. + - Add option to prevent players depositing/withdrawing in their homeblocks when they have a bank plot available (all while deposit/withdraw is restricted to bank plots.) + - Closes #7162. + - New Config Option: bank.do_homeblocks_not_work_when_a_town_has_bank_plots + - Default: false + - If true, towns which have one or more bank plots will no longer be able to use their homeblock for withdraw/depositing. + - Requires the above is_banking_limited_to_bank_plots to be true as well. \ No newline at end of file From 501beea47d2bfd7ac04cc73729621d6f019eedbf Mon Sep 17 00:00:00 2001 From: LlmDl Date: Thu, 4 Jan 2024 09:55:28 -0600 Subject: [PATCH 02/74] Improve last commit's error messaging to match the new rule. --- .../palmergames/bukkit/towny/utils/MoneyUtil.java | 15 ++++++++------- Towny/src/main/resources/lang/en-US.yml | 6 +++++- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/MoneyUtil.java b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/MoneyUtil.java index fea5cb6404..c26bc4aaa9 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/MoneyUtil.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/MoneyUtil.java @@ -178,8 +178,8 @@ private static void commonTests(int amount, Resident resident, Town town, Locati throw new TownyException(Translatable.of("msg_err_deposit_capped", bankcap)); } - if (TownySettings.isBankActionLimitedToBankPlots() && !isInTownsBankPlotOrAllowedHomeBlock(town, loc)) - throw new TownyException(Translatable.of("msg_err_unable_to_use_bank_outside_bank_plot")); + if (TownySettings.isBankActionLimitedToBankPlots()) + testBankPlotRules(town, loc); if (TownySettings.isBankActionDisallowedOutsideTown() && isNotInOwnTown(town, loc)) { if (nation) @@ -198,21 +198,22 @@ private static void commonTests(int amount, Resident resident, Town town, Locati } - private static boolean isInTownsBankPlotOrAllowedHomeBlock(Town town, Location loc) { + private static void testBankPlotRules(Town town, Location loc) throws TownyException { if (isNotInOwnTown(town, loc)) - return false; + throw new TownyException(Translatable.of("msg_err_unable_to_command_outside_of_town")); TownBlock tb = TownyAPI.getInstance().getTownBlock(loc); // TownBlock is a bank, we're good. if (tb.getType().equals(TownBlockType.BANK)) - return true; + return; // The config doesn't allow towns to use their homeblock after they have one or more bank plots. if (TownySettings.doHomeblocksNoLongerWorkWhenATownHasBankPlots() && town.getTownBlockTypeCache().getNumTownBlocks(TownBlockType.BANK, CacheType.ALL) > 0) - return false; + throw new TownyException(Translatable.of("msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock")); // The config does allow towns to use their homeblocks, or the town has no bank plots. - return tb.isHomeBlock(); + if (!tb.isHomeBlock()) + throw new TownyException(Translatable.of("msg_err_unable_to_use_bank_outside_bank_plot")); } private static boolean isNotInOwnTown(Town town, Location loc) { diff --git a/Towny/src/main/resources/lang/en-US.yml b/Towny/src/main/resources/lang/en-US.yml index 2f59e42e55..e8eb21fc11 100644 --- a/Towny/src/main/resources/lang/en-US.yml +++ b/Towny/src/main/resources/lang/en-US.yml @@ -2404,4 +2404,8 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." -msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." \ No newline at end of file +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." + +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' + +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' \ No newline at end of file From b5e3563b54629e1c9c2e5e54495071779f72077a Mon Sep 17 00:00:00 2001 From: LlmDl Date: Thu, 4 Jan 2024 10:18:08 -0600 Subject: [PATCH 03/74] - Fix plots not losing their trusted residents when the owner of the plot changes. - Closes #7161. Replaces unneeded TownBlock.setResident(null) with TownBlock.removeResident(). --- .../palmergames/bukkit/towny/command/TownyAdminCommand.java | 2 +- .../java/com/palmergames/bukkit/towny/object/TownBlock.java | 6 ++++-- .../com/palmergames/bukkit/towny/tasks/DailyTimerTask.java | 2 +- .../java/com/palmergames/bukkit/towny/tasks/PlotClaim.java | 2 +- .../com/palmergames/bukkit/towny/utils/TownRuinUtil.java | 2 +- Towny/src/main/resources/ChangeLog.txt | 4 +++- 6 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownyAdminCommand.java b/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownyAdminCommand.java index e5204550ac..1e5f3c565c 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownyAdminCommand.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownyAdminCommand.java @@ -2110,7 +2110,7 @@ private void adminSetPlot(CommandSender sender, String[] split) throws TownyExce TownBlock tb = TownyAPI.getInstance().getTownBlock(player); if (tb != null) { Town newTown = getTownOrThrow(split[1]); - tb.setResident(null); + tb.removeResident(); tb.setTown(newTown); tb.setType(TownBlockType.RESIDENTIAL); tb.setName(""); diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/object/TownBlock.java b/Towny/src/main/java/com/palmergames/bukkit/towny/object/TownBlock.java index 7ab18488ee..8683a8fac0 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/object/TownBlock.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/object/TownBlock.java @@ -23,6 +23,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -164,6 +165,7 @@ public boolean setResident(@Nullable Resident resident, boolean callEvent) { this.resident.removeTownBlock(this); unclaim = true; this.town.getTownBlockTypeCache().removeTownBlockOfTypeResidentOwned(this); + new ArrayList<>(this.getTrustedResidents()).forEach(this::removeTrustedResident); } this.resident = resident; if (resident != null && !resident.hasTownBlock(this)) { @@ -497,7 +499,7 @@ public int hashCode() { public void clear() { setTown(null); - setResident(null); + removeResident(); } @Override @@ -621,7 +623,7 @@ public TownBlockData getData() { } public void evictOwnerFromTownBlock() { - this.setResident(null); + this.removeResident(); this.setPlotPrice(-1); this.setType(getType()); this.save(); diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/DailyTimerTask.java b/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/DailyTimerTask.java index 0b37a1b0be..aa82354091 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/DailyTimerTask.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/DailyTimerTask.java @@ -565,7 +565,7 @@ private boolean collectPlotTaxFromResident(double tax, Resident resident, Town t } // Could not pay the plot tax, remove the resident from the plot. - townBlock.setResident(null); + townBlock.removeResident(); // Set the plot price. if (TownySettings.doesPlotTaxNonPaymentSetPlotForSale()) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/PlotClaim.java b/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/PlotClaim.java index e8224749e5..1bf7a621ad 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/PlotClaim.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/PlotClaim.java @@ -356,7 +356,7 @@ private boolean residentUnclaim(WorldCoord worldCoord) throws TownyException { try { TownBlock townBlock = worldCoord.getTownBlock(); - townBlock.setResident(null); + townBlock.removeResident(); townBlock.setPlotPrice(townBlock.getTown().getPlotTypePrice(townBlock.getType())); // Set the plot permissions to mirror the towns. diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/TownRuinUtil.java b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/TownRuinUtil.java index 506d7a9a19..5cb5815111 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/TownRuinUtil.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/TownRuinUtil.java @@ -103,7 +103,7 @@ public static void putTownIntoRuinedState(Town town) { //Return town blocks to the basic, unowned, type for(TownBlock townBlock: town.getTownBlocks()) { if (townBlock.hasResident()) - townBlock.setResident(null); // Removes any personal ownership. + townBlock.removeResident(); // Removes any personal ownership. townBlock.setType(TownBlockType.RESIDENTIAL); // Sets the townblock's perm line to the Town's perm line set above. townBlock.setPlotPrice(-1); // Makes the plot not for sale. townBlock.removePlotObjectGroup(); // Removes plotgroup if it were present. diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index 24e35b35d8..d974e4cf77 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9374,4 +9374,6 @@ v0.92.0.11: - New Config Option: bank.do_homeblocks_not_work_when_a_town_has_bank_plots - Default: false - If true, towns which have one or more bank plots will no longer be able to use their homeblock for withdraw/depositing. - - Requires the above is_banking_limited_to_bank_plots to be true as well. \ No newline at end of file + - Requires the above is_banking_limited_to_bank_plots to be true as well. + - Fix plots not losing their trusted residents when the owner of the plot changes. + - Closes #7161. \ No newline at end of file From 01c63d1d2b25a2b31036dc36cebdf40eb98a7610 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Thu, 4 Jan 2024 10:19:09 -0600 Subject: [PATCH 04/74] New Crowdin updates (#7160) * Update source file en-US.yml * New translations en-us.yml (Chinese Simplified) * New translations en-us.yml (German) * New translations en-us.yml (Romanian) * New translations en-us.yml (French) * New translations en-us.yml (Spanish) * New translations en-us.yml (Bulgarian) * New translations en-us.yml (Czech) * New translations en-us.yml (Danish) * New translations en-us.yml (Hebrew) * New translations en-us.yml (Italian) * New translations en-us.yml (Japanese) * New translations en-us.yml (Korean) * New translations en-us.yml (Lithuanian) * New translations en-us.yml (Dutch) * New translations en-us.yml (Norwegian) * New translations en-us.yml (Polish) * New translations en-us.yml (Portuguese) * New translations en-us.yml (Russian) * New translations en-us.yml (Albanian) * New translations en-us.yml (Swedish) * New translations en-us.yml (Turkish) * New translations en-us.yml (Ukrainian) * New translations en-us.yml (Chinese Traditional) * New translations en-us.yml (Vietnamese) * New translations en-us.yml (Portuguese, Brazilian) * New translations en-us.yml (Indonesian) * New translations en-us.yml (Spanish, Argentina) * New translations en-us.yml (Spanish, Chile) * New translations en-us.yml (Spanish, Mexico) * New translations en-us.yml (Spanish, Uruguay) * New translations en-us.yml (Spanish, Venezuela) * New translations en-us.yml (Spanish, Ecuador) * New translations en-us.yml (Thai) * New translations en-us.yml (Azerbaijani) * New translations en-us.yml (English, United Kingdom) * New translations en-us.yml (Tagalog) * New translations en-us.yml (Pirate English) * New translations en-us.yml (Serbian (Latin)) * New translations en-us.yml (English (upside down)) * New translations en-us.yml (LOLCAT) * New translations en-us.yml (Classical Chinese) * Update source file en-US.yml --- Towny/src/main/resources/lang/az-AZ.yml | 1 + Towny/src/main/resources/lang/bg-BG.yml | 1 + Towny/src/main/resources/lang/cs-CZ.yml | 1 + Towny/src/main/resources/lang/da-DK.yml | 1 + Towny/src/main/resources/lang/de-DE.yml | 1 + Towny/src/main/resources/lang/en-GB.yml | 1 + Towny/src/main/resources/lang/en-PT.yml | 1 + Towny/src/main/resources/lang/en-UD.yml | 1 + Towny/src/main/resources/lang/es-AR.yml | 1 + Towny/src/main/resources/lang/es-CL.yml | 1 + Towny/src/main/resources/lang/es-EC.yml | 1 + Towny/src/main/resources/lang/es-ES.yml | 1 + Towny/src/main/resources/lang/es-MX.yml | 1 + Towny/src/main/resources/lang/es-UY.yml | 1 + Towny/src/main/resources/lang/es-VE.yml | 1 + Towny/src/main/resources/lang/fr-FR.yml | 1 + Towny/src/main/resources/lang/he-IL.yml | 1 + Towny/src/main/resources/lang/id-ID.yml | 1 + Towny/src/main/resources/lang/it-IT.yml | 1 + Towny/src/main/resources/lang/ja-JP.yml | 1 + Towny/src/main/resources/lang/ko-KR.yml | 1 + Towny/src/main/resources/lang/lol-US.yml | 1 + Towny/src/main/resources/lang/lt-LT.yml | 1 + Towny/src/main/resources/lang/lzh.yml | 1 + Towny/src/main/resources/lang/nl-NL.yml | 1 + Towny/src/main/resources/lang/no-NO.yml | 1 + Towny/src/main/resources/lang/pl-PL.yml | 1 + Towny/src/main/resources/lang/pt-BR.yml | 1 + Towny/src/main/resources/lang/pt-PT.yml | 1 + Towny/src/main/resources/lang/ro-RO.yml | 1 + Towny/src/main/resources/lang/ru-RU.yml | 1 + Towny/src/main/resources/lang/sq-AL.yml | 1 + Towny/src/main/resources/lang/sr-CS.yml | 1 + Towny/src/main/resources/lang/sv-SE.yml | 1 + Towny/src/main/resources/lang/th-TH.yml | 1 + Towny/src/main/resources/lang/tl-PH.yml | 1 + Towny/src/main/resources/lang/tr-TR.yml | 1 + Towny/src/main/resources/lang/uk-UA.yml | 1 + Towny/src/main/resources/lang/vi-VN.yml | 1 + Towny/src/main/resources/lang/zh-CN.yml | 1 + Towny/src/main/resources/lang/zh-TW.yml | 1 + 41 files changed, 41 insertions(+) diff --git a/Towny/src/main/resources/lang/az-AZ.yml b/Towny/src/main/resources/lang/az-AZ.yml index 63c4a2ba92..d18e098976 100644 --- a/Towny/src/main/resources/lang/az-AZ.yml +++ b/Towny/src/main/resources/lang/az-AZ.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/bg-BG.yml b/Towny/src/main/resources/lang/bg-BG.yml index 4dcc290d34..a91d16d837 100644 --- a/Towny/src/main/resources/lang/bg-BG.yml +++ b/Towny/src/main/resources/lang/bg-BG.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/cs-CZ.yml b/Towny/src/main/resources/lang/cs-CZ.yml index 2f6f0b556c..d52d1247c5 100644 --- a/Towny/src/main/resources/lang/cs-CZ.yml +++ b/Towny/src/main/resources/lang/cs-CZ.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/da-DK.yml b/Towny/src/main/resources/lang/da-DK.yml index f372ba39da..5d915e6984 100644 --- a/Towny/src/main/resources/lang/da-DK.yml +++ b/Towny/src/main/resources/lang/da-DK.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/de-DE.yml b/Towny/src/main/resources/lang/de-DE.yml index 4242c5bb08..1cb860f42d 100644 --- a/Towny/src/main/resources/lang/de-DE.yml +++ b/Towny/src/main/resources/lang/de-DE.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/en-GB.yml b/Towny/src/main/resources/lang/en-GB.yml index 9dcfa29d4b..4144adea89 100644 --- a/Towny/src/main/resources/lang/en-GB.yml +++ b/Towny/src/main/resources/lang/en-GB.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/en-PT.yml b/Towny/src/main/resources/lang/en-PT.yml index 63eaf847a3..1fa6447dd0 100644 --- a/Towny/src/main/resources/lang/en-PT.yml +++ b/Towny/src/main/resources/lang/en-PT.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/en-UD.yml b/Towny/src/main/resources/lang/en-UD.yml index a24491b35d..1085a4783b 100644 --- a/Towny/src/main/resources/lang/en-UD.yml +++ b/Towny/src/main/resources/lang/en-UD.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/es-AR.yml b/Towny/src/main/resources/lang/es-AR.yml index 7159cf4bb1..2defc09025 100644 --- a/Towny/src/main/resources/lang/es-AR.yml +++ b/Towny/src/main/resources/lang/es-AR.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/es-CL.yml b/Towny/src/main/resources/lang/es-CL.yml index 96e0842a02..ff9360fea6 100644 --- a/Towny/src/main/resources/lang/es-CL.yml +++ b/Towny/src/main/resources/lang/es-CL.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/es-EC.yml b/Towny/src/main/resources/lang/es-EC.yml index abc682c29d..d1b9589900 100644 --- a/Towny/src/main/resources/lang/es-EC.yml +++ b/Towny/src/main/resources/lang/es-EC.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/es-ES.yml b/Towny/src/main/resources/lang/es-ES.yml index 142104f458..8e5f724efe 100644 --- a/Towny/src/main/resources/lang/es-ES.yml +++ b/Towny/src/main/resources/lang/es-ES.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/es-MX.yml b/Towny/src/main/resources/lang/es-MX.yml index 4bd2bd68e9..7762ac4089 100644 --- a/Towny/src/main/resources/lang/es-MX.yml +++ b/Towny/src/main/resources/lang/es-MX.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/es-UY.yml b/Towny/src/main/resources/lang/es-UY.yml index abc682c29d..d1b9589900 100644 --- a/Towny/src/main/resources/lang/es-UY.yml +++ b/Towny/src/main/resources/lang/es-UY.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/es-VE.yml b/Towny/src/main/resources/lang/es-VE.yml index abc682c29d..d1b9589900 100644 --- a/Towny/src/main/resources/lang/es-VE.yml +++ b/Towny/src/main/resources/lang/es-VE.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/fr-FR.yml b/Towny/src/main/resources/lang/fr-FR.yml index 7eaacd6dac..16d0cea1ef 100644 --- a/Towny/src/main/resources/lang/fr-FR.yml +++ b/Towny/src/main/resources/lang/fr-FR.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/he-IL.yml b/Towny/src/main/resources/lang/he-IL.yml index 170bb0261b..620126e4be 100644 --- a/Towny/src/main/resources/lang/he-IL.yml +++ b/Towny/src/main/resources/lang/he-IL.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/id-ID.yml b/Towny/src/main/resources/lang/id-ID.yml index 4e46b43cb8..87cec3dff5 100644 --- a/Towny/src/main/resources/lang/id-ID.yml +++ b/Towny/src/main/resources/lang/id-ID.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/it-IT.yml b/Towny/src/main/resources/lang/it-IT.yml index a2362710ee..1714c0b5e3 100644 --- a/Towny/src/main/resources/lang/it-IT.yml +++ b/Towny/src/main/resources/lang/it-IT.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/ja-JP.yml b/Towny/src/main/resources/lang/ja-JP.yml index 5f49528b97..3ab19bd980 100644 --- a/Towny/src/main/resources/lang/ja-JP.yml +++ b/Towny/src/main/resources/lang/ja-JP.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/ko-KR.yml b/Towny/src/main/resources/lang/ko-KR.yml index c90f2deefe..5cc4267694 100644 --- a/Towny/src/main/resources/lang/ko-KR.yml +++ b/Towny/src/main/resources/lang/ko-KR.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/lol-US.yml b/Towny/src/main/resources/lang/lol-US.yml index ad3972de7b..d3c60be02a 100644 --- a/Towny/src/main/resources/lang/lol-US.yml +++ b/Towny/src/main/resources/lang/lol-US.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/lt-LT.yml b/Towny/src/main/resources/lang/lt-LT.yml index 432d9bc728..c577ee6dce 100644 --- a/Towny/src/main/resources/lang/lt-LT.yml +++ b/Towny/src/main/resources/lang/lt-LT.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/lzh.yml b/Towny/src/main/resources/lang/lzh.yml index 06414b25d2..21b4db2f6b 100644 --- a/Towny/src/main/resources/lang/lzh.yml +++ b/Towny/src/main/resources/lang/lzh.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/nl-NL.yml b/Towny/src/main/resources/lang/nl-NL.yml index b7f5ff846b..8bb865fdc8 100644 --- a/Towny/src/main/resources/lang/nl-NL.yml +++ b/Towny/src/main/resources/lang/nl-NL.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/no-NO.yml b/Towny/src/main/resources/lang/no-NO.yml index 757a71ad58..5ad8b207fc 100644 --- a/Towny/src/main/resources/lang/no-NO.yml +++ b/Towny/src/main/resources/lang/no-NO.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/pl-PL.yml b/Towny/src/main/resources/lang/pl-PL.yml index 953b3e14c1..c19b8aec9b 100644 --- a/Towny/src/main/resources/lang/pl-PL.yml +++ b/Towny/src/main/resources/lang/pl-PL.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/pt-BR.yml b/Towny/src/main/resources/lang/pt-BR.yml index 2df9556112..d3b7a6a8f9 100644 --- a/Towny/src/main/resources/lang/pt-BR.yml +++ b/Towny/src/main/resources/lang/pt-BR.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/pt-PT.yml b/Towny/src/main/resources/lang/pt-PT.yml index a2e51511db..0fa12d1dd9 100644 --- a/Towny/src/main/resources/lang/pt-PT.yml +++ b/Towny/src/main/resources/lang/pt-PT.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/ro-RO.yml b/Towny/src/main/resources/lang/ro-RO.yml index 4ec56d40c2..0a1e458186 100644 --- a/Towny/src/main/resources/lang/ro-RO.yml +++ b/Towny/src/main/resources/lang/ro-RO.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/ru-RU.yml b/Towny/src/main/resources/lang/ru-RU.yml index ff607f12d6..b056ebd0fc 100644 --- a/Towny/src/main/resources/lang/ru-RU.yml +++ b/Towny/src/main/resources/lang/ru-RU.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/sq-AL.yml b/Towny/src/main/resources/lang/sq-AL.yml index 3e047c1e72..6acc42238b 100644 --- a/Towny/src/main/resources/lang/sq-AL.yml +++ b/Towny/src/main/resources/lang/sq-AL.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/sr-CS.yml b/Towny/src/main/resources/lang/sr-CS.yml index 4b3fafc87a..a252df851e 100644 --- a/Towny/src/main/resources/lang/sr-CS.yml +++ b/Towny/src/main/resources/lang/sr-CS.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/sv-SE.yml b/Towny/src/main/resources/lang/sv-SE.yml index c33c58434b..df9c820db0 100644 --- a/Towny/src/main/resources/lang/sv-SE.yml +++ b/Towny/src/main/resources/lang/sv-SE.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/th-TH.yml b/Towny/src/main/resources/lang/th-TH.yml index 17847d930a..b62a6d8b4e 100644 --- a/Towny/src/main/resources/lang/th-TH.yml +++ b/Towny/src/main/resources/lang/th-TH.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/tl-PH.yml b/Towny/src/main/resources/lang/tl-PH.yml index c30cdf2652..090e08f0a6 100644 --- a/Towny/src/main/resources/lang/tl-PH.yml +++ b/Towny/src/main/resources/lang/tl-PH.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/tr-TR.yml b/Towny/src/main/resources/lang/tr-TR.yml index 5104d40308..c362db6039 100644 --- a/Towny/src/main/resources/lang/tr-TR.yml +++ b/Towny/src/main/resources/lang/tr-TR.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/uk-UA.yml b/Towny/src/main/resources/lang/uk-UA.yml index c32c7ccf43..e96ab5f2a3 100644 --- a/Towny/src/main/resources/lang/uk-UA.yml +++ b/Towny/src/main/resources/lang/uk-UA.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/vi-VN.yml b/Towny/src/main/resources/lang/vi-VN.yml index 8cbe987fcc..a41434a96d 100644 --- a/Towny/src/main/resources/lang/vi-VN.yml +++ b/Towny/src/main/resources/lang/vi-VN.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/zh-CN.yml b/Towny/src/main/resources/lang/zh-CN.yml index 9bb4754721..91592b43ea 100644 --- a/Towny/src/main/resources/lang/zh-CN.yml +++ b/Towny/src/main/resources/lang/zh-CN.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." diff --git a/Towny/src/main/resources/lang/zh-TW.yml b/Towny/src/main/resources/lang/zh-TW.yml index 915d3542ad..7b8f68d9b2 100644 --- a/Towny/src/main/resources/lang/zh-TW.yml +++ b/Towny/src/main/resources/lang/zh-TW.yml @@ -2079,3 +2079,4 @@ msg_err_cannot_nation_spawn_your_town_is_sanctioned: "Your town is sanctioned by msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The following coordinate(s) cannot be claimed because they contain too much of an unwanted biome: %s." msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." +msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." From 6e4c0f243d28f98719294684fa31e51faac3e888 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Thu, 4 Jan 2024 09:07:18 -0600 Subject: [PATCH 05/74] - Make /ta town new [townname] bypass the proximity/claiming rules. - Closes #7163. --- Towny/pom.xml | 2 +- .../bukkit/towny/command/TownCommand.java | 34 ++++++++++++++----- .../towny/command/TownyAdminCommand.java | 2 +- Towny/src/main/resources/ChangeLog.txt | 5 ++- 4 files changed, 31 insertions(+), 12 deletions(-) diff --git a/Towny/pom.xml b/Towny/pom.xml index ea31f2ac82..888e7defc9 100644 --- a/Towny/pom.xml +++ b/Towny/pom.xml @@ -13,7 +13,7 @@ towny jar - 0.100.0.18 + 0.100.0.19 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 35197e7856..62c969dbb8 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 @@ -2529,6 +2529,20 @@ private void parseTownNewCommand(final Player player, String[] split) throws NoP * @throws TownyException when a new town isn't allowed. */ public static void newTown(Player player, String name, Resident resident, boolean noCharge) throws TownyException { + newTown(player, name, resident, noCharge, false); + } + + /** + * Create a new town. Command: /town new [townname] or /ta town new [townname] + * + * @param player Player using the command. + * @param name Name of town + * @param resident The resident in charge of the town. + * @param noCharge Charging for creation - /ta town new NAME MAYOR has no charge. + * @param adminCreated true when an admin has used /ta town new [NAME]. + * @throws TownyException when a new town isn't allowed. + */ + public static void newTown(Player player, String name, Resident resident, boolean noCharge, boolean adminCreated) throws TownyException { if (TownySettings.hasTownLimit() && TownyUniverse.getInstance().getTowns().size() >= TownySettings.getTownLimit()) throw new TownyException(Translatable.of("msg_err_universe_limit")); @@ -2556,17 +2570,19 @@ public static void newTown(Player player, String name, Resident resident, boolea if (!TownyAPI.getInstance().isWilderness(spawnLocation)) throw new TownyException(Translatable.of("msg_already_claimed_1", key)); - // Check that a town isn't being formed inside of a biome that isn't allowed to be claimed. - if (TownySettings.isUnwantedBiomeClaimingEnabled() || TownySettings.isOceanClaimingBlocked()) { - List selection = Arrays.asList(WorldCoord.parseWorldCoord(spawnLocation)); - selection = AreaSelectionUtil.filterOutUnwantedBiomeWorldCoords(player, selection); - selection = AreaSelectionUtil.filterOutOceanBiomeWorldCoords(player, selection); - if (selection.isEmpty()) - throw new TownyException("msg_err_cannot_begin_town_in_this_biome"); + if (!adminCreated) { + // Check that a town isn't being formed inside of a biome that isn't allowed to be claimed. + if (TownySettings.isUnwantedBiomeClaimingEnabled() || TownySettings.isOceanClaimingBlocked()) { + List selection = Arrays.asList(WorldCoord.parseWorldCoord(spawnLocation)); + selection = AreaSelectionUtil.filterOutUnwantedBiomeWorldCoords(player, selection); + selection = AreaSelectionUtil.filterOutOceanBiomeWorldCoords(player, selection); + if (selection.isEmpty()) + throw new TownyException("msg_err_cannot_begin_town_in_this_biome"); + } + + ProximityUtil.allowTownHomeBlockOrThrow(world, key, null, true); } - ProximityUtil.allowTownHomeBlockOrThrow(world, key, null, true); - // If the town doesn't cost money to create, just make the Town. if (noCharge || !TownyEconomyHandler.isActive()) { BukkitTools.ifCancelledThenThrow(new PreNewTownEvent(player, name, spawnLocation)); diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownyAdminCommand.java b/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownyAdminCommand.java index 1e5f3c565c..5cb4777dc9 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownyAdminCommand.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownyAdminCommand.java @@ -1393,7 +1393,7 @@ private void parseAdminNewTownCommand(CommandSender sender, String[] split) thro throw new TownyException(Translatable.of("msg_player_is_not_online", split[2])); player = resident.getPlayer(); } - TownCommand.newTown(player, split[1], resident, true); + TownCommand.newTown(player, split[1], resident, true, true); } private void parseAdminTownSet(CommandSender sender, Town town, String[] split) throws TownyException { diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index d974e4cf77..ae4d2082d0 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9376,4 +9376,7 @@ v0.92.0.11: - If true, towns which have one or more bank plots will no longer be able to use their homeblock for withdraw/depositing. - Requires the above is_banking_limited_to_bank_plots to be true as well. - Fix plots not losing their trusted residents when the owner of the plot changes. - - Closes #7161. \ No newline at end of file + - Closes #7161. +0.100.0.19: + - Make /ta town new [townname] bypass the proximity/claiming rules. + - Closes #7163. \ No newline at end of file From cad326fb228fb820c633a6cf3cb4b059485440a4 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Thu, 4 Jan 2024 11:16:44 -0600 Subject: [PATCH 06/74] - Fix outsiders being charged money for plotgroups they cannot actually /plot group claim, (not embassy plots.) --- .../bukkit/towny/command/PlotCommand.java | 5 +- .../bukkit/towny/utils/AreaSelectionUtil.java | 63 +++++++++++++++---- Towny/src/main/resources/ChangeLog.txt | 3 +- 3 files changed, 56 insertions(+), 15 deletions(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/command/PlotCommand.java b/Towny/src/main/java/com/palmergames/bukkit/towny/command/PlotCommand.java index c040373a89..8e6fa86829 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/command/PlotCommand.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/command/PlotCommand.java @@ -337,8 +337,9 @@ public void parsePlotClaim(Player player, String[] args, Resident resident, Town throw new TownyException(message); } - // Filter to just plots that are for sale. - selection = AreaSelectionUtil.filterPlotsForSale(selection); + // Filter to just plots that are for sale, which can actually be bought by the + // resident, (ie: outsiders can only buy Embassy plots.) + selection = AreaSelectionUtil.filterPlotsForSale(resident, selection); // Filter out plots already owned by the player. selection = AreaSelectionUtil.filterUnownedBlocks(resident, selection); diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/AreaSelectionUtil.java b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/AreaSelectionUtil.java index a1a2114f88..59181cef98 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/AreaSelectionUtil.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/AreaSelectionUtil.java @@ -10,6 +10,7 @@ import com.palmergames.bukkit.towny.object.Town; import com.palmergames.bukkit.towny.object.TownBlock; import com.palmergames.bukkit.towny.object.TownBlockOwner; +import com.palmergames.bukkit.towny.object.TownBlockType; import com.palmergames.bukkit.towny.object.Translatable; import com.palmergames.bukkit.towny.object.WorldCoord; import com.palmergames.bukkit.util.BiomeUtil; @@ -469,29 +470,67 @@ public static HashSet getPlotGroupsFromSelection(List sel } /** - * Gather plots that are for sale only. + * Gather plots that are for sale only, using a resident to determine whether they can be bought. + * + * @param resident Resident who would be buying the plots. + * @param selection List<WorldCoord> from which to get plots that are for sale. + * @return List<WorldCoord> that are all for sale. + */ + public static List filterPlotsForSale(Resident resident, List selection) { + + List out = new ArrayList<>(); + for (WorldCoord worldCoord : selection) { + TownBlock townBlock = worldCoord.getTownBlockOrNull(); + if (townBlock == null || !residentCanBuyTownBlock(resident, townBlock)) + continue; + + // Plot Groups do not set a townblock's individual plot price. + if (townBlock.hasPlotObjectGroup()) { + out.clear(); // Remove any other plots from the selection. + out.add(worldCoord); // Put in the one plot-group-having townblock, the rest of the group will be added later. + return out; // Return the one plot-group-having townblock. + } + + out.add(worldCoord); + } + return out; + } + + /** + * Gather plots that are for sale only, currently used only for setting plots to notforsale. + * * @param selection List<WorldCoord> from which to get plots that are for sale. * @return List<WorldCoord> that are all for sale. */ public static List filterPlotsForSale(List selection) { List out = new ArrayList<>(); - for (WorldCoord worldCoord : selection) - try { - // Plot Groups do not set a townblock's individual plot price. - if (worldCoord.getTownBlock().hasPlotObjectGroup() && worldCoord.getTownBlock().getPlotObjectGroup().getPrice() != -1) { - out.clear(); // Remove any other plots from the selection. - out.add(worldCoord); // Put in the one plot-group-having townblock, the rest of the group will be added later. - return out; // Return the one plot-group-having townblock. - } + for (WorldCoord worldCoord : selection) { + TownBlock townBlock = worldCoord.getTownBlockOrNull(); + if (townBlock == null || !townBlockIsForSale(townBlock)) + continue; - if (worldCoord.getTownBlock().isForSale()) - out.add(worldCoord); - } catch (NotRegisteredException ignored) { + // Plot Groups do not set a townblock's individual plot price. + if (townBlock.hasPlotObjectGroup()) { + out.clear(); // Remove any other plots from the selection. + out.add(worldCoord); // Put in the one plot-group-having townblock, the rest of the group will be added later. + return out; // Return the one plot-group-having townblock. } + + out.add(worldCoord); + } return out; } + private static boolean residentCanBuyTownBlock(Resident resident, TownBlock townBlock) { + Town town = townBlock.getTownOrNull(); + return town != null && townBlockIsForSale(townBlock) && (town.hasResident(resident) || townBlock.getType().equals(TownBlockType.EMBASSY)); + } + + private static boolean townBlockIsForSale(TownBlock townBlock) { + return townBlock.isForSale() || (townBlock.hasPlotObjectGroup() && townBlock.getPlotObjectGroup().getPrice() != -1); + } + /** * Gather plots that are not for sale only. * @param selection List<WorldCoord> from which to get plots that are not for sale. diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index ae4d2082d0..5da5bb042f 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9379,4 +9379,5 @@ v0.92.0.11: - Closes #7161. 0.100.0.19: - Make /ta town new [townname] bypass the proximity/claiming rules. - - Closes #7163. \ No newline at end of file + - Closes #7163. + - Fix outsiders being charged money for plotgroups they cannot actually /plot group claim, (not embassy plots.) \ No newline at end of file From f122c95978e07ceab3530f1811f25872e353ac69 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Thu, 4 Jan 2024 16:02:58 -0600 Subject: [PATCH 07/74] - Fix non-standard minecarts being unprotected. --- .../src/main/java/com/palmergames/bukkit/util/EntityLists.java | 2 +- Towny/src/main/resources/ChangeLog.txt | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/util/EntityLists.java b/Towny/src/main/java/com/palmergames/bukkit/util/EntityLists.java index f8e5145c21..72206b7f83 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/util/EntityLists.java +++ b/Towny/src/main/java/com/palmergames/bukkit/util/EntityLists.java @@ -19,7 +19,7 @@ public boolean contains(@NotNull Entity entity) { return this.contains(entity.getType()); } - public static final EntityLists VEHICLES = newBuilder().startsWith("minecart").endsWith("boat").endsWith("raft").build(); + public static final EntityLists VEHICLES = newBuilder().startsWith("minecart").endsWith("minecart").endsWith("boat").endsWith("raft").build(); public static final EntityLists MOUNTABLE = newBuilder().add("horse", "strider", "pig", "donkey", "mule", "trader_llama", "camel").build(); diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index 5da5bb042f..18d7219fbb 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9380,4 +9380,5 @@ v0.92.0.11: 0.100.0.19: - Make /ta town new [townname] bypass the proximity/claiming rules. - Closes #7163. - - Fix outsiders being charged money for plotgroups they cannot actually /plot group claim, (not embassy plots.) \ No newline at end of file + - Fix outsiders being charged money for plotgroups they cannot actually /plot group claim, (not embassy plots.) + - Fix non-standard minecarts being unprotected. \ No newline at end of file From 7ed7313225dd248580ad73683a856e45e9bdaa8d Mon Sep 17 00:00:00 2001 From: LlmDl Date: Fri, 5 Jan 2024 20:11:14 -0600 Subject: [PATCH 08/74] - Hide /ta ? from the /towny ? screen when players are not admins. --- .../bukkit/towny/command/HelpMenu.java | 16 ++++++++++++++++ .../bukkit/towny/command/TownyCommand.java | 5 ++++- Towny/src/main/resources/ChangeLog.txt | 3 ++- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/command/HelpMenu.java b/Towny/src/main/java/com/palmergames/bukkit/towny/command/HelpMenu.java index 34f710ef39..831a003006 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/command/HelpMenu.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/command/HelpMenu.java @@ -14,6 +14,22 @@ public enum HelpMenu { GENERAL_HELP { + @Override + protected MenuBuilder load() { + return new MenuBuilder() + .addTitle(Translation.of("help_0")) + .add(Translatable.of("help_1")) + .add("/resident", "?", Translatable.of("help_4")) + .add("/town", "?", Translatable.of("help_5")) + .add("/nation", "?", Translatable.of("help_6")) + .add("/plot", "?", Translatable.of("help_7")) + .add("/towny", "?", Translatable.of("help_8")) + .add("/tc", "[msg]", Translatable.of("help_2")) + .add("/nc", "[msg]", Translatable.of("help_3")); + } + }, + + GENERAL_HELP_ADMIN { @Override protected MenuBuilder load() { return new MenuBuilder() diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownyCommand.java b/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownyCommand.java index 73e9b4afc4..1c0848f030 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownyCommand.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownyCommand.java @@ -140,7 +140,10 @@ else if (TownyCommandAddonAPI.hasCommand(CommandType.TOWNY, args[0])) private void parseTownyCommand(CommandSender sender, String[] split) { if (split.length == 0) { - HelpMenu.GENERAL_HELP.send(sender); + if (TownyUniverse.getInstance().getPermissionSource().isTownyAdmin(sender)) + HelpMenu.GENERAL_HELP_ADMIN.send(sender); + else + HelpMenu.GENERAL_HELP.send(sender); return; } else if (split[0].equalsIgnoreCase("?") || split[0].equalsIgnoreCase("help")) { HelpMenu.HELP.send(sender); diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index 18d7219fbb..1184097146 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9381,4 +9381,5 @@ v0.92.0.11: - Make /ta town new [townname] bypass the proximity/claiming rules. - Closes #7163. - Fix outsiders being charged money for plotgroups they cannot actually /plot group claim, (not embassy plots.) - - Fix non-standard minecarts being unprotected. \ No newline at end of file + - Fix non-standard minecarts being unprotected. + - Hide /ta ? from the /towny ? screen when players are not admins. \ No newline at end of file From 95947d473959049625b53bcf328cbb6a127fa4b2 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Sat, 6 Jan 2024 08:23:17 -0600 Subject: [PATCH 09/74] - Add /t create and /n create tab completions. --- .../com/palmergames/bukkit/towny/command/NationCommand.java | 1 + .../java/com/palmergames/bukkit/towny/command/TownCommand.java | 1 + .../main/java/com/palmergames/bukkit/util/NameValidation.java | 2 +- Towny/src/main/resources/ChangeLog.txt | 3 ++- 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/command/NationCommand.java b/Towny/src/main/java/com/palmergames/bukkit/towny/command/NationCommand.java index 399eeab32c..713fb73248 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/command/NationCommand.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/command/NationCommand.java @@ -110,6 +110,7 @@ public class NationCommand extends BaseCommand implements CommandExecutor { "withdraw", "deposit", "new", + "create", "add", "kick", "delete", 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 62c969dbb8..322c0f08a4 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 @@ -163,6 +163,7 @@ public class TownCommand extends BaseCommand implements CommandExecutor { "list", "online", "new", + "create", "plots", "add", "kick", diff --git a/Towny/src/main/java/com/palmergames/bukkit/util/NameValidation.java b/Towny/src/main/java/com/palmergames/bukkit/util/NameValidation.java index 8e90a68361..b9921be9cd 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/util/NameValidation.java +++ b/Towny/src/main/java/com/palmergames/bukkit/util/NameValidation.java @@ -29,7 +29,7 @@ public class NameValidation { "outlawlist","deposit","outlaw","outpost","ranklist","rank","reclaim","reslist","say","set","toggle","join", "invite","buy","mayor","bankhistory","enemy","ally","townlist","allylist","enemylist","king","merge","jail", "plotgrouplist","trust","purge","leader","baltop","all","help", "spawn", "takeoverclaim", "ban", "unjail", - "trusttown","forsale","fs","notforsale","nfs","buytown","sanctiontown")); + "trusttown","forsale","fs","notforsale","nfs","buytown","sanctiontown","create")); } /** diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index 1184097146..d9f95ecbbd 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9382,4 +9382,5 @@ v0.92.0.11: - Closes #7163. - Fix outsiders being charged money for plotgroups they cannot actually /plot group claim, (not embassy plots.) - Fix non-standard minecarts being unprotected. - - Hide /ta ? from the /towny ? screen when players are not admins. \ No newline at end of file + - Hide /ta ? from the /towny ? screen when players are not admins. + - Add /t create and /n create tab completions. \ No newline at end of file From 7b4d856bfcdd206e2aeddcc08fe7be5928f5711d Mon Sep 17 00:00:00 2001 From: LlmDl Date: Sat, 6 Jan 2024 09:25:52 -0600 Subject: [PATCH 10/74] Remove unneeded deprecation warning. --- .../java/com/palmergames/bukkit/towny/object/CellBorder.java | 1 - 1 file changed, 1 deletion(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/object/CellBorder.java b/Towny/src/main/java/com/palmergames/bukkit/towny/object/CellBorder.java index f2838a4065..dc937f45af 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/object/CellBorder.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/object/CellBorder.java @@ -7,7 +7,6 @@ import java.util.Arrays; import java.util.function.Consumer; -@SuppressWarnings("deprecation") public class CellBorder extends WorldCoord { public boolean[] border; From 415f90429b656950b97a7697b18dbd2c13b46f7d Mon Sep 17 00:00:00 2001 From: LlmDl Date: Sat, 6 Jan 2024 12:54:22 -0600 Subject: [PATCH 11/74] Render border particles under leaves. Greatly improves the experience of looking for borders in forests. --- .../palmergames/bukkit/util/BlockUtil.java | 31 +++++++++++++++++++ .../com/palmergames/bukkit/util/DrawUtil.java | 2 +- .../palmergames/bukkit/util/ItemLists.java | 5 +++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/util/BlockUtil.java b/Towny/src/main/java/com/palmergames/bukkit/util/BlockUtil.java index e3ba4dea42..e2de9103d6 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/util/BlockUtil.java +++ b/Towny/src/main/java/com/palmergames/bukkit/util/BlockUtil.java @@ -4,6 +4,8 @@ import java.util.Arrays; import java.util.List; +import org.bukkit.Material; +import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.entity.Player; @@ -19,6 +21,35 @@ public class BlockUtil { public static List CARDINAL_BLOCKFACES = new ArrayList<>(Arrays.asList(BlockFace.EAST, BlockFace.NORTH, BlockFace.SOUTH, BlockFace.WEST)); + /** + * Return the highest non-leaf/non-air block's Y coordinate given an x, z in a world. + * When searching deeper than 30 blocks below the highest leaf block, this will fall back to the highest y block. + * + * @param world World to search in. + * @param x Coordinate to use. + * @param z Coordinate to use. + * @return the highest non-leaf and non-air block, hopefully. + */ + public static int getHighestNonLeafY(World world, int x, int z) { + Block block = world.getHighestBlockAt(x, z); + if (!ItemLists.LEAVES.contains(block.getType())) + return block.getY(); + + int start = block.getY() - 1; + int end = block.getY() - 30; // How tall can trees be, really. + // Search below our leaf block for a non-air, non-leaf block. + for (int y = start; y > end; y--) + if (aSuitableMaterial(world.getBlockAt(x, y, z).getType())) + return y; + + // Fallback to the highest block again. + return world.getHighestBlockYAt(x, z); + } + + private static boolean aSuitableMaterial(Material mat) { + return !mat.equals(Material.AIR) && !ItemLists.LEAVES.contains(mat); + } + /** * Are the blocks owned by the same resident or same town (if not player-owned.) * @param b1 Block 1 diff --git a/Towny/src/main/java/com/palmergames/bukkit/util/DrawUtil.java b/Towny/src/main/java/com/palmergames/bukkit/util/DrawUtil.java index 42a999ead8..c9b4a46387 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/util/DrawUtil.java +++ b/Towny/src/main/java/com/palmergames/bukkit/util/DrawUtil.java @@ -36,7 +36,7 @@ public static void runOnSurface(World world, int x1, int z1, int x2, int z2, int continue; } - int start = world.getHighestBlockYAt(x, z); + int start = BlockUtil.getHighestNonLeafY(world, x, z); int end = (start + height) < world.getMaxHeight() ? (start + height - 1) : world.getMaxHeight(); for (int y = start; y <= end; y++) { locationConsumer.accept(new Location(world, x, y, z)); diff --git a/Towny/src/main/java/com/palmergames/bukkit/util/ItemLists.java b/Towny/src/main/java/com/palmergames/bukkit/util/ItemLists.java index 3e64e0ff8f..943235973a 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/util/ItemLists.java +++ b/Towny/src/main/java/com/palmergames/bukkit/util/ItemLists.java @@ -76,6 +76,11 @@ public boolean contains(@NotNull ItemStack itemStack) { */ public static final ItemLists TREES = newBuilder().withTag(Tag.REGISTRY_BLOCKS, minecraft("logs")).withTag(Tag.REGISTRY_BLOCKS, minecraft("leaves")).endsWith("_WOOD").endsWith("_HYPHAE").notStartsWith("STRIPPED_").endsWith("_LEAVES").endsWith("_LOG").add("CRIMSON_STEM", "WARPED_STEM").add("BAMBOO_BLOCK").build(); + /** + * List of Leaves. + */ + public static final ItemLists LEAVES = newBuilder().withTag(Tag.REGISTRY_BLOCKS, minecraft("leaves")).endsWith("_LEAVES").build(); + /** * List of Beds. */ From 90f895b2e8a18854ef35c5c8bebfd4895e04f15f Mon Sep 17 00:00:00 2001 From: LlmDl Date: Sat, 6 Jan 2024 19:21:16 -0600 Subject: [PATCH 12/74] - Render border particles under leaves. --- Towny/src/main/resources/ChangeLog.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index d9f95ecbbd..06be65d58e 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9383,4 +9383,5 @@ v0.92.0.11: - Fix outsiders being charged money for plotgroups they cannot actually /plot group claim, (not embassy plots.) - Fix non-standard minecarts being unprotected. - Hide /ta ? from the /towny ? screen when players are not admins. - - Add /t create and /n create tab completions. \ No newline at end of file + - Add /t create and /n create tab completions. + - Render border particles under leaves. \ No newline at end of file From 1e3ed438899f9a8cd8b4149478f2aff1a1f4565f Mon Sep 17 00:00:00 2001 From: LlmDl Date: Sat, 6 Jan 2024 19:23:19 -0600 Subject: [PATCH 13/74] - Fix PlayerChangePlotEvent reactions running too early. - /res toggle townclaim mode and the ChunkNotifications that follow. --- .../towny/listeners/TownyCustomListener.java | 36 +++++++++++-------- Towny/src/main/resources/ChangeLog.txt | 4 ++- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyCustomListener.java b/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyCustomListener.java index 82efd50bb6..19677d686d 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyCustomListener.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyCustomListener.java @@ -71,24 +71,30 @@ public void onPlayerChangePlotEvent(PlayerChangePlotEvent event) { if (resident == null) return; - try { - if (resident.hasMode("townclaim")) - TownCommand.parseTownClaimCommand(player, new String[] {}); - if (resident.hasMode("townunclaim")) - TownCommand.parseTownUnclaimCommand(player, new String[] {}); - if (resident.hasMode("plotgroup") && resident.hasPlotGroupName()) - Towny.getPlugin().getScheduler().runLater(player, () -> Bukkit.dispatchCommand(player, "plot group add " + resident.getPlotGroupName()), 1l); - } catch (TownyException e) { - TownyMessaging.sendErrorMsg(player, e.getMessage(player)); - } - if (resident.hasMode("map")) - TownyCommand.showMap(player); - if (resident.hasMode("plotborder") || resident.hasMode("constantplotborder")) - BorderUtil.getPlotBorder(to).runBorderedOnSurface(1, 2, DrawSmokeTaskFactory.showToPlayer(player, to)); + // Run the following with a one tick delay, so that everything has a chance to take in the player's position. + plugin.getScheduler().runLater(() -> { + try { + if (resident.hasMode("townclaim")) + TownCommand.parseTownClaimCommand(player, new String[] {}); + if (resident.hasMode("townunclaim")) + TownCommand.parseTownUnclaimCommand(player, new String[] {}); + if (resident.hasMode("plotgroup") && resident.hasPlotGroupName()) + Towny.getPlugin().getScheduler().runLater(player, () -> Bukkit.dispatchCommand(player, "plot group add " + resident.getPlotGroupName()), 1l); + } catch (TownyException e) { + TownyMessaging.sendErrorMsg(player, e.getMessage(player)); + } + if (resident.hasMode("map")) + TownyCommand.showMap(player); + + if (resident.hasMode("plotborder") || resident.hasMode("constantplotborder")) + BorderUtil.getPlotBorder(to).runBorderedOnSurface(1, 2, DrawSmokeTaskFactory.showToPlayer(player, to)); + + }, 1L); + // Run the following with a two tick delay, so that newly claimed land will appear correctly. // Check if player has entered a new town/wilderness if (event.isShowingPlotNotifications()) - ChunkNotificationUtil.showChunkNotification(player, resident, to, from); + plugin.getScheduler().runLater(() -> ChunkNotificationUtil.showChunkNotification(player, resident, to, from), 2L); } @EventHandler(priority = EventPriority.NORMAL) diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index 06be65d58e..f711df29c2 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9384,4 +9384,6 @@ v0.92.0.11: - Fix non-standard minecarts being unprotected. - Hide /ta ? from the /towny ? screen when players are not admins. - Add /t create and /n create tab completions. - - Render border particles under leaves. \ No newline at end of file + - Render border particles under leaves. + - Fix PlayerChangePlotEvent reactions running too early. + - /res toggle townclaim mode and the ChunkNotifications that follow. \ No newline at end of file From 4bdcee5821f9d4c0b0f164d48baa31a502a5a4e8 Mon Sep 17 00:00:00 2001 From: 3 <49851457+Fruitloopins@users.noreply.github.com> Date: Sun, 7 Jan 2024 12:26:56 +1100 Subject: [PATCH 14/74] Add an isOverClaim property to TownClaimEvent and TownUnclaimEvent (#7165) * Add isOverClaim boolean to TownClaimEvent and TownUnclaimEvent * Add isOverClaim javadocs * Changes from review --- .../bukkit/towny/command/TownCommand.java | 2 +- .../bukkit/towny/db/TownyDatabaseHandler.java | 2 +- .../bukkit/towny/event/TownClaimEvent.java | 14 ++++++++++++-- .../towny/event/town/TownUnclaimEvent.java | 14 ++++++++++++-- .../bukkit/towny/tasks/TownClaim.java | 19 +++++++++++++++++-- 5 files changed, 43 insertions(+), 8 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 322c0f08a4..0530651ea8 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 @@ -3818,7 +3818,7 @@ private void parseTownTakeoverClaimCommand(Player player) throws TownyException double cost = TownySettings.getTakeoverClaimPrice(); String costSlug = !TownyEconomyHandler.isActive() || cost <= 0 ? Translatable.of("msg_spawn_cost_free").forLocale(player) : prettyMoney(cost); String townName = overclaimedTown.getName(); - Confirmation.runOnAccept(() -> Bukkit.getScheduler().runTask(plugin, new TownClaim(plugin, player, town, Arrays.asList(wc), false, true, false))) + Confirmation.runOnAccept(() -> Bukkit.getScheduler().runTask(plugin, new TownClaim(plugin, player, town, Arrays.asList(wc), false, true, false, true))) .setTitle(Translatable.of("confirmation_you_are_about_to_take_over_a_claim", townName, costSlug)) .setCost(new ConfirmationTransaction(() -> cost, town, "Takeover Claim (" + wc.toString() + ") from " + townName + ".")) .sendTo(player); diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/db/TownyDatabaseHandler.java b/Towny/src/main/java/com/palmergames/bukkit/towny/db/TownyDatabaseHandler.java index 5e24990624..dba222b55a 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/db/TownyDatabaseHandler.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/db/TownyDatabaseHandler.java @@ -371,7 +371,7 @@ public void removeTownBlock(TownBlock townBlock) { TownyRegenAPI.addToRegenQueueList(townBlock.getWorldCoord(), true); // Raise an event to signal the unclaim - BukkitTools.fireEvent(new TownUnclaimEvent(town, townBlock.getWorldCoord())); + BukkitTools.fireEvent(new TownUnclaimEvent(town, townBlock.getWorldCoord(), false)); } @Override diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/event/TownClaimEvent.java b/Towny/src/main/java/com/palmergames/bukkit/towny/event/TownClaimEvent.java index 3dbf944c32..07a4de5674 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/event/TownClaimEvent.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/event/TownClaimEvent.java @@ -18,6 +18,7 @@ public class TownClaimEvent extends Event { private final TownBlock townBlock; private Resident resident; + private boolean isOverClaim; @Override public HandlerList getHandlers() { @@ -28,13 +29,22 @@ public static HandlerList getHandlerList() { return handlers; } - public TownClaimEvent(TownBlock townBlock, Player player) { + public TownClaimEvent(TownBlock townBlock, Player player, boolean isOverClaim) { super(!Bukkit.getServer().isPrimaryThread()); this.townBlock = townBlock; this.resident = TownyUniverse.getInstance().getResident(player.getUniqueId()); + this.isOverClaim = isOverClaim; } - /** + /** + * Whether the claim has resulted from takeoverclaim. + * @return true if the claim resulted from /t takeoverclaim. + */ + public boolean isOverClaim() { + return isOverClaim; + } + + /** * * @return the new TownBlock. */ diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/event/town/TownUnclaimEvent.java b/Towny/src/main/java/com/palmergames/bukkit/towny/event/town/TownUnclaimEvent.java index 45a0992045..42439f9c26 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/event/town/TownUnclaimEvent.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/event/town/TownUnclaimEvent.java @@ -17,11 +17,13 @@ public class TownUnclaimEvent extends Event { private static final HandlerList handlers = new HandlerList(); private final Town town; private final WorldCoord worldCoord; + private boolean isOverClaim; - public TownUnclaimEvent(Town town, WorldCoord worldCoord) { + public TownUnclaimEvent(Town town, WorldCoord worldCoord, boolean isOverClaim) { super(!Bukkit.getServer().isPrimaryThread()); this.town = town; this.worldCoord = worldCoord; + this.isOverClaim = isOverClaim; } @NotNull @@ -34,7 +36,15 @@ public static HandlerList getHandlerList() { return handlers; } - /** + /** + * Whether the unclaim has resulted from takeoverclaim. + * @return true if the unclaim resulted from /t takeoverclaim. + */ + public boolean isOverClaim() { + return isOverClaim; + } + + /** * @return {@link Town} which is unclaiming land. */ @Nullable diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/TownClaim.java b/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/TownClaim.java index 969c76cfbe..941fdb0821 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/TownClaim.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/TownClaim.java @@ -46,6 +46,7 @@ public class TownClaim implements Runnable { private double runningRefund = 0.0; private double insufficientFunds = 0.0; private boolean successfulRun = false; + private boolean isOverClaim = false; /** * @param plugin reference to towny @@ -69,6 +70,20 @@ public TownClaim(Towny plugin, Player player, Town town, List select this.runningRefund = 0.0; } + public TownClaim(Towny plugin, Player player, Town town, List selection, boolean isOutpost, boolean claim, boolean forced, boolean isOverClaim) { + this.plugin = plugin; + this.player = player; + if (this.player != null) + this.outpostLocation = player.getLocation(); + this.town = town; + this.selection = selection; + this.outpost = isOutpost; + this.claim = claim; + this.forced = forced; + this.runningRefund = 0.0; + this.isOverClaim = isOverClaim; + } + @Override public void run() { lock.lock(); @@ -193,7 +208,7 @@ private void townClaim(WorldCoord worldCoord) throws TownyException { Town oldTown = worldCoord.getTownOrNull(); // Fire an event for other plugins. - BukkitTools.fireEvent(new TownUnclaimEvent(oldTown, worldCoord)); + BukkitTools.fireEvent(new TownUnclaimEvent(oldTown, worldCoord, isOverClaim)); if (townBlock.hasResident()) townBlock.setResident(null, false); @@ -226,7 +241,7 @@ private void townClaim(WorldCoord worldCoord) throws TownyException { townBlock.save(); // Raise an event for the claim - BukkitTools.fireEvent(new TownClaimEvent(townBlock, player)); + BukkitTools.fireEvent(new TownClaimEvent(townBlock, player, isOverClaim)); } private void handleRevertOnUnclaimPossiblities(WorldCoord worldCoord, TownBlock townBlock) { From ecedd1d71031c755a6a102c248e9bfd965ebc252 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Sat, 6 Jan 2024 19:28:01 -0600 Subject: [PATCH 15/74] - Add an isOverClaim property to TownClaimEvent and TownUnclaimEvent, courtesy of Fruitloopins with PR #7165. --- Towny/src/main/resources/ChangeLog.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index f711df29c2..170d069db3 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9386,4 +9386,5 @@ v0.92.0.11: - Add /t create and /n create tab completions. - Render border particles under leaves. - Fix PlayerChangePlotEvent reactions running too early. - - /res toggle townclaim mode and the ChunkNotifications that follow. \ No newline at end of file + - /res toggle townclaim mode and the ChunkNotifications that follow. + - Add an isOverClaim property to TownClaimEvent and TownUnclaimEvent, courtesy of Fruitloopins with PR #7165. \ No newline at end of file From 08d243f10820183b0ca8d6c9b9c23cf1413ff26e Mon Sep 17 00:00:00 2001 From: LlmDl Date: Sat, 6 Jan 2024 19:28:33 -0600 Subject: [PATCH 16/74] New Crowdin updates (#7167) * New translations en-us.yml (Chinese Simplified) * New translations en-us.yml (German) * New translations en-us.yml (Romanian) * New translations en-us.yml (French) * New translations en-us.yml (Spanish) * New translations en-us.yml (Bulgarian) * New translations en-us.yml (Czech) * New translations en-us.yml (Danish) * New translations en-us.yml (Hebrew) * New translations en-us.yml (Italian) * New translations en-us.yml (Japanese) * New translations en-us.yml (Korean) * New translations en-us.yml (Lithuanian) * New translations en-us.yml (Dutch) * New translations en-us.yml (Norwegian) * New translations en-us.yml (Polish) * New translations en-us.yml (Portuguese) * New translations en-us.yml (Russian) * New translations en-us.yml (Albanian) * New translations en-us.yml (Swedish) * New translations en-us.yml (Turkish) * New translations en-us.yml (Ukrainian) * New translations en-us.yml (Chinese Traditional) * New translations en-us.yml (Vietnamese) * New translations en-us.yml (Portuguese, Brazilian) * New translations en-us.yml (Indonesian) * New translations en-us.yml (Spanish, Argentina) * New translations en-us.yml (Spanish, Chile) * New translations en-us.yml (Spanish, Mexico) * New translations en-us.yml (Spanish, Uruguay) * New translations en-us.yml (Spanish, Venezuela) * New translations en-us.yml (Spanish, Ecuador) * New translations en-us.yml (Thai) * New translations en-us.yml (Azerbaijani) * New translations en-us.yml (English, United Kingdom) * New translations en-us.yml (Tagalog) * New translations en-us.yml (Pirate English) * New translations en-us.yml (Serbian (Latin)) * New translations en-us.yml (English (upside down)) * New translations en-us.yml (LOLCAT) * New translations en-us.yml (Classical Chinese) --- Towny/src/main/resources/lang/az-AZ.yml | 2 ++ Towny/src/main/resources/lang/bg-BG.yml | 2 ++ Towny/src/main/resources/lang/cs-CZ.yml | 2 ++ Towny/src/main/resources/lang/da-DK.yml | 2 ++ Towny/src/main/resources/lang/de-DE.yml | 2 ++ Towny/src/main/resources/lang/en-GB.yml | 2 ++ Towny/src/main/resources/lang/en-PT.yml | 2 ++ Towny/src/main/resources/lang/en-UD.yml | 2 ++ Towny/src/main/resources/lang/es-AR.yml | 2 ++ Towny/src/main/resources/lang/es-CL.yml | 2 ++ Towny/src/main/resources/lang/es-EC.yml | 2 ++ Towny/src/main/resources/lang/es-ES.yml | 2 ++ Towny/src/main/resources/lang/es-MX.yml | 2 ++ Towny/src/main/resources/lang/es-UY.yml | 2 ++ Towny/src/main/resources/lang/es-VE.yml | 2 ++ Towny/src/main/resources/lang/fr-FR.yml | 2 ++ Towny/src/main/resources/lang/he-IL.yml | 2 ++ Towny/src/main/resources/lang/id-ID.yml | 2 ++ Towny/src/main/resources/lang/it-IT.yml | 2 ++ Towny/src/main/resources/lang/ja-JP.yml | 2 ++ Towny/src/main/resources/lang/ko-KR.yml | 2 ++ Towny/src/main/resources/lang/lol-US.yml | 2 ++ Towny/src/main/resources/lang/lt-LT.yml | 2 ++ Towny/src/main/resources/lang/lzh.yml | 2 ++ Towny/src/main/resources/lang/nl-NL.yml | 2 ++ Towny/src/main/resources/lang/no-NO.yml | 2 ++ Towny/src/main/resources/lang/pl-PL.yml | 2 ++ Towny/src/main/resources/lang/pt-BR.yml | 2 ++ Towny/src/main/resources/lang/pt-PT.yml | 2 ++ Towny/src/main/resources/lang/ro-RO.yml | 2 ++ Towny/src/main/resources/lang/ru-RU.yml | 2 ++ Towny/src/main/resources/lang/sq-AL.yml | 2 ++ Towny/src/main/resources/lang/sr-CS.yml | 2 ++ Towny/src/main/resources/lang/sv-SE.yml | 2 ++ Towny/src/main/resources/lang/th-TH.yml | 2 ++ Towny/src/main/resources/lang/tl-PH.yml | 2 ++ Towny/src/main/resources/lang/tr-TR.yml | 2 ++ Towny/src/main/resources/lang/uk-UA.yml | 2 ++ Towny/src/main/resources/lang/vi-VN.yml | 2 ++ Towny/src/main/resources/lang/zh-CN.yml | 2 ++ Towny/src/main/resources/lang/zh-TW.yml | 2 ++ 41 files changed, 82 insertions(+) diff --git a/Towny/src/main/resources/lang/az-AZ.yml b/Towny/src/main/resources/lang/az-AZ.yml index d18e098976..29b416dffe 100644 --- a/Towny/src/main/resources/lang/az-AZ.yml +++ b/Towny/src/main/resources/lang/az-AZ.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/bg-BG.yml b/Towny/src/main/resources/lang/bg-BG.yml index a91d16d837..7ecafca8fc 100644 --- a/Towny/src/main/resources/lang/bg-BG.yml +++ b/Towny/src/main/resources/lang/bg-BG.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/cs-CZ.yml b/Towny/src/main/resources/lang/cs-CZ.yml index d52d1247c5..20b54a01f5 100644 --- a/Towny/src/main/resources/lang/cs-CZ.yml +++ b/Towny/src/main/resources/lang/cs-CZ.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/da-DK.yml b/Towny/src/main/resources/lang/da-DK.yml index 5d915e6984..c795e1dfb4 100644 --- a/Towny/src/main/resources/lang/da-DK.yml +++ b/Towny/src/main/resources/lang/da-DK.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/de-DE.yml b/Towny/src/main/resources/lang/de-DE.yml index 1cb860f42d..1a33c2b2bd 100644 --- a/Towny/src/main/resources/lang/de-DE.yml +++ b/Towny/src/main/resources/lang/de-DE.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/en-GB.yml b/Towny/src/main/resources/lang/en-GB.yml index 4144adea89..2241dd6f8e 100644 --- a/Towny/src/main/resources/lang/en-GB.yml +++ b/Towny/src/main/resources/lang/en-GB.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/en-PT.yml b/Towny/src/main/resources/lang/en-PT.yml index 1fa6447dd0..aaddecc330 100644 --- a/Towny/src/main/resources/lang/en-PT.yml +++ b/Towny/src/main/resources/lang/en-PT.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/en-UD.yml b/Towny/src/main/resources/lang/en-UD.yml index 1085a4783b..6b61b1c220 100644 --- a/Towny/src/main/resources/lang/en-UD.yml +++ b/Towny/src/main/resources/lang/en-UD.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/es-AR.yml b/Towny/src/main/resources/lang/es-AR.yml index 2defc09025..f6a050ae6a 100644 --- a/Towny/src/main/resources/lang/es-AR.yml +++ b/Towny/src/main/resources/lang/es-AR.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/es-CL.yml b/Towny/src/main/resources/lang/es-CL.yml index ff9360fea6..5f4b82c098 100644 --- a/Towny/src/main/resources/lang/es-CL.yml +++ b/Towny/src/main/resources/lang/es-CL.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/es-EC.yml b/Towny/src/main/resources/lang/es-EC.yml index d1b9589900..65322a65ae 100644 --- a/Towny/src/main/resources/lang/es-EC.yml +++ b/Towny/src/main/resources/lang/es-EC.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/es-ES.yml b/Towny/src/main/resources/lang/es-ES.yml index 8e5f724efe..bb7d17d97a 100644 --- a/Towny/src/main/resources/lang/es-ES.yml +++ b/Towny/src/main/resources/lang/es-ES.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/es-MX.yml b/Towny/src/main/resources/lang/es-MX.yml index 7762ac4089..e64133b897 100644 --- a/Towny/src/main/resources/lang/es-MX.yml +++ b/Towny/src/main/resources/lang/es-MX.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/es-UY.yml b/Towny/src/main/resources/lang/es-UY.yml index d1b9589900..65322a65ae 100644 --- a/Towny/src/main/resources/lang/es-UY.yml +++ b/Towny/src/main/resources/lang/es-UY.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/es-VE.yml b/Towny/src/main/resources/lang/es-VE.yml index d1b9589900..65322a65ae 100644 --- a/Towny/src/main/resources/lang/es-VE.yml +++ b/Towny/src/main/resources/lang/es-VE.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/fr-FR.yml b/Towny/src/main/resources/lang/fr-FR.yml index 16d0cea1ef..bda8326fe5 100644 --- a/Towny/src/main/resources/lang/fr-FR.yml +++ b/Towny/src/main/resources/lang/fr-FR.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/he-IL.yml b/Towny/src/main/resources/lang/he-IL.yml index 620126e4be..099594b700 100644 --- a/Towny/src/main/resources/lang/he-IL.yml +++ b/Towny/src/main/resources/lang/he-IL.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/id-ID.yml b/Towny/src/main/resources/lang/id-ID.yml index 87cec3dff5..8364e22853 100644 --- a/Towny/src/main/resources/lang/id-ID.yml +++ b/Towny/src/main/resources/lang/id-ID.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/it-IT.yml b/Towny/src/main/resources/lang/it-IT.yml index 1714c0b5e3..ea63717694 100644 --- a/Towny/src/main/resources/lang/it-IT.yml +++ b/Towny/src/main/resources/lang/it-IT.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/ja-JP.yml b/Towny/src/main/resources/lang/ja-JP.yml index 3ab19bd980..c873834c47 100644 --- a/Towny/src/main/resources/lang/ja-JP.yml +++ b/Towny/src/main/resources/lang/ja-JP.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/ko-KR.yml b/Towny/src/main/resources/lang/ko-KR.yml index 5cc4267694..3b73dc8cad 100644 --- a/Towny/src/main/resources/lang/ko-KR.yml +++ b/Towny/src/main/resources/lang/ko-KR.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/lol-US.yml b/Towny/src/main/resources/lang/lol-US.yml index d3c60be02a..34a1db385a 100644 --- a/Towny/src/main/resources/lang/lol-US.yml +++ b/Towny/src/main/resources/lang/lol-US.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/lt-LT.yml b/Towny/src/main/resources/lang/lt-LT.yml index c577ee6dce..05d9329567 100644 --- a/Towny/src/main/resources/lang/lt-LT.yml +++ b/Towny/src/main/resources/lang/lt-LT.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/lzh.yml b/Towny/src/main/resources/lang/lzh.yml index 21b4db2f6b..d0c487bb88 100644 --- a/Towny/src/main/resources/lang/lzh.yml +++ b/Towny/src/main/resources/lang/lzh.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/nl-NL.yml b/Towny/src/main/resources/lang/nl-NL.yml index 8bb865fdc8..ae69a67510 100644 --- a/Towny/src/main/resources/lang/nl-NL.yml +++ b/Towny/src/main/resources/lang/nl-NL.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/no-NO.yml b/Towny/src/main/resources/lang/no-NO.yml index 5ad8b207fc..d40086b622 100644 --- a/Towny/src/main/resources/lang/no-NO.yml +++ b/Towny/src/main/resources/lang/no-NO.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/pl-PL.yml b/Towny/src/main/resources/lang/pl-PL.yml index c19b8aec9b..b4ed60b407 100644 --- a/Towny/src/main/resources/lang/pl-PL.yml +++ b/Towny/src/main/resources/lang/pl-PL.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/pt-BR.yml b/Towny/src/main/resources/lang/pt-BR.yml index d3b7a6a8f9..5018cac060 100644 --- a/Towny/src/main/resources/lang/pt-BR.yml +++ b/Towny/src/main/resources/lang/pt-BR.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/pt-PT.yml b/Towny/src/main/resources/lang/pt-PT.yml index 0fa12d1dd9..fae5b45a85 100644 --- a/Towny/src/main/resources/lang/pt-PT.yml +++ b/Towny/src/main/resources/lang/pt-PT.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/ro-RO.yml b/Towny/src/main/resources/lang/ro-RO.yml index 0a1e458186..a7232aea91 100644 --- a/Towny/src/main/resources/lang/ro-RO.yml +++ b/Towny/src/main/resources/lang/ro-RO.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/ru-RU.yml b/Towny/src/main/resources/lang/ru-RU.yml index b056ebd0fc..84b16826a3 100644 --- a/Towny/src/main/resources/lang/ru-RU.yml +++ b/Towny/src/main/resources/lang/ru-RU.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/sq-AL.yml b/Towny/src/main/resources/lang/sq-AL.yml index 6acc42238b..7aefa14d46 100644 --- a/Towny/src/main/resources/lang/sq-AL.yml +++ b/Towny/src/main/resources/lang/sq-AL.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/sr-CS.yml b/Towny/src/main/resources/lang/sr-CS.yml index a252df851e..b0bc56e92e 100644 --- a/Towny/src/main/resources/lang/sr-CS.yml +++ b/Towny/src/main/resources/lang/sr-CS.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/sv-SE.yml b/Towny/src/main/resources/lang/sv-SE.yml index df9c820db0..6a06df1ddf 100644 --- a/Towny/src/main/resources/lang/sv-SE.yml +++ b/Towny/src/main/resources/lang/sv-SE.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/th-TH.yml b/Towny/src/main/resources/lang/th-TH.yml index b62a6d8b4e..2019deace0 100644 --- a/Towny/src/main/resources/lang/th-TH.yml +++ b/Towny/src/main/resources/lang/th-TH.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/tl-PH.yml b/Towny/src/main/resources/lang/tl-PH.yml index 090e08f0a6..22f10b4552 100644 --- a/Towny/src/main/resources/lang/tl-PH.yml +++ b/Towny/src/main/resources/lang/tl-PH.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/tr-TR.yml b/Towny/src/main/resources/lang/tr-TR.yml index c362db6039..f39046400f 100644 --- a/Towny/src/main/resources/lang/tr-TR.yml +++ b/Towny/src/main/resources/lang/tr-TR.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/uk-UA.yml b/Towny/src/main/resources/lang/uk-UA.yml index e96ab5f2a3..47e469f7df 100644 --- a/Towny/src/main/resources/lang/uk-UA.yml +++ b/Towny/src/main/resources/lang/uk-UA.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/vi-VN.yml b/Towny/src/main/resources/lang/vi-VN.yml index a41434a96d..a5f7ca834e 100644 --- a/Towny/src/main/resources/lang/vi-VN.yml +++ b/Towny/src/main/resources/lang/vi-VN.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/zh-CN.yml b/Towny/src/main/resources/lang/zh-CN.yml index 91592b43ea..37b2c2d8de 100644 --- a/Towny/src/main/resources/lang/zh-CN.yml +++ b/Towny/src/main/resources/lang/zh-CN.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' diff --git a/Towny/src/main/resources/lang/zh-TW.yml b/Towny/src/main/resources/lang/zh-TW.yml index 7b8f68d9b2..99b1385443 100644 --- a/Towny/src/main/resources/lang/zh-TW.yml +++ b/Towny/src/main/resources/lang/zh-TW.yml @@ -2080,3 +2080,5 @@ msg_err_cannot_claim_the_following_worldcoords_because_of_unwanted_biome: "The f msg_err_cannot_claim_the_following_worldcoords_because_of_ocean_biome: "The following coordinate(s) cannot be claimed because they contain too much ocean biome: %s." msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome." msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." +msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' From bd34127a74279f7ceae1de1c26452e2021266426 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Sun, 7 Jan 2024 14:35:50 -0600 Subject: [PATCH 17/74] - Refactor PermHud class. --- Towny/pom.xml | 2 +- .../bukkit/towny/huds/PermHUD.java | 255 +++++++++++------- Towny/src/main/resources/ChangeLog.txt | 4 +- 3 files changed, 161 insertions(+), 100 deletions(-) diff --git a/Towny/pom.xml b/Towny/pom.xml index 888e7defc9..80daef8006 100644 --- a/Towny/pom.xml +++ b/Towny/pom.xml @@ -13,7 +13,7 @@ towny jar - 0.100.0.19 + 0.100.0.20 diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/huds/PermHUD.java b/Towny/src/main/java/com/palmergames/bukkit/towny/huds/PermHUD.java index b0463d0ff9..5ada061265 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/huds/PermHUD.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/huds/PermHUD.java @@ -1,7 +1,6 @@ package com.palmergames.bukkit.towny.huds; import com.palmergames.bukkit.towny.TownyAPI; -import com.palmergames.bukkit.towny.object.Coord; import com.palmergames.bukkit.towny.object.Resident; import com.palmergames.bukkit.towny.object.TownBlock; import com.palmergames.bukkit.towny.object.TownBlockOwner; @@ -25,9 +24,36 @@ public class PermHUD { + /* Scoreboards use old-timey colours. */ + private static final ChatColor DARK_RED = ChatColor.DARK_RED; + private static final ChatColor WHITE = ChatColor.WHITE; + private static final ChatColor GRAY = ChatColor.GRAY; + private static final ChatColor YELLOW = ChatColor.YELLOW; + private static final ChatColor DARK_GREEN = ChatColor.DARK_GREEN; + private static final ChatColor GOLD = ChatColor.GOLD; + private static final ChatColor BOLD = ChatColor.BOLD; + private static final ChatColor UNDERLINE = ChatColor.UNDERLINE; + + /* Scoreboards use Teams here is our team names.*/ + private static final String HUD_OBJECTIVE = "PERM_HUD_OBJ"; + private static final String TEAM_PERMS_TITLE = "permsTitle"; + private static final String PLOT_NAME = "plot_name"; + private static final String TEAM_BUILD = "build"; + private static final String TEAM_DESTROY = "destroy"; + private static final String TEAM_SWITCH = "switching"; + private static final String TEAM_ITEMUSE = "item"; + private static final String TEAM_PLOT_TYPE = "plotType"; + private static final String TEAM_PVP = "pvp"; + private static final String TEAM_EXPLOSIONS = "explosions"; + private static final String TEAM_FIRESPREAD = "firespread"; + private static final String TEAM_MOBSPAWNING = "mobspawn"; + private static final String TEAM_TITLE = "keyTitle"; + private static final String TEAM_RESIDENT = "keyResident"; + private static final String TEAM_FRIEND = "keyFriend"; + private static final String TEAM_ALLY = "keyAlly"; + public static void updatePerms (Player p) { - WorldCoord worldCoord = new WorldCoord(p.getWorld(), Coord.parseCoord(p)); - updatePerms(p, worldCoord); + updatePerms(p, WorldCoord.parseWorldCoord(p)); } public static void updatePerms(Player p, WorldCoord worldCoord) { @@ -42,10 +68,10 @@ public static void updatePerms(Player p, WorldCoord worldCoord) { toggleOn(p); return; } - - if (board.getObjective("PERM_HUD_OBJ") == null) { // Some other plugin's scoreboard has - HUDManager.toggleOff(p); // likely been activated, meaning we - return; // will throw NPEs if we continue. + + if (board.getObjective(HUD_OBJECTIVE) == null) { // Some other plugin's scoreboard has + HUDManager.toggleOff(p); // likely been activated, meaning we + return; // will throw NPEs if we continue. } if (worldCoord.isWilderness()) { @@ -55,61 +81,77 @@ public static void updatePerms(Player p, WorldCoord worldCoord) { TownBlock townBlock = worldCoord.getTownBlockOrNull(); TownBlockOwner owner = townBlock.getTownBlockOwner(); - TownyWorld world = townBlock.getWorld(); - TownyPermission tp = townBlock.getPermissions(); - String v = (owner instanceof Resident) ? "f" : "r"; - String u = (owner instanceof Resident) ? "t" : "n"; - build = (tp.getResidentPerm(ActionType.BUILD) ? v : "-") + (tp.getNationPerm(ActionType.BUILD) ? u : "-") + (tp.getAllyPerm(ActionType.BUILD) ? "a" : "-") + (tp.getOutsiderPerm(ActionType.BUILD) ? "o" : "-"); - destroy = (tp.getResidentPerm(ActionType.DESTROY) ? v : "-") + (tp.getNationPerm(ActionType.DESTROY) ? u : "-") + (tp.getAllyPerm(ActionType.DESTROY) ? "a" : "-") + (tp.getOutsiderPerm(ActionType.DESTROY) ? "o" : "-"); - switching = (tp.getResidentPerm(ActionType.SWITCH) ? v : "-") + (tp.getNationPerm(ActionType.SWITCH) ? u : "-") + (tp.getAllyPerm(ActionType.SWITCH) ? "a" : "-") + (tp.getOutsiderPerm(ActionType.SWITCH) ? "o" : "-"); - item = (tp.getResidentPerm(ActionType.ITEM_USE) ? v : "-") + (tp.getNationPerm(ActionType.ITEM_USE) ? u : "-") + (tp.getAllyPerm(ActionType.ITEM_USE) ? "a" : "-") + (tp.getOutsiderPerm(ActionType.ITEM_USE) ? "o" : "-"); - type = townBlock.getType().equals(TownBlockType.RESIDENTIAL) ? " " : townBlock.getType().getName(); - pvp = !CombatUtil.preventPvP(worldCoord.getTownyWorld(), townBlock) ? translator.of("status_on") : translator.of("status_off"); - explosions = (world.isForceExpl() || tp.explosion) ? translator.of("status_on") : translator.of("status_off"); - firespread = (world.isForceFire() || tp.fire) ? translator.of("status_on") : translator.of("status_off"); - mobspawn = (world.isForceTownMobs() || tp.mobs || townBlock.getTownOrNull().isAdminEnabledMobs()) ? translator.of("status_on") : translator.of("status_off"); // Displays the name of the owner, and if the owner is a resident the town name as well. - title = ChatColor.GOLD + owner.getName() + (townBlock.hasResident() ? " (" + townBlock.getTownOrNull().getName() + ")" : ""); - + title = GOLD + owner.getName() + (townBlock.hasResident() ? " (" + townBlock.getTownOrNull().getName() + ")" : ""); + type = townBlock.getType().equals(TownBlockType.RESIDENTIAL) ? " " : townBlock.getType().getName(); plotName = townBlock.getName().isEmpty() ? "" : translator.of("msg_perm_hud_plot_name") + townBlock.getName(); - if (!plotName.isEmpty()) - board.getTeam("plot").setSuffix(HUDManager.check(plotName)); - else - board.getTeam("plot").setSuffix(" "); - board.getTeam("build").setSuffix(build); - board.getTeam("destroy").setSuffix(destroy); - board.getTeam("switching").setSuffix(switching); - board.getTeam("item").setSuffix(item); - board.getTeam("plotType").setSuffix(type); - board.getTeam("pvp").setSuffix(pvp); - board.getTeam("explosions").setSuffix(explosions); - board.getTeam("firespread").setSuffix(firespread); - board.getTeam("mobspawn").setSuffix(mobspawn); - board.getObjective("PERM_HUD_OBJ").setDisplayName(HUDManager.check(title)); + + TownyPermission tp = townBlock.getPermissions(); + boolean residentOwned = owner instanceof Resident; + build = getPermLine(tp, ActionType.BUILD, residentOwned); + destroy = getPermLine(tp, ActionType.DESTROY, residentOwned); + switching = getPermLine(tp, ActionType.SWITCH, residentOwned); + item = getPermLine(tp, ActionType.ITEM_USE, residentOwned); + + TownyWorld world = townBlock.getWorld(); + pvp = getTranslatedOnOrOff(!CombatUtil.preventPvP(world, townBlock), translator); + explosions = getTranslatedOnOrOff(world.isForceExpl() || tp.explosion, translator); + firespread = getTranslatedOnOrOff(world.isForceFire() || tp.fire, translator); + mobspawn = getTranslatedOnOrOff(world.isForceTownMobs() || tp.mobs || townBlock.getTownOrNull().isAdminEnabledMobs(), translator); + + + // Set the values to our Scoreboard's teams. + board.getObjective(HUD_OBJECTIVE).setDisplayName(HUDManager.check(title)); + board.getTeam(PLOT_NAME).setSuffix(!plotName.isEmpty() ? HUDManager.check(plotName) : " "); + board.getTeam(TEAM_PLOT_TYPE).setSuffix(type); + + board.getTeam(TEAM_BUILD).setSuffix(build); + board.getTeam(TEAM_DESTROY).setSuffix(destroy); + board.getTeam(TEAM_SWITCH).setSuffix(switching); + board.getTeam(TEAM_ITEMUSE).setSuffix(item); + + board.getTeam(TEAM_PVP).setSuffix(pvp); + board.getTeam(TEAM_EXPLOSIONS).setSuffix(explosions); + board.getTeam(TEAM_FIRESPREAD).setSuffix(firespread); + board.getTeam(TEAM_MOBSPAWNING).setSuffix(mobspawn); + + } + + private static String getPermLine(TownyPermission tp, ActionType actionType, boolean residentOwned) { + String v = residentOwned ? "f" : "r"; + String u = residentOwned ? "t" : "n"; + return (tp.getResidentPerm(actionType) ? v : "-") + (tp.getNationPerm(actionType) ? u : "-") + + (tp.getAllyPerm(actionType) ? "a" : "-") + (tp.getOutsiderPerm(actionType) ? "o" : "-"); + } + + private static String getTranslatedOnOrOff(boolean test, Translator translator) { + return test ? translator.of("status_on") : translator.of("status_off"); } private static void clearPerms (Player p) { Scoreboard board = p.getScoreboard(); try { - board.getTeam("plot").setSuffix(" "); - board.getTeam("build").setSuffix(" "); - board.getTeam("destroy").setSuffix(" "); - board.getTeam("switching").setSuffix(" "); - board.getTeam("item").setSuffix(" "); - board.getTeam("plotType").setSuffix(" "); - board.getTeam("pvp").setSuffix(" "); - board.getTeam("explosions").setSuffix(" "); - board.getTeam("firespread").setSuffix(" "); - board.getTeam("mobspawn").setSuffix(" "); - board.getObjective("PERM_HUD_OBJ").setDisplayName(HUDManager.check(getFormattedWildernessName(p.getWorld()))); + board.getObjective(HUD_OBJECTIVE).setDisplayName(HUDManager.check(getFormattedWildernessName(p.getWorld()))); + board.getTeam(PLOT_NAME).setSuffix(" "); + board.getTeam(TEAM_PLOT_TYPE).setSuffix(" "); + + board.getTeam(TEAM_BUILD).setSuffix(" "); + board.getTeam(TEAM_DESTROY).setSuffix(" "); + board.getTeam(TEAM_SWITCH).setSuffix(" "); + board.getTeam(TEAM_ITEMUSE).setSuffix(" "); + + board.getTeam(TEAM_PVP).setSuffix(" "); + board.getTeam(TEAM_EXPLOSIONS).setSuffix(" "); + board.getTeam(TEAM_FIRESPREAD).setSuffix(" "); + board.getTeam(TEAM_MOBSPAWNING).setSuffix(" "); } catch (NullPointerException e) { toggleOn(p); } } private static String getFormattedWildernessName(World w) { - StringBuilder wildernessName = new StringBuilder().append(ChatColor.DARK_RED).append(ChatColor.BOLD); + StringBuilder wildernessName = new StringBuilder().append(DARK_RED).append(BOLD); if (TownyAPI.getInstance().isTownyWorld(w)) wildernessName.append(TownyAPI.getInstance().getTownyWorld(w).getFormattedUnclaimedZoneName()); else @@ -119,72 +161,93 @@ private static String getFormattedWildernessName(World w) { } public static void toggleOn (Player p) { - Translator translator = Translator.locale(p); - String PERM_HUD_TITLE = ChatColor.GOLD + ""; - String permsTitle_entry = ChatColor.YELLOW + "" + ChatColor.UNDERLINE + translator.of("msg_perm_hud_title"); - String plotName_entry = ChatColor.DARK_GREEN + ""; - String build_entry = ChatColor.DARK_GREEN + translator.of("msg_perm_hud_build") + ChatColor.GRAY; - String destroy_entry = ChatColor.DARK_GREEN + translator.of("msg_perm_hud_destroy") + ChatColor.GRAY; - String switching_entry = ChatColor.DARK_GREEN + translator.of("msg_perm_hud_switch") + ChatColor.GRAY; - String item_entry = ChatColor.DARK_GREEN + translator.of("msg_perm_hud_item_use") + ChatColor.GRAY; - String keyPlotType_entry = ChatColor.DARK_GREEN + translator.of("msg_perm_hud_plot_type"); - String pvp_entry = ChatColor.DARK_GREEN + translator.of("msg_perm_hud_pvp") + " "; - String explosions_entry = ChatColor.DARK_GREEN + translator.of("msg_perm_hud_explosions") + " "; - String firespread_entry = ChatColor.DARK_GREEN + translator.of("msg_perm_hud_firespread") + " "; - String mobspawn_entry = ChatColor.DARK_GREEN + translator.of("msg_perm_hud_mobspawns") + " "; - String keyTitle_entry = ChatColor.YELLOW + "" + ChatColor.UNDERLINE + translator.of("msg_perm_hud_key"); - String keyResident_entry = ChatColor.DARK_GREEN + "" + ChatColor.BOLD + "f" + ChatColor.WHITE + " - " + ChatColor.GRAY + translator.of("msg_perm_hud_friend") + ChatColor.DARK_GREEN + " " + ChatColor.BOLD + "r" + ChatColor.WHITE + " - " + ChatColor.GRAY + translator.of("msg_perm_hud_resident"); - String keyNation_entry = ChatColor.DARK_GREEN + "" + ChatColor.BOLD + "t" + ChatColor.WHITE + " - " + ChatColor.GRAY + translator.of("msg_perm_hud_town") + ChatColor.DARK_GREEN + " " + ChatColor.BOLD + "n" + ChatColor.WHITE + " - " + ChatColor.GRAY + translator.of("msg_perm_hud_nation"); - String keyAlly_entry = ChatColor.DARK_GREEN + "" + ChatColor.BOLD + "a" + ChatColor.WHITE + " - " + ChatColor.GRAY + translator.of("msg_perm_hud_ally") + ChatColor.DARK_GREEN + " " + ChatColor.BOLD + "o" + ChatColor.WHITE + " - " + ChatColor.GRAY + translator.of("msg_perm_hud_outsider"); - - //init objective + //init scoreboard Scoreboard board = Bukkit.getScoreboardManager().getNewScoreboard(); - Objective obj = BukkitTools.objective(board, "PERM_HUD_OBJ", PERM_HUD_TITLE); + initializeScoreboard(Translator.locale(p), board); + + //set the board onto the player + p.setScoreboard(board); + + //call for the board's values to be populated + updatePerms(p); + } + + private static void initializeScoreboard(Translator translator, Scoreboard board) { + String PERM_HUD_TITLE = GOLD + ""; + String plotName_entry = DARK_GREEN + ""; + String keyPlotType_entry = DARK_GREEN + translator.of("msg_perm_hud_plot_type"); + + String permsTitle_entry = YELLOW + "" + UNDERLINE + translator.of("msg_perm_hud_title"); + String build_entry = DARK_GREEN + translator.of("msg_perm_hud_build") + GRAY; + String destroy_entry = DARK_GREEN + translator.of("msg_perm_hud_destroy") + GRAY; + String switching_entry = DARK_GREEN + translator.of("msg_perm_hud_switch") + GRAY; + String item_entry = DARK_GREEN + translator.of("msg_perm_hud_item_use") + GRAY; + + String pvp_entry = DARK_GREEN + translator.of("msg_perm_hud_pvp") + " "; + String explosions_entry = DARK_GREEN + translator.of("msg_perm_hud_explosions") + " "; + String firespread_entry = DARK_GREEN + translator.of("msg_perm_hud_firespread") + " "; + String mobspawn_entry = DARK_GREEN + translator.of("msg_perm_hud_mobspawns") + " "; + + String keyTitle_entry = YELLOW + "" + UNDERLINE + translator.of("msg_perm_hud_key"); + String keyResident_entry = DARK_GREEN + "" + BOLD + "f" + WHITE + " - " + GRAY + translator.of("msg_perm_hud_friend") + + DARK_GREEN + " " + BOLD + "r" + WHITE + " - " + GRAY + translator.of("msg_perm_hud_resident"); + String keyNation_entry = DARK_GREEN + "" + BOLD + "t" + WHITE + " - " + GRAY + translator.of("msg_perm_hud_town") + + DARK_GREEN + " " + BOLD + "n" + WHITE + " - " + GRAY + translator.of("msg_perm_hud_nation"); + String keyAlly_entry = DARK_GREEN + "" + BOLD + "a" + WHITE + " - " + GRAY + translator.of("msg_perm_hud_ally") + + DARK_GREEN + " " + BOLD + "o" + WHITE + " - " + GRAY + translator.of("msg_perm_hud_outsider"); + + Objective obj = BukkitTools.objective(board, HUD_OBJECTIVE, PERM_HUD_TITLE); obj.setDisplaySlot(DisplaySlot.SIDEBAR); obj.setDisplayName(PERM_HUD_TITLE); //register teams - Team permsTitle = board.registerNewTeam("permsTitle"); - Team plotName = board.registerNewTeam("plot"); - Team build = board.registerNewTeam("build"); - Team destroy = board.registerNewTeam("destroy"); - Team switching = board.registerNewTeam("switching"); - Team item = board.registerNewTeam("item"); - Team keyPlotType = board.registerNewTeam("plotType"); - Team pvp = board.registerNewTeam("pvp"); - Team explosions = board.registerNewTeam("explosions"); - Team firespread = board.registerNewTeam("firespread"); - Team mobspawn= board.registerNewTeam("mobspawn"); - Team keyTitle = board.registerNewTeam("keyTitle"); - Team keyResident = board.registerNewTeam("keyResident"); - Team keyFriend = board.registerNewTeam("keyFriend"); - Team keyAlly = board.registerNewTeam("keyAlly"); - - //register players - permsTitle.addEntry(permsTitle_entry); + Team plotName = board.registerNewTeam(PLOT_NAME); + Team keyPlotType = board.registerNewTeam(TEAM_PLOT_TYPE); + + Team permsTitle = board.registerNewTeam(TEAM_PERMS_TITLE); + Team build = board.registerNewTeam(TEAM_BUILD); + Team destroy = board.registerNewTeam(TEAM_DESTROY); + Team switching = board.registerNewTeam(TEAM_SWITCH); + Team item = board.registerNewTeam(TEAM_ITEMUSE); + + Team pvp = board.registerNewTeam(TEAM_PVP); + Team explosions = board.registerNewTeam(TEAM_EXPLOSIONS); + Team firespread = board.registerNewTeam(TEAM_FIRESPREAD); + Team mobspawn= board.registerNewTeam(TEAM_MOBSPAWNING); + + Team keyTitle = board.registerNewTeam(TEAM_TITLE); + Team keyResident = board.registerNewTeam(TEAM_RESIDENT); + Team keyFriend = board.registerNewTeam(TEAM_FRIEND); + Team keyAlly = board.registerNewTeam(TEAM_ALLY); + + //add each team as an entry (this sets the prefix to each line of the HUD.) plotName.addEntry(plotName_entry); + keyPlotType.addEntry(keyPlotType_entry); + + permsTitle.addEntry(permsTitle_entry); build.addEntry(build_entry); destroy.addEntry(destroy_entry); switching.addEntry(switching_entry); item.addEntry(item_entry); - keyPlotType.addEntry(keyPlotType_entry); + pvp.addEntry(pvp_entry); explosions.addEntry(explosions_entry); firespread.addEntry(firespread_entry); mobspawn.addEntry(mobspawn_entry); + keyTitle.addEntry(keyTitle_entry); keyResident.addEntry(keyResident_entry); keyFriend.addEntry(keyNation_entry); keyAlly.addEntry(keyAlly_entry); //set scores for positioning - obj.getScore(permsTitle_entry).setScore(15); - obj.getScore(plotName_entry).setScore(14); - obj.getScore(build_entry).setScore(13); - obj.getScore(destroy_entry).setScore(12); - obj.getScore(switching_entry).setScore(11); - obj.getScore(item_entry).setScore(10); + obj.getScore(plotName_entry).setScore(15); + obj.getScore(keyPlotType_entry).setScore(14); + obj.getScore(permsTitle_entry).setScore(13); + obj.getScore(build_entry).setScore(12); + obj.getScore(destroy_entry).setScore(11); + obj.getScore(switching_entry).setScore(10); + obj.getScore(item_entry).setScore(9); obj.getScore(pvp_entry).setScore(8); - obj.getScore(keyPlotType_entry).setScore(9); obj.getScore(explosions_entry).setScore(7); obj.getScore(firespread_entry).setScore(6); obj.getScore(mobspawn_entry).setScore(5); @@ -192,9 +255,5 @@ public static void toggleOn (Player p) { obj.getScore(keyResident_entry).setScore(3); obj.getScore(keyNation_entry).setScore(2); obj.getScore(keyAlly_entry).setScore(1); - - //set the board - p.setScoreboard(board); - updatePerms(p); } } diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index 170d069db3..24c9a17fd3 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9387,4 +9387,6 @@ v0.92.0.11: - Render border particles under leaves. - Fix PlayerChangePlotEvent reactions running too early. - /res toggle townclaim mode and the ChunkNotifications that follow. - - Add an isOverClaim property to TownClaimEvent and TownUnclaimEvent, courtesy of Fruitloopins with PR #7165. \ No newline at end of file + - Add an isOverClaim property to TownClaimEvent and TownUnclaimEvent, courtesy of Fruitloopins with PR #7165. +0.100.0.20: + - Refactor PermHud class. \ No newline at end of file From 7a5b3ae95ba4eafb39d89d95cb18b98f203b8391 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Mon, 8 Jan 2024 07:52:52 -0600 Subject: [PATCH 18/74] - Fix jail bail amounts not being applied correctly. --- .../java/com/palmergames/bukkit/towny/command/TownCommand.java | 2 +- Towny/src/main/resources/ChangeLog.txt | 3 ++- 2 files changed, 3 insertions(+), 2 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 0530651ea8..65ec25d0a4 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 @@ -1648,7 +1648,7 @@ private static int setJailHours(CommandSender sender, String[] split) { } private static double setBail(CommandSender sender, String[] split) { - double bail = Math.min(1, Double.parseDouble(split[2])); + double bail = Math.max(1, Double.parseDouble(split[2])); if (bail > TownySettings.getBailMaxAmount()) { bail = TownySettings.getBailMaxAmount(); diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index 24c9a17fd3..4ca29691fe 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9389,4 +9389,5 @@ v0.92.0.11: - /res toggle townclaim mode and the ChunkNotifications that follow. - Add an isOverClaim property to TownClaimEvent and TownUnclaimEvent, courtesy of Fruitloopins with PR #7165. 0.100.0.20: - - Refactor PermHud class. \ No newline at end of file + - Refactor PermHud class. + - Fix jail bail amounts not being applied correctly. \ No newline at end of file From 641f4c9b9686556e30de55ec475c5e1d77336a93 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Mon, 8 Jan 2024 09:44:11 -0600 Subject: [PATCH 19/74] - Fix a couple places where the adminbypass mode would not stop admins being treated special for teleports. --- .../bukkit/towny/listeners/TownyPlayerListener.java | 2 +- .../java/com/palmergames/bukkit/towny/utils/ResidentUtil.java | 2 +- Towny/src/main/resources/ChangeLog.txt | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyPlayerListener.java b/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyPlayerListener.java index b2996fa2ae..6f32abdd5e 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyPlayerListener.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyPlayerListener.java @@ -775,7 +775,7 @@ public void onPlayerTeleport(PlayerTeleportEvent event) { Player player = event.getPlayer(); Resident resident = TownyUniverse.getInstance().getResident(player.getUniqueId()); - boolean isAdmin = resident != null && (resident.isAdmin() || resident.hasPermissionNode(PermissionNodes.TOWNY_ADMIN_OUTLAW_TELEPORT_BYPASS.getNode())); + boolean isAdmin = !Towny.getPlugin().hasPlayerMode(player, "adminbypass") && resident != null && (resident.isAdmin() || resident.hasPermissionNode(PermissionNodes.TOWNY_ADMIN_OUTLAW_TELEPORT_BYPASS.getNode())); // Cancel teleport if Jailed by Towny and not an admin. if (resident != null && resident.isJailed() && !isAdmin) { if ((event.getCause() == TeleportCause.COMMAND)) { diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/ResidentUtil.java b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/ResidentUtil.java index c0e8c8a901..64ef657e1f 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/ResidentUtil.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/ResidentUtil.java @@ -290,7 +290,7 @@ public static void outlawEnteredTown(Resident outlaw, Town town, Location locati if (BukkitTools.isEventCancelled(outlawEvent)) return; - boolean hasBypassNode = outlaw.hasPermissionNode(PermissionNodes.TOWNY_ADMIN_OUTLAW_TELEPORT_BYPASS.getNode()); + boolean hasBypassNode = outlaw.hasPermissionNode(PermissionNodes.TOWNY_ADMIN_OUTLAW_TELEPORT_BYPASS.getNode()) && !outlaw.hasMode("adminbypass"); // Admins are omitted so towns won't be informed an admin might be spying on them. if (TownySettings.doTownsGetWarnedOnOutlaw() && !hasBypassNode && !CooldownTimerTask.hasCooldown(outlaw.getName(), CooldownType.OUTLAW_WARNING)) { diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index 4ca29691fe..43ff273cb0 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9390,4 +9390,5 @@ v0.92.0.11: - Add an isOverClaim property to TownClaimEvent and TownUnclaimEvent, courtesy of Fruitloopins with PR #7165. 0.100.0.20: - Refactor PermHud class. - - Fix jail bail amounts not being applied correctly. \ No newline at end of file + - Fix jail bail amounts not being applied correctly. + - Fix a couple places where the adminbypass mode would not stop admins being treated special for teleports. \ No newline at end of file From 2d4f713ea939335e5264a76fab88e6db79a4b8ae Mon Sep 17 00:00:00 2001 From: LlmDl Date: Mon, 8 Jan 2024 10:55:18 -0600 Subject: [PATCH 20/74] - API: add TownIsTownOverClaimedEvent. - Thrown when Towny asks if a Town is overclaimed, and it is. - Allows other plugins to cancel the event, in which case Towny will tell itself that the town is not overclaimed. --- .../town/TownIsTownOverClaimedEvent.java | 30 +++++++++++++++++++ .../towny/listeners/TownyCustomListener.java | 2 +- .../palmergames/bukkit/towny/object/Town.java | 7 ++++- .../bukkit/towny/tasks/OnPlayerLogin.java | 6 ++-- Towny/src/main/resources/ChangeLog.txt | 5 +++- 5 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 Towny/src/main/java/com/palmergames/bukkit/towny/event/town/TownIsTownOverClaimedEvent.java diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/event/town/TownIsTownOverClaimedEvent.java b/Towny/src/main/java/com/palmergames/bukkit/towny/event/town/TownIsTownOverClaimedEvent.java new file mode 100644 index 0000000000..451701042f --- /dev/null +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/event/town/TownIsTownOverClaimedEvent.java @@ -0,0 +1,30 @@ +package com.palmergames.bukkit.towny.event.town; + +import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; + +import com.palmergames.bukkit.towny.event.CancellableTownyEvent; +import com.palmergames.bukkit.towny.object.Town; + +public class TownIsTownOverClaimedEvent extends CancellableTownyEvent { + private static final HandlerList HANDLER_LIST = new HandlerList(); + private final Town town; + + public TownIsTownOverClaimedEvent(Town town) { + this.town = town; + } + + public Town getTown() { + return town; + } + + public static HandlerList getHandlerList() { + return HANDLER_LIST; + } + + @NotNull + @Override + public HandlerList getHandlers() { + return HANDLER_LIST; + } +} diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyCustomListener.java b/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyCustomListener.java index 19677d686d..6f43206688 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyCustomListener.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyCustomListener.java @@ -222,7 +222,7 @@ public void onTownClaim(TownClaimEvent event) { public void onTownLosesResident(TownRemoveResidentEvent event) { if (!TownySettings.isOverClaimingAllowingStolenLand()) return; - if (event.getTown().getTownBlocks().size() > event.getTown().getMaxTownBlocks()) + if (event.getTown().isOverClaimed()) TownyMessaging.sendPrefixedTownMessage(event.getTown(), Translatable.literal(Colors.Red).append(Translatable.of("msg_warning_your_town_is_overclaimed"))); } diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/object/Town.java b/Towny/src/main/java/com/palmergames/bukkit/towny/object/Town.java index 37082fd93d..235acfc041 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/object/Town.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/object/Town.java @@ -17,6 +17,7 @@ import com.palmergames.bukkit.towny.event.town.TownAddEnemiedTownEvent; import com.palmergames.bukkit.towny.event.town.TownCalculateTownLevelNumberEvent; import com.palmergames.bukkit.towny.event.town.TownConqueredEvent; +import com.palmergames.bukkit.towny.event.town.TownIsTownOverClaimedEvent; import com.palmergames.bukkit.towny.event.town.TownMapColourLocalCalculationEvent; import com.palmergames.bukkit.towny.event.town.TownMapColourNationalCalculationEvent; import com.palmergames.bukkit.towny.event.town.TownMayorChangedEvent; @@ -1241,7 +1242,11 @@ public boolean isOverOutpostLimit() { } public boolean isOverClaimed() { - return !hasUnlimitedClaims() && getTownBlocks().size() > getMaxTownBlocks(); + if (hasUnlimitedClaims() || getTownBlocks().size() <= getMaxTownBlocks()) + return false; + + TownIsTownOverClaimedEvent event = new TownIsTownOverClaimedEvent(this); + return !BukkitTools.isEventCancelled(event); } /** diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/OnPlayerLogin.java b/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/OnPlayerLogin.java index a48565cab0..d1663c01a9 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/OnPlayerLogin.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/OnPlayerLogin.java @@ -154,11 +154,11 @@ public void run() { // Send any warning messages at login. if (TownyEconomyHandler.isActive() && TownySettings.isTaxingDaily()) { final Resident finalResident = resident; - TownyEconomyHandler.economyExecutor().execute(() -> warningMessage(finalResident, town, nation)); + TownyEconomyHandler.economyExecutor().execute(() -> bankWarningMessage(finalResident, town, nation)); } // Send a message warning of being overclaimed while the takeoverclaims feature is enabled. - if (TownySettings.isOverClaimingAllowingStolenLand() && town.getTownBlocks().size() > town.getMaxTownBlocks()) + if (TownySettings.isOverClaimingAllowingStolenLand() && town.isOverClaimed()) TownyMessaging.sendMsg(resident, Translatable.literal(Colors.Red).append(Translatable.of("msg_warning_your_town_is_overclaimed"))); // Send a message warning of ruined status and time until deletion. @@ -217,7 +217,7 @@ private void loginExistingResident(Resident resident) { * @param town Town which the resident is part of. * @param nation Nation which the town is a part of or null. */ - private void warningMessage(Resident resident, Town town, Nation nation) { + private void bankWarningMessage(Resident resident, Town town, Nation nation) { if (town.hasUpkeep()) { double upkeep = TownySettings.getTownUpkeepCost(town); if (upkeep > 0 && !town.getAccount().canPayFromHoldings(upkeep)) { diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index 43ff273cb0..235c910ceb 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9391,4 +9391,7 @@ v0.92.0.11: 0.100.0.20: - Refactor PermHud class. - Fix jail bail amounts not being applied correctly. - - Fix a couple places where the adminbypass mode would not stop admins being treated special for teleports. \ No newline at end of file + - Fix a couple places where the adminbypass mode would not stop admins being treated special for teleports. + - API: add TownIsTownOverClaimedEvent. + - Thrown when Towny asks if a Town is overclaimed, and it is. + - Allows other plugins to cancel the event, in which case Towny will tell itself that the town is not overclaimed. \ No newline at end of file From 6e9c4bac478b94b39ebee1619f6eb72d4c125156 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Mon, 8 Jan 2024 11:50:01 -0600 Subject: [PATCH 21/74] - Add plot costs and plot group information to the /plot perm hud when applicable. - Closes #7173. --- .../bukkit/towny/huds/HUDManager.java | 2 +- .../bukkit/towny/huds/PermHUD.java | 60 +++++++++++++++---- Towny/src/main/resources/ChangeLog.txt | 4 +- Towny/src/main/resources/lang/en-US.yml | 9 +++ 4 files changed, 63 insertions(+), 12 deletions(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/huds/HUDManager.java b/Towny/src/main/java/com/palmergames/bukkit/towny/huds/HUDManager.java index 4f3ffe1a93..0c0e1502e4 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/huds/HUDManager.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/huds/HUDManager.java @@ -142,7 +142,7 @@ public static void removeMapHUDUser(Player player) { } public static boolean isPermHUDActive(Player player) { - return player.getScoreboard().getTeam("plot") != null; + return player.getScoreboard().getTeam(PermHUD.permHudTestKey()) != null; } public static boolean isMapHudActive(Player player) { diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/huds/PermHUD.java b/Towny/src/main/java/com/palmergames/bukkit/towny/huds/PermHUD.java index 5ada061265..bebc609724 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/huds/PermHUD.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/huds/PermHUD.java @@ -1,6 +1,7 @@ package com.palmergames.bukkit.towny.huds; import com.palmergames.bukkit.towny.TownyAPI; +import com.palmergames.bukkit.towny.TownyEconomyHandler; import com.palmergames.bukkit.towny.object.Resident; import com.palmergames.bukkit.towny.object.TownBlock; import com.palmergames.bukkit.towny.object.TownBlockOwner; @@ -37,7 +38,8 @@ public class PermHUD { /* Scoreboards use Teams here is our team names.*/ private static final String HUD_OBJECTIVE = "PERM_HUD_OBJ"; private static final String TEAM_PERMS_TITLE = "permsTitle"; - private static final String PLOT_NAME = "plot_name"; + private static final String TEAM_PLOT_NAME = "plot_name"; + private static final String TEAM_PLOT_COST = "plot_cost"; private static final String TEAM_BUILD = "build"; private static final String TEAM_DESTROY = "destroy"; private static final String TEAM_SWITCH = "switching"; @@ -56,6 +58,10 @@ public static void updatePerms (Player p) { updatePerms(p, WorldCoord.parseWorldCoord(p)); } + public static String permHudTestKey() { + return TEAM_PLOT_NAME; + } + public static void updatePerms(Player p, WorldCoord worldCoord) { Translator translator = Translator.locale(p); String plotName, build, destroy, switching, item, type, pvp, explosions, firespread, mobspawn, title; @@ -81,11 +87,22 @@ public static void updatePerms(Player p, WorldCoord worldCoord) { TownBlock townBlock = worldCoord.getTownBlockOrNull(); TownBlockOwner owner = townBlock.getTownBlockOwner(); + boolean plotGroup = townBlock.hasPlotObjectGroup(); // Displays the name of the owner, and if the owner is a resident the town name as well. title = GOLD + owner.getName() + (townBlock.hasResident() ? " (" + townBlock.getTownOrNull().getName() + ")" : ""); + + // Plot Type type = townBlock.getType().equals(TownBlockType.RESIDENTIAL) ? " " : townBlock.getType().getName(); - plotName = townBlock.getName().isEmpty() ? "" : translator.of("msg_perm_hud_plot_name") + townBlock.getName(); + + // Plot or PlotGroup Name. + plotName = plotGroup && !townBlock.getPlotObjectGroup().getName().isEmpty() + ? townBlock.getPlotObjectGroup().getName() + : !townBlock.getName().isEmpty() ? townBlock.getName() : ""; + plotName = plotName.isEmpty() ? " " : HUDManager.check(DARK_GREEN + translator.of(plotGroup ? "msg_perm_hud_plotgroup_name" : "msg_perm_hud_plot_name") + WHITE + plotName); + + // Plot Price or "No" + String forSale = getPlotPrice(translator, townBlock, plotGroup); TownyPermission tp = townBlock.getPermissions(); boolean residentOwned = owner instanceof Resident; @@ -103,8 +120,9 @@ public static void updatePerms(Player p, WorldCoord worldCoord) { // Set the values to our Scoreboard's teams. board.getObjective(HUD_OBJECTIVE).setDisplayName(HUDManager.check(title)); - board.getTeam(PLOT_NAME).setSuffix(!plotName.isEmpty() ? HUDManager.check(plotName) : " "); + board.getTeam(TEAM_PLOT_NAME).setSuffix(plotName); board.getTeam(TEAM_PLOT_TYPE).setSuffix(type); + board.getTeam(TEAM_PLOT_COST).setSuffix(forSale); board.getTeam(TEAM_BUILD).setSuffix(build); board.getTeam(TEAM_DESTROY).setSuffix(destroy); @@ -115,7 +133,20 @@ public static void updatePerms(Player p, WorldCoord worldCoord) { board.getTeam(TEAM_EXPLOSIONS).setSuffix(explosions); board.getTeam(TEAM_FIRESPREAD).setSuffix(firespread); board.getTeam(TEAM_MOBSPAWNING).setSuffix(mobspawn); + } + private static String getPlotPrice(Translator translator, TownBlock townBlock, boolean plotGroup) { + String forSale = translator.of("msg_perm_hud_no"); + if (TownyEconomyHandler.isActive()) { + forSale = plotGroup && townBlock.getPlotObjectGroup().getPrice() > -1 + ? prettyMoney(townBlock.getPlotObjectGroup().getPrice()) + : townBlock.isForSale() ? prettyMoney(townBlock.getPlotPrice()) : forSale; + } else { + // No economy is active but plots can be put up for sale (they're just free.) + forSale = (plotGroup && townBlock.getPlotObjectGroup().getPrice() > -1) || (!plotGroup && townBlock.isForSale()) + ? translator.of("msg_perm_hud_yes") : forSale; + } + return forSale; } private static String getPermLine(TownyPermission tp, ActionType actionType, boolean residentOwned) { @@ -133,8 +164,9 @@ private static void clearPerms (Player p) { Scoreboard board = p.getScoreboard(); try { board.getObjective(HUD_OBJECTIVE).setDisplayName(HUDManager.check(getFormattedWildernessName(p.getWorld()))); - board.getTeam(PLOT_NAME).setSuffix(" "); + board.getTeam(TEAM_PLOT_NAME).setSuffix(" "); board.getTeam(TEAM_PLOT_TYPE).setSuffix(" "); + board.getTeam(TEAM_PLOT_COST).setSuffix(" "); board.getTeam(TEAM_BUILD).setSuffix(" "); board.getTeam(TEAM_DESTROY).setSuffix(" "); @@ -174,9 +206,10 @@ public static void toggleOn (Player p) { private static void initializeScoreboard(Translator translator, Scoreboard board) { String PERM_HUD_TITLE = GOLD + ""; - String plotName_entry = DARK_GREEN + ""; + String plotName_entry = ""; String keyPlotType_entry = DARK_GREEN + translator.of("msg_perm_hud_plot_type"); - + String forSale_entry = DARK_GREEN + translator.of("msg_perm_hud_plot_for_sale") + GRAY; + String permsTitle_entry = YELLOW + "" + UNDERLINE + translator.of("msg_perm_hud_title"); String build_entry = DARK_GREEN + translator.of("msg_perm_hud_build") + GRAY; String destroy_entry = DARK_GREEN + translator.of("msg_perm_hud_destroy") + GRAY; @@ -200,9 +233,10 @@ private static void initializeScoreboard(Translator translator, Scoreboard board obj.setDisplaySlot(DisplaySlot.SIDEBAR); obj.setDisplayName(PERM_HUD_TITLE); //register teams - Team plotName = board.registerNewTeam(PLOT_NAME); + Team plotName = board.registerNewTeam(TEAM_PLOT_NAME); Team keyPlotType = board.registerNewTeam(TEAM_PLOT_TYPE); - + Team forSaleTitle = board.registerNewTeam(TEAM_PLOT_COST); + Team permsTitle = board.registerNewTeam(TEAM_PERMS_TITLE); Team build = board.registerNewTeam(TEAM_BUILD); Team destroy = board.registerNewTeam(TEAM_DESTROY); @@ -222,6 +256,7 @@ private static void initializeScoreboard(Translator translator, Scoreboard board //add each team as an entry (this sets the prefix to each line of the HUD.) plotName.addEntry(plotName_entry); keyPlotType.addEntry(keyPlotType_entry); + forSaleTitle.addEntry(forSale_entry); permsTitle.addEntry(permsTitle_entry); build.addEntry(build_entry); @@ -240,8 +275,9 @@ private static void initializeScoreboard(Translator translator, Scoreboard board keyAlly.addEntry(keyAlly_entry); //set scores for positioning - obj.getScore(plotName_entry).setScore(15); - obj.getScore(keyPlotType_entry).setScore(14); + obj.getScore(plotName_entry).setScore(16); + obj.getScore(keyPlotType_entry).setScore(15); + obj.getScore(forSale_entry).setScore(14); obj.getScore(permsTitle_entry).setScore(13); obj.getScore(build_entry).setScore(12); obj.getScore(destroy_entry).setScore(11); @@ -256,4 +292,8 @@ private static void initializeScoreboard(Translator translator, Scoreboard board obj.getScore(keyNation_entry).setScore(2); obj.getScore(keyAlly_entry).setScore(1); } + + private static String prettyMoney(double price) { + return TownyEconomyHandler.getFormattedBalance(price); + } } diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index 235c910ceb..a5bf257ee1 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9394,4 +9394,6 @@ v0.92.0.11: - Fix a couple places where the adminbypass mode would not stop admins being treated special for teleports. - API: add TownIsTownOverClaimedEvent. - Thrown when Towny asks if a Town is overclaimed, and it is. - - Allows other plugins to cancel the event, in which case Towny will tell itself that the town is not overclaimed. \ No newline at end of file + - Allows other plugins to cancel the event, in which case Towny will tell itself that the town is not overclaimed. + - Add plot costs and plot group information to the /plot perm hud when applicable. + - Closes #7173. \ No newline at end of file diff --git a/Towny/src/main/resources/lang/en-US.yml b/Towny/src/main/resources/lang/en-US.yml index e8eb21fc11..231061221c 100644 --- a/Towny/src/main/resources/lang/en-US.yml +++ b/Towny/src/main/resources/lang/en-US.yml @@ -2127,6 +2127,15 @@ msg_perm_hud_nation: 'nation' msg_perm_hud_outsider: 'outsider' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Plot: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' + #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. From be2ce2312984fbca4815dcffce05afd32ad43863 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Mon, 8 Jan 2024 16:40:03 -0600 Subject: [PATCH 22/74] Prevent the drops that spawn from problem blocks which can be duped in explosion regenerations. (#7176) * Working implementation preventing the drops that spawn from problem blocks. Many attachable blocks are not given the Attachable interface, making that basically useless. Instead an ItemLists was made up to keep the explodable attachables in check during the ProtectionRegenTasks, which now takes special care to nuke these blocks into Air. Bonus: Adds ability to add ItemLists to ItemLists. Closes #7154 Closes #5689 * Handle doors special case. --- .../towny/object/AbstractRegistryList.java | 21 ++++++++++++++++ .../bukkit/towny/regen/TownyRegenAPI.java | 24 +++++++++++++++++++ .../palmergames/bukkit/util/ItemLists.java | 24 +++++++++++++++++++ 3 files changed, 69 insertions(+) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/object/AbstractRegistryList.java b/Towny/src/main/java/com/palmergames/bukkit/towny/object/AbstractRegistryList.java index 6573dbc47d..0651578fec 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/object/AbstractRegistryList.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/object/AbstractRegistryList.java @@ -2,8 +2,11 @@ import com.palmergames.bukkit.towny.TownyMessaging; import com.palmergames.bukkit.util.BukkitTools; +import com.palmergames.bukkit.util.ItemLists; + import org.bukkit.Bukkit; import org.bukkit.Keyed; +import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.Registry; import org.bukkit.Tag; @@ -174,6 +177,24 @@ public Builder add(@NotNull String... names) { return this; } + /** + * Adds an entire ItemLists contents. + * @param itemList ItemLists to add. + */ + public Builder addItemList(@NotNull ItemLists itemList) { + for (Material mat: itemList.tagged) { + final T match = BukkitTools.matchRegistry(this.registry, mat.name()); + if (match != null) + anyMatchPredicates.add(t -> t.equals(match)); + else { + TownyMessaging.sendDebugMsg("Expected element with name '" + mat.name() + "' was not found in the " + this.clazz.getSimpleName() + " registry."); + anyMatchPredicates.add(t -> false); + } + } + + return this; + } + public Builder filter(@NotNull Predicate predicate) { allMatchPredicates.add(predicate); return this; diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/regen/TownyRegenAPI.java b/Towny/src/main/java/com/palmergames/bukkit/towny/regen/TownyRegenAPI.java index af0bce5f12..a7a687484a 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/regen/TownyRegenAPI.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/regen/TownyRegenAPI.java @@ -9,11 +9,15 @@ import com.palmergames.bukkit.towny.object.WorldCoord; import com.palmergames.bukkit.towny.regen.block.BlockLocation; import com.palmergames.bukkit.towny.tasks.ProtectionRegenTask; +import com.palmergames.bukkit.util.ItemLists; import org.bukkit.Chunk; import org.bukkit.ChunkSnapshot; import org.bukkit.Material; import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.Bisected.Half; +import org.bukkit.block.data.type.Door; import org.bukkit.event.Event; import org.bukkit.event.block.BlockExplodeEvent; import org.bukkit.event.entity.EntityExplodeEvent; @@ -297,11 +301,31 @@ public static boolean beginProtectionRegenTask(Block block, int count, TownyWorl else if (event instanceof BlockExplodeEvent) ((BlockExplodeEvent) event).setYield(0); + // Set extra-special blocks to air so we're not duping items. + handlePeskyBlocks(block); + return true; } return false; } + private static void handlePeskyBlocks(Block block) { + if (ItemLists.EXPLODABLE_ATTACHABLES.contains(block.getType())) { + if (!(block.getBlockData() instanceof Door door)) + // Not a Door, set the pesky block to AIR so an item doesn't drop. + block.setType(Material.AIR); + + // Doors are double-tall and especially pesky. We parse over exploded blocks + // from bottom to top, so if we don't handle doors backwards we regenerate doors + // with only a bottom half. + else if (door.getHalf().equals(Half.TOP)) { + // Remove the bottom along with the top here. + block.getRelative(BlockFace.DOWN).setType(Material.AIR); + block.setType(Material.AIR); + } + } + } + /** * Does a task for this block already exist? * diff --git a/Towny/src/main/java/com/palmergames/bukkit/util/ItemLists.java b/Towny/src/main/java/com/palmergames/bukkit/util/ItemLists.java index 943235973a..b372d7bf31 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/util/ItemLists.java +++ b/Towny/src/main/java/com/palmergames/bukkit/util/ItemLists.java @@ -4,6 +4,7 @@ import java.lang.reflect.Modifier; import java.util.Arrays; import java.util.Collection; +import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -61,6 +62,11 @@ public boolean contains(@NotNull ItemStack itemStack) { */ public static final ItemLists PLANTS = newBuilder().withTag(Tag.REGISTRY_BLOCKS, minecraft("flowers")).add("TALL_GRASS","BROWN_MUSHROOM","RED_MUSHROOM","CACTUS","ALLIUM","AZURE_BLUET","BLUE_ORCHID","CORNFLOWER","DANDELION","LILAC","LILY_OF_THE_VALLEY","ORANGE_TULIP","OXEYE_DAISY","PEONY","PINK_TULIP","POPPY","RED_TULIP","ROSE_BUSH","SUNFLOWER","WHITE_TULIP","WITHER_ROSE","CRIMSON_FUNGUS","LARGE_FERN","PUMPKIN","VINE","TWISTING_VINES_PLANT","WEEPING_VINES_PLANT","NETHER_WART_BLOCK","COCOA","SUGAR_CANE","CRIMSON_ROOTS","WARPED_ROOTS","NETHER_SPROUTS","BIG_DRIPLEAF","SMALL_DRIPLEAF", "TORCHFLOWER").build(); + /** + * List of Flowers. + */ + public static final ItemLists FLOWERS = newBuilder().withTag(Tag.REGISTRY_BLOCKS, minecraft("flowers")).add("ALLIUM","AZURE_BLUET","BLUE_ORCHID","CORNFLOWER","DANDELION","LILAC","LILY_OF_THE_VALLEY","ORANGE_TULIP","OXEYE_DAISY","PEONY","PINK_TULIP","POPPY","RED_TULIP","ROSE_BUSH","SUNFLOWER","WHITE_TULIP","WITHER_ROSE").build(); + /** * List of Ores and Valuable Raw Materials. */ @@ -252,6 +258,24 @@ public boolean contains(@NotNull ItemStack itemStack) { .conditionally(() -> CURRENT_VERSION.isNewerThanOrEquals(MINECRAFT_1_20_3), builder -> builder.add("DECORATED_POT")) .build(); + /** + * List of blocks which, when exploded, will not have their drops set to false, despite our asking. + */ + public static final ItemLists EXPLODABLE_ATTACHABLES = newBuilder() + .add("LANTERN","SOUL_LANTERN") + .add("REDSTONE_WIRE","COMPARATOR","REPEATER","LEVER") + .endsWith("_CARPET") + .endsWith("_BANNER") + .endsWith("_BUTTON") + .endsWith("RAIL") + .endsWith("PUMPKIN_STEM").endsWith("MELON_STEM") + .endsWith("_AMETHYST_BUD").add("AMETHYST_CLUSTER") + .addItemList(FLOWERS) + .addItemList(SAPLINGS) + .addItemList(PRESSURE_PLATES) + .addItemList(WOOD_DOORS) + .build(); + /** * Config-useable material groups. */ From 4b3c645b901e5dc3e89bf01cd88dd73b402e7bdb Mon Sep 17 00:00:00 2001 From: LlmDl Date: Mon, 8 Jan 2024 16:41:25 -0600 Subject: [PATCH 23/74] Add claiming particles. (#7171) * Add claiming particles. * Cleanup class and centre particles. --- .../bukkit/config/ConfigNodes.java | 5 + .../bukkit/towny/TownySettings.java | 4 + .../towny/listeners/TownyCustomListener.java | 7 +- .../bukkit/towny/object/CellSurface.java | 117 ++++++++++++++++++ 4 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 Towny/src/main/java/com/palmergames/bukkit/towny/object/CellSurface.java diff --git a/Towny/src/main/java/com/palmergames/bukkit/config/ConfigNodes.java b/Towny/src/main/java/com/palmergames/bukkit/config/ConfigNodes.java index a5a5350c85..a5f63d6a39 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/config/ConfigNodes.java +++ b/Towny/src/main/java/com/palmergames/bukkit/config/ConfigNodes.java @@ -1000,6 +1000,11 @@ public enum ConfigNodes { "# at the cost of more work setting up. Also, extremely small values will render the caching done useless.", "# Each cell is (town_block_size * town_block_size * height-of-the-world) in size, with height-of-the-world", "# being from the bottom to the top of the build-able world."), + CLAIMING_SHOW_CLAIM_PARTICLES( + "claiming.show_claiming_particles", + "true", + "", + "# When false players will not see the particle flood effect when they claim townblocks."), CLAIMING_MIN_ADJACENT_BLOCKS( "claiming.min_adjacent_blocks", "-1", diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/TownySettings.java b/Towny/src/main/java/com/palmergames/bukkit/towny/TownySettings.java index dbb6e0d52d..1ac847f399 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/TownySettings.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/TownySettings.java @@ -1343,6 +1343,10 @@ public static int getTownBlockSize() { return getInt(ConfigNodes.CLAIMING_TOWN_BLOCK_SIZE); } + public static boolean isShowingClaimParticleEffect() { + return getBoolean(ConfigNodes.CLAIMING_SHOW_CLAIM_PARTICLES); + } + public static boolean isFriendlyFireEnabled() { return getBoolean(ConfigNodes.NWS_FRIENDLY_FIRE_ENABLED); diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyCustomListener.java b/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyCustomListener.java index 6f43206688..729c426752 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyCustomListener.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyCustomListener.java @@ -22,6 +22,7 @@ import com.palmergames.bukkit.towny.event.nation.NationPreTownLeaveEvent; import com.palmergames.bukkit.towny.event.town.TownPreUnclaimCmdEvent; import com.palmergames.bukkit.towny.exceptions.TownyException; +import com.palmergames.bukkit.towny.object.CellSurface; import com.palmergames.bukkit.towny.object.PlayerCache; import com.palmergames.bukkit.towny.object.Resident; import com.palmergames.bukkit.towny.object.SpawnType; @@ -200,12 +201,16 @@ public void onTownUnclaim(TownPreUnclaimCmdEvent event) { /** * Used to warn towns when they're approaching their claim limit, when the - * takeoverclaim feature is enabled + * takeoverclaim feature is enabled, as well as claiming particles. * * @param event TownClaimEvent. */ @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onTownClaim(TownClaimEvent event) { + if (TownySettings.isShowingClaimParticleEffect()) + Towny.getPlugin().getScheduler().runAsync(() -> + CellSurface.getCellSurface(event.getTownBlock().getWorldCoord()).runClaimingParticleOverSurfaceAtPlayer(event.getResident().getPlayer())); + if (!TownySettings.isOverClaimingAllowingStolenLand()) return; if (event.getTown().availableTownBlocks() <= TownySettings.getTownBlockRatio()) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/object/CellSurface.java b/Towny/src/main/java/com/palmergames/bukkit/towny/object/CellSurface.java new file mode 100644 index 0000000000..242260614c --- /dev/null +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/object/CellSurface.java @@ -0,0 +1,117 @@ +package com.palmergames.bukkit.towny.object; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import org.bukkit.Color; +import org.bukkit.Location; +import org.bukkit.Particle; +import org.bukkit.entity.Player; +import com.github.bsideup.jabel.Desugar; +import com.palmergames.bukkit.towny.Towny; +import com.palmergames.bukkit.towny.TownySettings; +import com.palmergames.bukkit.towny.utils.BorderUtil; +import com.palmergames.bukkit.util.BlockUtil; +import com.palmergames.bukkit.util.DrawSmokeTaskFactory; + +public class CellSurface { + private static final long PARTICLE_DELAY = 1L; + private final Particle.DustOptions CLAIMING_PARTICLE = new Particle.DustOptions(Color.LIME, 2); + private final WorldCoord worldCoord; + + public CellSurface(WorldCoord worldCoord) { + this.worldCoord = worldCoord; + } + + public static CellSurface getCellSurface(WorldCoord worldCoord) { + return new CellSurface(worldCoord); + } + + @Desugar + public record BlockPos(int x, int z) {} + + public void runClaimingParticleOverSurfaceAtPlayer(Player player) { + + // Create a Map of rings of BlockPos' which will expand outwards from the Player + // location if they are stood in the WorldCoord (or from the correct edge block + // of the WorldCoord if they are stood outside of it.) + Map> toRender = mapRingsOfClaimParticles(getX(player.getLocation()), getZ(player.getLocation())); + + // Parse over the Map to generate particles on each successive ring with an + // added tick of delay (using the Map's Integer key to determine delay.) + toRender.entrySet().forEach(e -> e.getValue().forEach(pos -> + Towny.getPlugin().getScheduler().runAsyncLater(()-> drawClaimingParticleOnTopOfBlock(player, pos.x, pos.z), e.getKey() * PARTICLE_DELAY))); + + // Splash the edges of the WorldCoord last with extra height to add definition to the boundaries. + long finalDelay = toRender.keySet().size() + 1 * PARTICLE_DELAY; + Towny.getPlugin().getScheduler().runAsyncLater(()-> + BorderUtil.getPlotBorder(worldCoord).runBorderedOnSurface(2, 2, DrawSmokeTaskFactory.showToPlayer(player, Color.GREEN)), finalDelay); + + } + + private Map> mapRingsOfClaimParticles(int startingX, int startingZ) { + Set traveled = new HashSet<>(); + Map> toRender = new HashMap>(); + + BlockPos pos; + Set localRing = new HashSet<>(); + int maxRadius = TownySettings.getTownBlockSize(); + for (int ringNum = 1; ringNum <= maxRadius; ringNum++) { + for (int x = startingX + Math.negateExact(ringNum); x <= startingX + ringNum; x++) { + for (int z = startingZ + Math.negateExact(ringNum); z <= startingZ + ringNum; z++) { + + pos = new BlockPos(x, z); + // We've already covered this in an earlier ring. + if (traveled.contains(pos)) + continue; + + // Mark pos as traveled so we're not re-parsing things (also when it is outside + // of the WorldCoord.) + traveled.add(pos); + + // We might be outside of the WorldCoord. + if (!worldCoord.getBoundingBox().contains(x, 1, z)) + continue; + + localRing.add(pos); + } + } + if (localRing.isEmpty()) + break; + toRender.put(ringNum, new HashSet<>(localRing)); + localRing.clear(); + } + return toRender; + } + + private void drawClaimingParticleOnTopOfBlock(Player player, int x, int z) { + if (!player.isOnline()) + return; + player.spawnParticle(Particle.REDSTONE, getParticleLocation(x, z), 5, CLAIMING_PARTICLE); + } + + private Location getParticleLocation(int x, int z) { + return new Location(worldCoord.getBukkitWorld(), x, BlockUtil.getHighestNonLeafY(worldCoord.getBukkitWorld(), x, z), z).add(0.5, 0.95, 0.5); // centre and raise slightly. + } + + private int getX(Location playerLoc) { + if (WorldCoord.parseWorldCoord(playerLoc).equals(worldCoord)) + return playerLoc.getBlockX(); + + // Player is outside of the WorldCoord, try to match up their X with an X in the WorldCoord or hit the correct corner. + return findSuitableXorZ(playerLoc.getBlockX(), worldCoord.getBoundingBox().getMaxX(), worldCoord.getBoundingBox().getMinX()); + } + + private int getZ(Location playerLoc) { + if (WorldCoord.parseWorldCoord(playerLoc).equals(worldCoord)) + return playerLoc.getBlockZ(); + + // Player is outside of the WorldCoord, try to match up their Z with an Z in the WorldCoord or hit the correct corner. + return findSuitableXorZ(playerLoc.getBlockZ(), worldCoord.getBoundingBox().getMaxZ(), worldCoord.getBoundingBox().getMinZ()); + } + + private int findSuitableXorZ(int player, double max, double min) { + return (int) Math.max(Math.min(player, max), min); + } +} From 1bc2d6acaf6a7ce9a4bbf9d71804ea60731a2eda Mon Sep 17 00:00:00 2001 From: LlmDl Date: Mon, 8 Jan 2024 16:43:31 -0600 Subject: [PATCH 24/74] - Prevent the drops that spawn from problem blocks which can be duped in explosion regenerations. - These were things like carpets, pressureplates and other blocks that attach to blocks. - Closes #7154, #5689. - Add claiming particle effect. - New Config Option: claiming.show_claiming_particles - Default: true - When false players will not see the particle flood effect when they claim townblocks. --- Towny/pom.xml | 2 +- Towny/src/main/resources/ChangeLog.txt | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Towny/pom.xml b/Towny/pom.xml index 80daef8006..a14cdf6dee 100644 --- a/Towny/pom.xml +++ b/Towny/pom.xml @@ -13,7 +13,7 @@ towny jar - 0.100.0.20 + 0.100.0.21 diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index a5bf257ee1..fe43d1e125 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9396,4 +9396,12 @@ v0.92.0.11: - Thrown when Towny asks if a Town is overclaimed, and it is. - Allows other plugins to cancel the event, in which case Towny will tell itself that the town is not overclaimed. - Add plot costs and plot group information to the /plot perm hud when applicable. - - Closes #7173. \ No newline at end of file + - Closes #7173. +0.100.0.21: + - Prevent the drops that spawn from problem blocks which can be duped in explosion regenerations. + - These were things like carpets, pressureplates and other blocks that attach to blocks. + - Closes #7154, #5689. + - Add claiming particle effect. + - New Config Option: claiming.show_claiming_particles + - Default: true + - When false players will not see the particle flood effect when they claim townblocks. \ No newline at end of file From 7510c706c9fe0007887d877aef8c9c0a2271f9ca Mon Sep 17 00:00:00 2001 From: Daniel Trotman <13711345+lexiccn@users.noreply.github.com> Date: Tue, 9 Jan 2024 14:17:59 +0000 Subject: [PATCH 25/74] Command Addon API for /town buy (#7177) * Add TOWN_BUY to CommandType enum * Fix a small typo in thrown exception * Add HelpMenu for /town buy * Add wildcard buy permission and bonus buy permission * Declare the permissions in plugin.yml * Implement the changes to TownCommand to allow for /t buy commands * Remove title and command from /t buy bonus page * Change /town buy permission checks * Add legacy node Similar to how we handled the list permission changing. --------- Co-authored-by: LlmDl --- .../bukkit/towny/TownyCommandAddonAPI.java | 1 + .../bukkit/towny/command/HelpMenu.java | 8 ++++ .../bukkit/towny/command/TownCommand.java | 44 ++++++++++++++----- .../towny/permissions/PermissionNodes.java | 3 +- Towny/src/main/resources/lang/en-US.yml | 2 + Towny/src/main/resources/plugin.yml | 13 +++++- 6 files changed, 57 insertions(+), 14 deletions(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/TownyCommandAddonAPI.java b/Towny/src/main/java/com/palmergames/bukkit/towny/TownyCommandAddonAPI.java index bf21f25f25..c483b9ad34 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/TownyCommandAddonAPI.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/TownyCommandAddonAPI.java @@ -27,6 +27,7 @@ public enum CommandType { NATION_SET, NATION_TOGGLE, TOWN, + TOWN_BUY, TOWN_SET, TOWN_TOGGLE, PLOT, diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/command/HelpMenu.java b/Towny/src/main/java/com/palmergames/bukkit/towny/command/HelpMenu.java index 831a003006..cd709c2aed 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/command/HelpMenu.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/command/HelpMenu.java @@ -676,6 +676,14 @@ protected MenuBuilder load() { } }, + TOWN_BUY { + @Override + protected MenuBuilder load() { + return new MenuBuilder("town buy") + .add("bonus [n]", Translatable.of("town_buy_help")); + } + }, + RESIDENT_HELP { @Override protected MenuBuilder load() { 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 65ec25d0a4..61d49c3ab6 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 @@ -425,7 +425,7 @@ public List onTabComplete(CommandSender sender, Command command, String return townInviteTabComplete(sender, args, player, town); case "buy": if (args.length == 2) - return NameUtil.filterByStart(Collections.singletonList("bonus"), args[1]); + return NameUtil.filterByStart(TownyCommandAddonAPI.getTabCompletes(CommandType.TOWN_BUY, Collections.singletonList("bonus")), args[1]); break; case "toggle": return switch (args.length) { @@ -2440,32 +2440,52 @@ public static void townBuy(CommandSender sender, String[] split, @Nullable Town if (!TownyEconomyHandler.isActive()) throw new TownyException(Translatable.of("msg_err_no_economy")); + if (split.length == 0 || split[0].equalsIgnoreCase("?") || split[0].equalsIgnoreCase("help")) { + HelpMenu.TOWN_BUY.send(sender); + return; + } + if (town == null && sender instanceof Player player) { checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_BUY.getNode()); catchRuinedTown(player); town = getTownFromPlayerOrThrow(player); } + switch(split[0].toLowerCase(Locale.ROOT)) { + case "bonus" -> townBuyBonus(town, split, sender); + default -> { + if (TownyCommandAddonAPI.hasCommand(CommandType.TOWN_BUY, split[0])) { + TownyCommandAddonAPI.getAddonCommand(CommandType.TOWN_BUY, split[0]).execute(sender, "town", split); + } + } + } + } + + /** + * Town tries to buy bonus blocks or checks the cost and increase. + * + * @param town - Towm object. + * @param split - List of command arguments. + * @param sender - Player. + * @throws TownyException - Exception. + */ + public static void townBuyBonus(Town town, String[] split, CommandSender sender) throws TownyException { + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_BUY_BONUS.getNode()); + if (!TownySettings.isSellingBonusBlocks(town) && !TownySettings.isBonusBlocksPerTownLevel()) - throw new TownyException("Config.yml has bonus blocks diabled at max_purchased_blocks: '0' "); + throw new TownyException("Config.yml has bonus blocks disabled at max_purchased_blocks: '0' "); else if (TownySettings.isBonusBlocksPerTownLevel() && TownySettings.getMaxBonusBlocks(town) == 0) throw new TownyException("Config.yml has bonus blocks disabled at town_level section: townBlockBonusBuyAmount: 0"); - - if (split.length == 0 || !split[0].equalsIgnoreCase("bonus")) { - TownyMessaging.sendMessage(sender, ChatTools.formatTitle("/town buy")); + + if (split.length < 2) { String line = Colors.Yellow + "[Purchased Bonus] " + Colors.Green + "Cost: " + Colors.LightGreen + "%s" + Colors.Gray + " | " + Colors.Green + "Max: " + Colors.LightGreen + "%d"; TownyMessaging.sendMessage(sender, String.format(line, prettyMoney(town.getBonusBlockCost()), TownySettings.getMaxPurchasedBlocks(town))); if (TownySettings.getPurchasedBonusBlocksIncreaseValue() != 1.0) TownyMessaging.sendMessage(sender, Colors.Green + "Cost Increase per TownBlock: " + Colors.LightGreen + "+" + new DecimalFormat("##.##%").format(TownySettings.getPurchasedBonusBlocksIncreaseValue()-1)); - TownyMessaging.sendMessage(sender, ChatTools.formatCommand("", "/town buy", "bonus [n]", "")); return; } - - // They have used `/t buy bonus`, check that they have specified an amount to purchase. - if (split.length == 2) - townBuyBonusTownBlocks(town, MathUtil.getIntOrThrow(split[1].trim()), sender); - else - throw new TownyException(Translatable.of("msg_must_specify_amnt", "/town buy bonus")); + + townBuyBonusTownBlocks(town, MathUtil.getIntOrThrow(split[1].trim()), sender); } /** diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/permissions/PermissionNodes.java b/Towny/src/main/java/com/palmergames/bukkit/towny/permissions/PermissionNodes.java index 32d892e04c..9790300692 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/permissions/PermissionNodes.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/permissions/PermissionNodes.java @@ -122,7 +122,8 @@ public enum PermissionNodes { TOWNY_COMMAND_TOWN_PLOTS("towny.command.town.plots"), TOWNY_COMMAND_TOWN_PURGE("towny.command.town.purge"), TOWNY_COMMAND_TOWN_MERGE("towny.command.town.merge"), - TOWNY_COMMAND_TOWN_BUY("towny.command.town.buy"), + TOWNY_COMMAND_TOWN_BUY("towny.command.town.buy.*"), + TOWNY_COMMAND_TOWN_BUY_BONUS("towny.command.town.buy.bonus"), TOWNY_COMMAND_TOWN_JAIL("towny.command.town.jail"), TOWNY_COMMAND_TOWN_JAIL_LIST("towny.command.town.jail.list"), TOWNY_COMMAND_TOWN_UNJAIL("towny.command.town.unjail"), diff --git a/Towny/src/main/resources/lang/en-US.yml b/Towny/src/main/resources/lang/en-US.yml index 231061221c..e80ba96382 100644 --- a/Towny/src/main/resources/lang/en-US.yml +++ b/Towny/src/main/resources/lang/en-US.yml @@ -155,6 +155,8 @@ town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." + mayor_help_3: 'Claim area not attached to town' mayor_help_4: 'Claim around you to a radius of X' mayor_help_5: 'Claim to the maximum radius' diff --git a/Towny/src/main/resources/plugin.yml b/Towny/src/main/resources/plugin.yml index 240434f3fb..0e853286ac 100644 --- a/Towny/src/main/resources/plugin.yml +++ b/Towny/src/main/resources/plugin.yml @@ -357,7 +357,7 @@ permissions: default: false children: towny.command.town.bankhistory: true - towny.command.town.buy: true + towny.command.town.buy.*: true towny.command.town.claim.*: true towny.command.town.delete: true towny.command.town.deposit: true @@ -517,6 +517,17 @@ permissions: towny.command.town.deposit.othertown: description: User can deposit money into another town bank using /t deposit amount townname. default: false + towny.command.town.buy: + description: Users are able to use the /t buy bonus command, for legacy townyperms file support. Replacing this node with towny.command.town.buy.bonus is recommended. + default: false + children: + towny.command.town.buy.bonus: true + + towny.command.town.buy.*: + description: User can access all commands related to buying for the town. + default: false + children: + towny.command.town.buy.bonus: true # Plot command permissions towny.command.plot.*: From eb36c8c5fe6f7428aaac1efe6d9598498e0239d8 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Tue, 9 Jan 2024 08:24:04 -0600 Subject: [PATCH 26/74] - API: New CommandAddonAPI for /town buy, courtesy of lexiccn with PR #7177. (First-Time Contributor!) - It is now possible for other plugins to add subcommands to the /town buy command. - Closes #6379. - New Permission Node: towny.command.town.buy.* - Child Nodes: - towny.command.town.buy.bonus - Allows mayors to use /t buy bonus. - No change required in your townyperms.yml, the old node towny.command.town.buy will continue to point to towny.command.town.buy.bonus, although it is recommended you change over to using the new towny.command.town.buy.* instead. --- Towny/src/main/resources/ChangeLog.txt | 11 ++++++++++- Towny/src/main/resources/plugin.yml | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index fe43d1e125..4d02658b69 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9404,4 +9404,13 @@ v0.92.0.11: - Add claiming particle effect. - New Config Option: claiming.show_claiming_particles - Default: true - - When false players will not see the particle flood effect when they claim townblocks. \ No newline at end of file + - When false players will not see the particle flood effect when they claim townblocks. + - API: New CommandAddonAPI for /town buy, courtesy of lexiccn with PR #7177. (First-Time Contributor!) + - It is now possible for other plugins to add subcommands to the /town buy command. + - Closes #6379. + - New Permission Node: towny.command.town.buy.* + - Child Nodes: + - towny.command.town.buy.bonus - Allows mayors to use /t buy bonus. + - No change required in your townyperms.yml, + the old node towny.command.town.buy will continue to point to towny.command.town.buy.bonus, + although it is recommended you change over to using the new towny.command.town.buy.* instead. \ No newline at end of file diff --git a/Towny/src/main/resources/plugin.yml b/Towny/src/main/resources/plugin.yml index 0e853286ac..c6e998c38b 100644 --- a/Towny/src/main/resources/plugin.yml +++ b/Towny/src/main/resources/plugin.yml @@ -529,7 +529,7 @@ permissions: children: towny.command.town.buy.bonus: true - # Plot command permissions + # Plot command permissions towny.command.plot.*: description: User can access all town related commands. default: false From 64fb8edba3586ff987fc70576674285d5fcc49b1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Jan 2024 08:24:52 -0600 Subject: [PATCH 27/74] Bump com.github.seeseemelk:MockBukkit-v1.20 from 3.58.0 to 3.60.0 (#7175) Bumps [com.github.seeseemelk:MockBukkit-v1.20](https://github.com/MockBukkit/MockBukkit) from 3.58.0 to 3.60.0. - [Commits](https://github.com/MockBukkit/MockBukkit/compare/v3.58.0...v3.60.0) --- updated-dependencies: - dependency-name: com.github.seeseemelk:MockBukkit-v1.20 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Towny/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Towny/pom.xml b/Towny/pom.xml index a14cdf6dee..1ff9a3801b 100644 --- a/Towny/pom.xml +++ b/Towny/pom.xml @@ -256,7 +256,7 @@ com.github.seeseemelk MockBukkit-v1.20 - 3.58.0 + 3.60.0 test From 65423fcc22a2bc44328a52e7cb43df76bbb4ac53 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Jan 2024 08:26:11 -0600 Subject: [PATCH 28/74] Bump net.coreprotect:coreprotect from 22.2 to 22.3 (#7174) Bumps net.coreprotect:coreprotect from 22.2 to 22.3. --- updated-dependencies: - dependency-name: net.coreprotect:coreprotect dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Towny/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Towny/pom.xml b/Towny/pom.xml index 1ff9a3801b..d4c11e986e 100644 --- a/Towny/pom.xml +++ b/Towny/pom.xml @@ -250,7 +250,7 @@ net.coreprotect coreprotect - 22.2 + 22.3 provided From c140cbb8508b4d01eaed036b44fa1035ee388fca Mon Sep 17 00:00:00 2001 From: LlmDl Date: Tue, 9 Jan 2024 08:27:30 -0600 Subject: [PATCH 29/74] - Bump com.github.seeseemelk:MockBukkit-v1.20 from 3.58.0 to 3.60.0. - Bump net.coreprotect:coreprotect from 22.2 to 22.3. --- Towny/src/main/resources/ChangeLog.txt | 4 +++- Towny/src/main/resources/plugin.yml | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index 4d02658b69..e4043e99fe 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9413,4 +9413,6 @@ v0.92.0.11: - towny.command.town.buy.bonus - Allows mayors to use /t buy bonus. - No change required in your townyperms.yml, the old node towny.command.town.buy will continue to point to towny.command.town.buy.bonus, - although it is recommended you change over to using the new towny.command.town.buy.* instead. \ No newline at end of file + although it is recommended you change over to using the new towny.command.town.buy.* instead. + - Bump com.github.seeseemelk:MockBukkit-v1.20 from 3.58.0 to 3.60.0. + - Bump net.coreprotect:coreprotect from 22.2 to 22.3. \ No newline at end of file diff --git a/Towny/src/main/resources/plugin.yml b/Towny/src/main/resources/plugin.yml index c6e998c38b..aa437458e6 100644 --- a/Towny/src/main/resources/plugin.yml +++ b/Towny/src/main/resources/plugin.yml @@ -517,11 +517,12 @@ permissions: towny.command.town.deposit.othertown: description: User can deposit money into another town bank using /t deposit amount townname. default: false + towny.command.town.buy: description: Users are able to use the /t buy bonus command, for legacy townyperms file support. Replacing this node with towny.command.town.buy.bonus is recommended. default: false children: - towny.command.town.buy.bonus: true + towny.command.town.buy.bonus: true towny.command.town.buy.*: description: User can access all commands related to buying for the town. From 397350aa9cc0344599e61add2c4e30909fdd2f97 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Tue, 9 Jan 2024 08:29:27 -0600 Subject: [PATCH 30/74] New Crowdin updates (#7172) * New translations en-us.yml (Lithuanian) * Update source file en-US.yml * New translations en-us.yml (Chinese Simplified) * New translations en-us.yml (German) * New translations en-us.yml (Romanian) * New translations en-us.yml (French) * New translations en-us.yml (Spanish) * New translations en-us.yml (Bulgarian) * New translations en-us.yml (Czech) * New translations en-us.yml (Danish) * New translations en-us.yml (Hebrew) * New translations en-us.yml (Italian) * New translations en-us.yml (Japanese) * New translations en-us.yml (Korean) * New translations en-us.yml (Lithuanian) * New translations en-us.yml (Dutch) * New translations en-us.yml (Norwegian) * New translations en-us.yml (Polish) * New translations en-us.yml (Portuguese) * New translations en-us.yml (Russian) * New translations en-us.yml (Albanian) * New translations en-us.yml (Swedish) * New translations en-us.yml (Turkish) * New translations en-us.yml (Ukrainian) * New translations en-us.yml (Chinese Traditional) * New translations en-us.yml (Vietnamese) * New translations en-us.yml (Portuguese, Brazilian) * New translations en-us.yml (Indonesian) * New translations en-us.yml (Spanish, Argentina) * New translations en-us.yml (Spanish, Chile) * New translations en-us.yml (Spanish, Mexico) * New translations en-us.yml (Spanish, Uruguay) * New translations en-us.yml (Spanish, Venezuela) * New translations en-us.yml (Spanish, Ecuador) * New translations en-us.yml (Thai) * New translations en-us.yml (Azerbaijani) * New translations en-us.yml (English, United Kingdom) * New translations en-us.yml (Tagalog) * New translations en-us.yml (Pirate English) * New translations en-us.yml (Serbian (Latin)) * New translations en-us.yml (English (upside down)) * New translations en-us.yml (LOLCAT) * New translations en-us.yml (Classical Chinese) --- Towny/src/main/resources/lang/az-AZ.yml | 8 +++ Towny/src/main/resources/lang/bg-BG.yml | 8 +++ Towny/src/main/resources/lang/cs-CZ.yml | 8 +++ Towny/src/main/resources/lang/da-DK.yml | 8 +++ Towny/src/main/resources/lang/de-DE.yml | 8 +++ Towny/src/main/resources/lang/en-GB.yml | 8 +++ Towny/src/main/resources/lang/en-PT.yml | 8 +++ Towny/src/main/resources/lang/en-UD.yml | 8 +++ Towny/src/main/resources/lang/es-AR.yml | 8 +++ Towny/src/main/resources/lang/es-CL.yml | 8 +++ Towny/src/main/resources/lang/es-EC.yml | 8 +++ Towny/src/main/resources/lang/es-ES.yml | 8 +++ Towny/src/main/resources/lang/es-MX.yml | 8 +++ Towny/src/main/resources/lang/es-UY.yml | 8 +++ Towny/src/main/resources/lang/es-VE.yml | 8 +++ Towny/src/main/resources/lang/fr-FR.yml | 8 +++ Towny/src/main/resources/lang/he-IL.yml | 8 +++ Towny/src/main/resources/lang/id-ID.yml | 8 +++ Towny/src/main/resources/lang/it-IT.yml | 8 +++ Towny/src/main/resources/lang/ja-JP.yml | 8 +++ Towny/src/main/resources/lang/ko-KR.yml | 8 +++ Towny/src/main/resources/lang/lol-US.yml | 8 +++ Towny/src/main/resources/lang/lt-LT.yml | 72 +++++++++++++----------- Towny/src/main/resources/lang/lzh.yml | 8 +++ Towny/src/main/resources/lang/nl-NL.yml | 8 +++ Towny/src/main/resources/lang/no-NO.yml | 8 +++ Towny/src/main/resources/lang/pl-PL.yml | 8 +++ Towny/src/main/resources/lang/pt-BR.yml | 8 +++ Towny/src/main/resources/lang/pt-PT.yml | 8 +++ Towny/src/main/resources/lang/ro-RO.yml | 8 +++ Towny/src/main/resources/lang/ru-RU.yml | 8 +++ Towny/src/main/resources/lang/sq-AL.yml | 8 +++ Towny/src/main/resources/lang/sr-CS.yml | 8 +++ Towny/src/main/resources/lang/sv-SE.yml | 8 +++ Towny/src/main/resources/lang/th-TH.yml | 8 +++ Towny/src/main/resources/lang/tl-PH.yml | 8 +++ Towny/src/main/resources/lang/tr-TR.yml | 8 +++ Towny/src/main/resources/lang/uk-UA.yml | 8 +++ Towny/src/main/resources/lang/vi-VN.yml | 8 +++ Towny/src/main/resources/lang/zh-CN.yml | 8 +++ Towny/src/main/resources/lang/zh-TW.yml | 8 +++ 41 files changed, 360 insertions(+), 32 deletions(-) diff --git a/Towny/src/main/resources/lang/az-AZ.yml b/Towny/src/main/resources/lang/az-AZ.yml index 29b416dffe..fbea7b983a 100644 --- a/Towny/src/main/resources/lang/az-AZ.yml +++ b/Towny/src/main/resources/lang/az-AZ.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'nation' msg_perm_hud_outsider: 'outsider' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Plot: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'The town %s has had their townlevel set to %s.' diff --git a/Towny/src/main/resources/lang/bg-BG.yml b/Towny/src/main/resources/lang/bg-BG.yml index 7ecafca8fc..7b43b0ed0a 100644 --- a/Towny/src/main/resources/lang/bg-BG.yml +++ b/Towny/src/main/resources/lang/bg-BG.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'nation' msg_perm_hud_outsider: 'outsider' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Plot: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'The town %s has had their townlevel set to %s.' diff --git a/Towny/src/main/resources/lang/cs-CZ.yml b/Towny/src/main/resources/lang/cs-CZ.yml index 20b54a01f5..cf327c6ae3 100644 --- a/Towny/src/main/resources/lang/cs-CZ.yml +++ b/Towny/src/main/resources/lang/cs-CZ.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'nation' msg_perm_hud_outsider: 'outsider' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Plot: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'The town %s has had their townlevel set to %s.' diff --git a/Towny/src/main/resources/lang/da-DK.yml b/Towny/src/main/resources/lang/da-DK.yml index c795e1dfb4..a9838faef7 100644 --- a/Towny/src/main/resources/lang/da-DK.yml +++ b/Towny/src/main/resources/lang/da-DK.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'nation' msg_perm_hud_outsider: 'Uvedkommende' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Grund: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'Byen %s har fået deres byniveau sat til %s.' diff --git a/Towny/src/main/resources/lang/de-DE.yml b/Towny/src/main/resources/lang/de-DE.yml index 1a33c2b2bd..4bd1b85ad2 100644 --- a/Towny/src/main/resources/lang/de-DE.yml +++ b/Towny/src/main/resources/lang/de-DE.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'nation' msg_perm_hud_outsider: 'außenseiter' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Grundstück: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'In der Stadt %s wurde das Stadtlevel auf %s gesetzt.' diff --git a/Towny/src/main/resources/lang/en-GB.yml b/Towny/src/main/resources/lang/en-GB.yml index 2241dd6f8e..a79fdfff5f 100644 --- a/Towny/src/main/resources/lang/en-GB.yml +++ b/Towny/src/main/resources/lang/en-GB.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'nation' msg_perm_hud_outsider: 'outsider' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Plot: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'The town %s has had their townlevel set to %s.' diff --git a/Towny/src/main/resources/lang/en-PT.yml b/Towny/src/main/resources/lang/en-PT.yml index aaddecc330..690ba0cac1 100644 --- a/Towny/src/main/resources/lang/en-PT.yml +++ b/Towny/src/main/resources/lang/en-PT.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'nation' msg_perm_hud_outsider: 'outsider' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Plot: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'The town %s has had their townlevel set to %s.' diff --git a/Towny/src/main/resources/lang/en-UD.yml b/Towny/src/main/resources/lang/en-UD.yml index 6b61b1c220..0e833ef726 100644 --- a/Towny/src/main/resources/lang/en-UD.yml +++ b/Towny/src/main/resources/lang/en-UD.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'nation' msg_perm_hud_outsider: 'outsider' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Plot: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'The town %s has had their townlevel set to %s.' diff --git a/Towny/src/main/resources/lang/es-AR.yml b/Towny/src/main/resources/lang/es-AR.yml index f6a050ae6a..839bc3b7a0 100644 --- a/Towny/src/main/resources/lang/es-AR.yml +++ b/Towny/src/main/resources/lang/es-AR.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'nación' msg_perm_hud_outsider: 'forastero' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Parcela: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'La ciudad %s ha establecido su nivel de ciudad en %s.' diff --git a/Towny/src/main/resources/lang/es-CL.yml b/Towny/src/main/resources/lang/es-CL.yml index 5f4b82c098..2a5d3582b6 100644 --- a/Towny/src/main/resources/lang/es-CL.yml +++ b/Towny/src/main/resources/lang/es-CL.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'nación' msg_perm_hud_outsider: 'extranjero' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Parcela: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'Se estableció el nivel de ciudad de %s en %s.' diff --git a/Towny/src/main/resources/lang/es-EC.yml b/Towny/src/main/resources/lang/es-EC.yml index 65322a65ae..591bb50e15 100644 --- a/Towny/src/main/resources/lang/es-EC.yml +++ b/Towny/src/main/resources/lang/es-EC.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'nación' msg_perm_hud_outsider: 'forastero' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Parcela: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'La ciudad %s ha establecido su nivel de ciudad en %s.' diff --git a/Towny/src/main/resources/lang/es-ES.yml b/Towny/src/main/resources/lang/es-ES.yml index bb7d17d97a..5d5d4e6d3b 100644 --- a/Towny/src/main/resources/lang/es-ES.yml +++ b/Towny/src/main/resources/lang/es-ES.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'nación' msg_perm_hud_outsider: 'forastero' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Parcela: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'La ciudad %s ha establecido su nivel de ciudad en %s.' diff --git a/Towny/src/main/resources/lang/es-MX.yml b/Towny/src/main/resources/lang/es-MX.yml index e64133b897..ecab186628 100644 --- a/Towny/src/main/resources/lang/es-MX.yml +++ b/Towny/src/main/resources/lang/es-MX.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'nación' msg_perm_hud_outsider: 'forastero' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Parcela: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'La ciudad %s ha establecido su nivel de ciudad en %s.' diff --git a/Towny/src/main/resources/lang/es-UY.yml b/Towny/src/main/resources/lang/es-UY.yml index 65322a65ae..591bb50e15 100644 --- a/Towny/src/main/resources/lang/es-UY.yml +++ b/Towny/src/main/resources/lang/es-UY.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'nación' msg_perm_hud_outsider: 'forastero' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Parcela: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'La ciudad %s ha establecido su nivel de ciudad en %s.' diff --git a/Towny/src/main/resources/lang/es-VE.yml b/Towny/src/main/resources/lang/es-VE.yml index 65322a65ae..591bb50e15 100644 --- a/Towny/src/main/resources/lang/es-VE.yml +++ b/Towny/src/main/resources/lang/es-VE.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'nación' msg_perm_hud_outsider: 'forastero' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Parcela: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'La ciudad %s ha establecido su nivel de ciudad en %s.' diff --git a/Towny/src/main/resources/lang/fr-FR.yml b/Towny/src/main/resources/lang/fr-FR.yml index bda8326fe5..3803c69e6d 100644 --- a/Towny/src/main/resources/lang/fr-FR.yml +++ b/Towny/src/main/resources/lang/fr-FR.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'pays' msg_perm_hud_outsider: 'étrangers' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Parcelles: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'La ville %s a vu son niveau de ville fixé à %s.' diff --git a/Towny/src/main/resources/lang/he-IL.yml b/Towny/src/main/resources/lang/he-IL.yml index 099594b700..95fc27204b 100644 --- a/Towny/src/main/resources/lang/he-IL.yml +++ b/Towny/src/main/resources/lang/he-IL.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'nation' msg_perm_hud_outsider: 'outsider' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Plot: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'The town %s has had their townlevel set to %s.' diff --git a/Towny/src/main/resources/lang/id-ID.yml b/Towny/src/main/resources/lang/id-ID.yml index 8364e22853..066b9718f7 100644 --- a/Towny/src/main/resources/lang/id-ID.yml +++ b/Towny/src/main/resources/lang/id-ID.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'negara' msg_perm_hud_outsider: 'orang luar' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Lahan: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'Kota %s telah mengatur townlevel mereka ke %s.' diff --git a/Towny/src/main/resources/lang/it-IT.yml b/Towny/src/main/resources/lang/it-IT.yml index ea63717694..9588f17b62 100644 --- a/Towny/src/main/resources/lang/it-IT.yml +++ b/Towny/src/main/resources/lang/it-IT.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'nazione' msg_perm_hud_outsider: 'esterno' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Lotti: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'La città %s ha il suo livello di città impostato a %s.' diff --git a/Towny/src/main/resources/lang/ja-JP.yml b/Towny/src/main/resources/lang/ja-JP.yml index c873834c47..746da44ba7 100644 --- a/Towny/src/main/resources/lang/ja-JP.yml +++ b/Towny/src/main/resources/lang/ja-JP.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: '国' msg_perm_hud_outsider: 'outsider' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'プロット: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: '%sは町のレベルを%sに設定しました。' diff --git a/Towny/src/main/resources/lang/ko-KR.yml b/Towny/src/main/resources/lang/ko-KR.yml index 3b73dc8cad..762287f192 100644 --- a/Towny/src/main/resources/lang/ko-KR.yml +++ b/Towny/src/main/resources/lang/ko-KR.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: '국가' msg_perm_hud_outsider: '외부인' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Plot: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'The town %s has had their townlevel set to %s.' diff --git a/Towny/src/main/resources/lang/lol-US.yml b/Towny/src/main/resources/lang/lol-US.yml index 34a1db385a..11ad7ad77f 100644 --- a/Towny/src/main/resources/lang/lol-US.yml +++ b/Towny/src/main/resources/lang/lol-US.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'nation' msg_perm_hud_outsider: 'outsider' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Plot: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'The town %s has had their townlevel set to %s.' diff --git a/Towny/src/main/resources/lang/lt-LT.yml b/Towny/src/main/resources/lang/lt-LT.yml index 05d9329567..b518562e53 100644 --- a/Towny/src/main/resources/lang/lt-LT.yml +++ b/Towny/src/main/resources/lang/lt-LT.yml @@ -1426,22 +1426,22 @@ msg_town_merge_cost_withdraw: 'Miestų susijungimas kainuoja' msg_town_merge_transaction_reason: 'Miestų susijungimas' towny_prices_town_merge: '&e[Merging] &2Base Cost: &a%s &8| &2Per Plot: &a%s' #Added in 0.101 -msg_err_nation_not_allied_with: '&cYour nation isn''t allied with %s.' -msg_err_nation_not_enemies_with: '&cYour nation isn''t enemies with %s.' -msg_err_nation_already_enemies_with: '&cYour nation is already enemies with %s.' -msg_err_ally_already_requested: '&cYou have already requested to ally with %s.' -msg_err_nation_not_allied_with_2: '&c%s isn''t allied with %s.' -msg_err_nation_not_enemies_with_2: '&c%s isn''t enemies with %s.' -msg_err_nation_already_allied_with_2: '&c%s is already allied with %s.' -msg_err_nation_already_enemies_with_2: '&c%s is already enemies with %s.' -msg_ta_allies_enemies_updated: '&bAllies/Enemies updated for %s.' +msg_err_nation_not_allied_with: '&cJūsų valstybė nėra %s sąjungininkė.' +msg_err_nation_not_enemies_with: '&cJūsų valstybė nėra %s priešė.' +msg_err_nation_already_enemies_with: '&cJūsų valstybė jau yra %s priešė.' +msg_err_ally_already_requested: '&cJūs jau paprašėte %s sudaryti aljansą.' +msg_err_nation_not_allied_with_2: '&c%s nėra %s sąjungininkė.' +msg_err_nation_not_enemies_with_2: '&c%s nėra %s priešė.' +msg_err_nation_already_allied_with_2: '&c%s jau yra %s sąjungininkė.' +msg_err_nation_already_enemies_with_2: '&c%s jau yra %s priešė.' +msg_ta_allies_enemies_updated: '&b%s atnaujinti sąjungininkai/priešai.' #Added in 0.102 -towny_map_detailed_information: '&2Click to see detailed plot information.' +towny_map_detailed_information: '&2Spustelėkite norėdami pamatyti detalesnę sklypo informaciją.' msg_err_nation_capital_too_many_residents: '&cThe current capital city has too many residents to be replaced by %s.' -msg_deleting_nation_will_result_in_losing_residents: '&cWarning: Deleting your nation will mean your town is over the population limit of %d, resulting in the removal of %d residents.' +msg_deleting_nation_will_result_in_losing_residents: '&cĮspėjimas: Jūsų valstybės panaikinimas reikš, jog Jūsų miestas yra viršys gyventojų skaičiaus limitą (%d), todėl bus pašalinti %d gyventojai.' #Added in 0.103 -msg_command_blocked_inside_towns: '&cYou cannot use that command inside towns.' -msg_command_limited: 'You can only use that command inside your own plots.' +msg_command_blocked_inside_towns: '&cJūs negalite naudoti šios komandos būdami miestuose.' +msg_command_limited: 'Jūs galite naudoti šią komandą tik savo sklypuose.' #Added in 0.104 #Don't add a space to the end please msg_plot_perm_claimed_at: 'Claimed at:' @@ -1451,27 +1451,27 @@ msg_regenerations_use_x_in_all_worlds: 'Regenerations turned %s in all worlds.' #Added in 0.106 msg_command_outsider_blocked: 'You cannot run that command because you don''t live in %s.' #Added in 0.107 -msg_jailed_for_x_hours: ' for %s hours.' -msg_err_this_jail_has_no_cells: 'This jail has no cells.' -msg_err_no_cell_found_at_this_location: 'No jail cell found at this location.' -msg_jail_cell_set: 'Jail cell set.' -msg_jail_cell_removed: 'Jail cell removed.' -msg_err_resident_is_already_jailed: '%s is already jailed' -msg_err_the_town_does_not_have_that_many_jails: 'The town does not have that many jails.' -msg_err_that_jail_plot_does_not_have_that_many_cells: 'That jail plot does not have that many cells.' -msg_primary_jail_set_for_town: 'Your town''s primary jail has been set.' -msg_x_has_been_freed_from_x: '%s has been freed from jail %s' -msg_you_have_been_jailed: 'You have been jailed.' +msg_jailed_for_x_hours: ' %s valandoms.' +msg_err_this_jail_has_no_cells: 'Šis kalėjimas neturi kamerų.' +msg_err_no_cell_found_at_this_location: 'Šioje vietoje nepavyko rasti kalėjimo kameros.' +msg_jail_cell_set: 'Kalėjimo kamera nustatyta.' +msg_jail_cell_removed: 'Kalėjimo kamera panaikinta.' +msg_err_resident_is_already_jailed: '%s jau yra įkalintas' +msg_err_the_town_does_not_have_that_many_jails: 'Šis miestas neturi tiek daug kalėjimų.' +msg_err_that_jail_plot_does_not_have_that_many_cells: 'Tas kalėjimo sklypas neturi tiek daug kamerų.' +msg_primary_jail_set_for_town: 'Jūsų miesto pagrindinis kalėjimas buvo nustatytas.' +msg_x_has_been_freed_from_x: '%s buvo paleistas iš kalėjimo %s' +msg_you_have_been_jailed: 'Jūs buvote įkalintas.' msg_run_to_the_wilderness_or_wait_for_a_jailbreak: 'Run to the wilderness or wait for a jailbreak.' -msg_err_player_is_not_jailed: 'That player is not jailed.' -msg_you_have_paid_bail: 'You have paid bail.' +msg_err_player_is_not_jailed: 'Tas žaidėjas nėra įkalintas.' +msg_you_have_paid_bail: 'Jūs sumokėjote užstatą.' msg_you_have_been_freed_via_jailbreak: 'There''s been a jailbreak, you are free!' -msg_you_have_served_your_sentence_and_are_free: 'You have served your jail sentence and are free.' -msg_x_has_served_their_sentence_and_is_free: '%s has served their jail sentence and is free.' -msg_you've_been_jailed_for_x_hours: 'You''ve been jailed for %s hours.' -msg_you_are_being_sent_to_jail: 'You are being sent to jail.' -msg_err_you_cannot_remove_the_last_cell: 'You cannot remove the last jail cell in this jail, until another cell is added' -msg_do_not_log_out_while_waiting_to_be_teleported: 'Do not log out before being teleported to jail, it would be fatal.' +msg_you_have_served_your_sentence_and_are_free: 'Jūs atlikote savo laisvės atėmimo bausmę ir dabar esate laisvas.' +msg_x_has_served_their_sentence_and_is_free: '%s atliko savo laisvės atėmimo bausmę ir dabar yra laisvas.' +msg_you've_been_jailed_for_x_hours: 'Jūs buvote įkalintas %s valandoms.' +msg_you_are_being_sent_to_jail: 'Jūs esate siunčiamas į kalėjimą.' +msg_err_you_cannot_remove_the_last_cell: 'Jūs negalite panaikinti paskutinės kameros šiame kalėjime, kol nepridėjote kitos' +msg_do_not_log_out_while_waiting_to_be_teleported: 'Neatsijunkite prieš nusiunčiant Jus į kalėjimą, tai būtų pražūtinga.' jail_plu: 'Kalėjimai' jail_sing: 'Kalėjimas' msg_resident_has_not_played_long_enough_to_be_jailed: '%s hasn''t played long enough to be jailed, wait another %s' @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'valstybė' msg_perm_hud_outsider: 'pašalietis' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Sklypas: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'The town %s has had their townlevel set to %s.' diff --git a/Towny/src/main/resources/lang/lzh.yml b/Towny/src/main/resources/lang/lzh.yml index d0c487bb88..c14195f599 100644 --- a/Towny/src/main/resources/lang/lzh.yml +++ b/Towny/src/main/resources/lang/lzh.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: '城邦' msg_perm_hud_outsider: 'outsider' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Plot: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'The town %s has had their townlevel set to %s.' diff --git a/Towny/src/main/resources/lang/nl-NL.yml b/Towny/src/main/resources/lang/nl-NL.yml index ae69a67510..5da64edc86 100644 --- a/Towny/src/main/resources/lang/nl-NL.yml +++ b/Towny/src/main/resources/lang/nl-NL.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'nation' msg_perm_hud_outsider: 'outsider' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Plot: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'The town %s has had their townlevel set to %s.' diff --git a/Towny/src/main/resources/lang/no-NO.yml b/Towny/src/main/resources/lang/no-NO.yml index d40086b622..5c22fd2e74 100644 --- a/Towny/src/main/resources/lang/no-NO.yml +++ b/Towny/src/main/resources/lang/no-NO.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'nasjon' msg_perm_hud_outsider: 'utsider' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Tomt: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'Byen %s har fått bynivået sitt satt til %s.' diff --git a/Towny/src/main/resources/lang/pl-PL.yml b/Towny/src/main/resources/lang/pl-PL.yml index b4ed60b407..6f4d164b1d 100644 --- a/Towny/src/main/resources/lang/pl-PL.yml +++ b/Towny/src/main/resources/lang/pl-PL.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'nacja' msg_perm_hud_outsider: 'obcy' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Działka: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'Poziom miasta %s został ustawiony na %s.' diff --git a/Towny/src/main/resources/lang/pt-BR.yml b/Towny/src/main/resources/lang/pt-BR.yml index 5018cac060..1130350f9c 100644 --- a/Towny/src/main/resources/lang/pt-BR.yml +++ b/Towny/src/main/resources/lang/pt-BR.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'nation' msg_perm_hud_outsider: 'outsider' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Plot: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'The town %s has had their townlevel set to %s.' diff --git a/Towny/src/main/resources/lang/pt-PT.yml b/Towny/src/main/resources/lang/pt-PT.yml index fae5b45a85..bc0a7d9980 100644 --- a/Towny/src/main/resources/lang/pt-PT.yml +++ b/Towny/src/main/resources/lang/pt-PT.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'nation' msg_perm_hud_outsider: 'outsider' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Plot: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'The town %s has had their townlevel set to %s.' diff --git a/Towny/src/main/resources/lang/ro-RO.yml b/Towny/src/main/resources/lang/ro-RO.yml index a7232aea91..6019f510fb 100644 --- a/Towny/src/main/resources/lang/ro-RO.yml +++ b/Towny/src/main/resources/lang/ro-RO.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'nation' msg_perm_hud_outsider: 'outsider' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Plot: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'The town %s has had their townlevel set to %s.' diff --git a/Towny/src/main/resources/lang/ru-RU.yml b/Towny/src/main/resources/lang/ru-RU.yml index 84b16826a3..a84a09f15f 100644 --- a/Towny/src/main/resources/lang/ru-RU.yml +++ b/Towny/src/main/resources/lang/ru-RU.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'нация' msg_perm_hud_outsider: 'чужак' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Участок: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'Городу %s установлен уровень %s.' diff --git a/Towny/src/main/resources/lang/sq-AL.yml b/Towny/src/main/resources/lang/sq-AL.yml index 7aefa14d46..68d9f440e3 100644 --- a/Towny/src/main/resources/lang/sq-AL.yml +++ b/Towny/src/main/resources/lang/sq-AL.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'nation' msg_perm_hud_outsider: 'outsider' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Plot: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'The town %s has had their townlevel set to %s.' diff --git a/Towny/src/main/resources/lang/sr-CS.yml b/Towny/src/main/resources/lang/sr-CS.yml index b0bc56e92e..2de8575f6b 100644 --- a/Towny/src/main/resources/lang/sr-CS.yml +++ b/Towny/src/main/resources/lang/sr-CS.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'nation' msg_perm_hud_outsider: 'outsider' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Plot: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'The town %s has had their townlevel set to %s.' diff --git a/Towny/src/main/resources/lang/sv-SE.yml b/Towny/src/main/resources/lang/sv-SE.yml index 6a06df1ddf..bbaaf2a21a 100644 --- a/Towny/src/main/resources/lang/sv-SE.yml +++ b/Towny/src/main/resources/lang/sv-SE.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'nation' msg_perm_hud_outsider: 'outsider' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Plot: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'The town %s has had their townlevel set to %s.' diff --git a/Towny/src/main/resources/lang/th-TH.yml b/Towny/src/main/resources/lang/th-TH.yml index 2019deace0..619ae6a0e2 100644 --- a/Towny/src/main/resources/lang/th-TH.yml +++ b/Towny/src/main/resources/lang/th-TH.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'nation' msg_perm_hud_outsider: 'outsider' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Plot: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'The town %s has had their townlevel set to %s.' diff --git a/Towny/src/main/resources/lang/tl-PH.yml b/Towny/src/main/resources/lang/tl-PH.yml index 22f10b4552..a40fe22afd 100644 --- a/Towny/src/main/resources/lang/tl-PH.yml +++ b/Towny/src/main/resources/lang/tl-PH.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'nation' msg_perm_hud_outsider: 'outsider' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Plot: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'The town %s has had their townlevel set to %s.' diff --git a/Towny/src/main/resources/lang/tr-TR.yml b/Towny/src/main/resources/lang/tr-TR.yml index f39046400f..4c973b6fc1 100644 --- a/Towny/src/main/resources/lang/tr-TR.yml +++ b/Towny/src/main/resources/lang/tr-TR.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'ulus' msg_perm_hud_outsider: 'yabancı' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Arsa: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: '%s kasabasının seviyesi %s olarak ayarlandı.' diff --git a/Towny/src/main/resources/lang/uk-UA.yml b/Towny/src/main/resources/lang/uk-UA.yml index 47e469f7df..6532b53f33 100644 --- a/Towny/src/main/resources/lang/uk-UA.yml +++ b/Towny/src/main/resources/lang/uk-UA.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'нація' msg_perm_hud_outsider: 'чужинець' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Ділянка: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'Місто %s установило свій рівень %s.' diff --git a/Towny/src/main/resources/lang/vi-VN.yml b/Towny/src/main/resources/lang/vi-VN.yml index a5f7ca834e..ea8b4d3783 100644 --- a/Towny/src/main/resources/lang/vi-VN.yml +++ b/Towny/src/main/resources/lang/vi-VN.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: 'nation' msg_perm_hud_outsider: 'outsider' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Plot: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'The town %s has had their townlevel set to %s.' diff --git a/Towny/src/main/resources/lang/zh-CN.yml b/Towny/src/main/resources/lang/zh-CN.yml index 37b2c2d8de..24dee305f7 100644 --- a/Towny/src/main/resources/lang/zh-CN.yml +++ b/Towny/src/main/resources/lang/zh-CN.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: '国家' msg_perm_hud_outsider: '外人' #Seen in /plot perm hud: msg_perm_hud_plot_name: '地皮: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: '城镇 %s 已将其城镇级别设置为 %s。' diff --git a/Towny/src/main/resources/lang/zh-TW.yml b/Towny/src/main/resources/lang/zh-TW.yml index 99b1385443..d7da466bb7 100644 --- a/Towny/src/main/resources/lang/zh-TW.yml +++ b/Towny/src/main/resources/lang/zh-TW.yml @@ -1876,6 +1876,14 @@ msg_perm_hud_nation: '城邦' msg_perm_hud_outsider: 'outsider' #Seen in /plot perm hud: msg_perm_hud_plot_name: 'Plot: ' +#Seen in /plot perm hud: +msg_perm_hud_plotgroup_name: 'Plot Group: ' +#Seen in /plot perm hud: +msg_perm_hud_plot_for_sale: 'For Sale: ' +#Seen in /plot perm hud: +msg_perm_hud_no: 'No' +#Seen in /plot perm hud: +msg_perm_hud_yes: 'Yes' #Added in 0.153 #Message shown confirming /ta town NAME settownlevel # command. msg_town_level_overridden_with: 'The town %s has had their townlevel set to %s.' From 094075ef8fcdf23fd0fbee4f520dc9ec7c04e76c Mon Sep 17 00:00:00 2001 From: LlmDl Date: Tue, 9 Jan 2024 10:27:15 -0600 Subject: [PATCH 31/74] Show help when we cannot match a /t buy subcommand. --- .../java/com/palmergames/bukkit/towny/command/TownCommand.java | 2 ++ 1 file changed, 2 insertions(+) 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 61d49c3ab6..0275bf109a 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 @@ -2456,7 +2456,9 @@ public static void townBuy(CommandSender sender, String[] split, @Nullable Town default -> { if (TownyCommandAddonAPI.hasCommand(CommandType.TOWN_BUY, split[0])) { TownyCommandAddonAPI.getAddonCommand(CommandType.TOWN_BUY, split[0]).execute(sender, "town", split); + return; } + HelpMenu.TOWN_BUY.send(sender); } } } From 018b43ac32494fb6974d156aa4478d0b5e4a61aa Mon Sep 17 00:00:00 2001 From: LlmDl Date: Tue, 9 Jan 2024 10:37:11 -0600 Subject: [PATCH 32/74] Update default dev mode name. --- .../main/java/com/palmergames/bukkit/config/ConfigNodes.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/config/ConfigNodes.java b/Towny/src/main/java/com/palmergames/bukkit/config/ConfigNodes.java index a5f63d6a39..eb74575b89 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/config/ConfigNodes.java +++ b/Towny/src/main/java/com/palmergames/bukkit/config/ConfigNodes.java @@ -1558,7 +1558,7 @@ public enum ConfigNodes { "", "# Spams the player named in dev_name with all messages related to towny."), PLUGIN_DEV_MODE_ENABLE("plugin.dev_mode.enable", "false"), - PLUGIN_DEV_MODE_DEV_NAME("plugin.dev_mode.dev_name", "ElgarL"), + PLUGIN_DEV_MODE_DEV_NAME("plugin.dev_mode.dev_name", "LlmDl"), PLUGIN_RESET_LOG_ON_BOOT( "plugin.reset_log_on_boot", "true", From 5da1432cf8d18887645993358f42259ef846ee55 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Tue, 9 Jan 2024 11:27:42 -0600 Subject: [PATCH 33/74] - Small refactor to the parseJailCommand class. --- Towny/pom.xml | 2 +- .../bukkit/towny/command/TownCommand.java | 241 +++++++++--------- Towny/src/main/resources/ChangeLog.txt | 4 +- 3 files changed, 131 insertions(+), 116 deletions(-) diff --git a/Towny/pom.xml b/Towny/pom.xml index d4c11e986e..71ca45ddf0 100644 --- a/Towny/pom.xml +++ b/Towny/pom.xml @@ -13,7 +13,7 @@ towny jar - 0.100.0.21 + 0.100.0.22 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 0275bf109a..352c658bb1 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 @@ -632,49 +632,50 @@ private void parseTownCommand(final Player player, String[] split) throws TownyE return; } + String[] subArg = StringMgmt.remFirstArg(split); switch (split[0].toLowerCase(Locale.ROOT)) { - case "add"-> townAdd(player, null, StringMgmt.remFirstArg(split)); + case "add"-> townAdd(player, null, subArg); 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 "buy"-> townBuy(player, subArg, null, false); + case "buytown"-> parseTownBuyTownCommand(player, subArg); + case "claim"-> parseTownClaimCommand(player, subArg); + case "delete"-> townDelete(player, subArg); case "deposit"-> parseTownDepositCommand(player, split); case "enemylist"-> townEnemyList(player, split); - case "forsale", "fs"-> parseTownForSaleCommand(player, StringMgmt.remFirstArg(split)); + case "forsale", "fs"-> parseTownForSaleCommand(player, subArg); 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 "invite", "invites"-> parseInviteCommand(player, subArg); + case "jail"-> parseJailCommand(player, null, subArg, false); + case "join"-> parseTownJoin(player, subArg); + case "kick"-> townKick(player, subArg); case "leave"-> townLeave(player); case "list" -> listTowns(player, split); case "mayor" -> parseTownyMayorCommand(player); - case "merge"-> parseTownMergeCommand(player, StringMgmt.remFirstArg(split)); + case "merge"-> parseTownMergeCommand(player, subArg); 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 "online"-> parseTownOnlineCommand(player, subArg); + case "outlaw", "ban"-> parseTownOutlawCommand(player, subArg, false, getResidentOrThrow(player).getTown()); case "outlawlist"-> townOutlawList(player, split); - case "outpost"-> townOutpost(player, StringMgmt.remFirstArg(split)); + case "outpost"-> townOutpost(player, subArg); 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 "purge"-> parseTownPurgeCommand(player, subArg); + case "rank"-> townRank(player, subArg); 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 "set"-> townSet(player, subArg, false, null); + case "spawn"-> townSpawn(player, subArg, 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 "toggle"-> townToggle(player, subArg, false, null); + case "trust"-> parseTownTrustCommand(player, subArg, null); + case "trusttown"-> parseTownTrustTownCommand(player, subArg, null); + case "unclaim"-> parseTownUnclaimCommand(player, subArg); + case "unjail"-> parseUnJailCommand(player, null, subArg, false); case "withdraw"-> parseTownWithdrawCommand(player, split); default -> { // Test if this is an addon command @@ -1491,8 +1492,10 @@ private static void parseJailCommand(CommandSender sender, Town town, String[] s if (!town.hasJails()) throw new TownyException(Translatable.of("msg_town_has_no_jails")); + boolean bailEnabled = TownySettings.isAllowingBail() && TownyEconomyHandler.isActive(); + if (split.length == 0) { - if (TownySettings.isAllowingBail() && TownyEconomyHandler.isActive()) + if (bailEnabled) HelpMenu.TOWN_JAILWITHBAIL.send(sender); else HelpMenu.TOWN_JAIL.send(sender); @@ -1506,115 +1509,110 @@ private static void parseJailCommand(CommandSender sender, Town town, String[] s // Set default values. int hours = 2; // default set to two in relation to https://github.com/TownyAdvanced/Towny/issues/6029 - double bail = TownySettings.isAllowingBail() && TownyEconomyHandler.isActive() ? TownySettings.getBailAmount() : 0.0; int jailNum = 1; int cell = 1; Jail jail = town.getPrimaryJail(); + double bail = bailEnabled ? TownySettings.getBailAmount() : 0.0; double initialJailFee = TownyEconomyHandler.isActive() && TownySettings.initialJailFee() > 0 ? TownySettings.initialJailFee() : 0; - try { - Resident jailedResident = getResidentOrThrow(split[0]); + // Vet the potential resident to be jailed, throws an exception with error message if they cannot be jailed. + Resident jailedResident = getResidentAllowedToBeJailedOrThrow(town, split); - // You can only jail your members of your own town. - if (!town.hasResident(jailedResident)) - throw new TownyException(Translatable.of("msg_resident_not_your_town")); + // Players used to be able to get places faster by using jailing exploits. + checkTeleportExploitsOrThrow(sender, admin, jailedResident); - // Make sure they aren't already jailed. - if (jailedResident.isJailed()) - throw new TownyException(Translatable.of("msg_err_resident_is_already_jailed", jailedResident.getName())); + // Begin getting hours, bail, jail and cell numbers from the inputted arguments, otherwise use the defaults. + if (split.length > 1) { + // offset is used to determine what argument in split is used for bail, jail # and cell #. + int offset = bailEnabled ? 1 : 0; - // Make sure they're not a new player who is jail-immune. - if (TownySettings.newPlayerJailImmunity() > 0) { - long time = (jailedResident.getRegistered() + TownySettings.newPlayerJailImmunity()) - System.currentTimeMillis(); - if (time > 0) - throw new TownyException(Translatable.of("msg_resident_has_not_played_long_enough_to_be_jailed", jailedResident.getName(), TimeMgmt.getFormattedTimeValue(time))); - } + /* + * Make sure that the arguments being passed in are actually numbers we can use. + */ + if (!checkArgumentsPassedForJail(sender, split, offset)) + return; - // Make sure the town can afford to jail. - if (initialJailFee > 0 && !town.getAccount().canPayFromHoldings(initialJailFee)) - throw new TownyException(Translatable.of("msg_not_enough_money_in_bank_to_jail_x_fee_is_x", jailedResident, initialJailFee)); + // Set the hours, which are mandatory. + hours = setJailHours(sender, split); - Player jailedPlayer = jailedResident.getPlayer(); - // Make sure the to-be-jailed resident is online. - if (jailedPlayer == null) - throw new TownyException(Translatable.of("msg_player_is_not_online", jailedResident.getName())); + // Set the bail if bailing is enabled and if the argument is given. + if (offset == 1 && split.length >= 3) + bail = setBail(sender, split); - // Make sure this isn't someone jailing themselves to get a free teleport. - if (!admin && jailedPlayer.getUniqueId().equals(((Player) sender).getUniqueId())) - throw new TownyException(Translatable.of("msg_no_self_jailing")); + // Set the jail number if the argument is given. + if (split.length >= 3 + offset) { + jail = town.getJail(MathUtil.getPositiveIntOrThrow(split[2 + offset])); + if (jail == null) + throw new TownyException(Translatable.of("msg_err_the_town_does_not_have_that_many_jails")); + } - // Test if a player is located where they are outlawed/enemied and unable to teleport. - Town jaileeLocTown = TownyAPI.getInstance().getTown(jailedPlayer.getLocation()); - if (jaileeLocTown != null) { - if (!TownySettings.canOutlawsTeleportOutOfTowns() && jaileeLocTown.hasOutlaw(jailedResident)) - throw new TownyException(Translatable.of("msg_err_resident_cannot_be_jailed_because_they_are_outlawed_there")); + // Set the jail cell if the argument is given. + if (split.length == 4 + offset) { + cell = MathUtil.getPositiveIntOrThrow(split[3 + offset]); + if (!jail.hasJailCell(cell)) + throw new TownyException(Translatable.of("msg_err_that_jail_plot_does_not_have_that_many_cells")); + } + } - Nation jaileeLocNation = jaileeLocTown.getNationOrNull(); + // Can the Town jail this resident? + testTownCanJailResidentOrThrow(town, initialJailFee, jailedResident); - if (jaileeLocNation != null && - jailedResident.hasNation() && - TownySettings.getDisallowedTownSpawnZones().contains("enemy") && - jaileeLocNation.hasEnemy(jailedResident.getNationOrNull())) - throw new TownyException(Translatable.of("msg_err_resident_cannot_be_jailed_because_they_are_enemied_there")); - } + // Jail the resident, when enabled it will apply the bail. + JailUtil.jailResidentWithBail(jailedResident, jail, cell, hours, bail, JailReason.MAYOR, sender); - // Begin getting hours, bail, jail and cell numbers from the inputted arguments. - if (split.length > 1) { - // offset is used to determine what argument in split is used for bail, jail # and cell #. - int offset = TownySettings.isAllowingBail() && TownyEconomyHandler.isActive() ? 1 : 0; + // Send an admin a message if the player was jailed via Admin. + if (admin) + TownyMessaging.sendMsg(sender, Translatable.of("msg_player_has_been_sent_to_jail_number", jailedResident.getName(), jailNum)); - /* - * Make sure that the arguments being passed in are actually numbers we can use. - */ - if (!checkArgumentsPassedForJail(sender, split, offset)) - return; + // If fee exists (already sanitised for) deduct it from Town bank and inform in chat + if (initialJailFee > 0) { + town.getAccount().withdraw(initialJailFee, "New Prisoner fee for " + jailedResident.getName()); + TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_x_has_been_withdrawn_for_jailing_of_prisoner_x", initialJailFee, jailedResident)); + } + } - // Set the hours, which are mandatory. - hours = setJailHours(sender, split); + private static Resident getResidentAllowedToBeJailedOrThrow(Town town, String[] split) throws TownyException { + Resident jailedResident = getResidentOrThrow(split[0]); - // Set the bail if bailing is enabled and if the argument is given. - if (offset == 1 && split.length >= 3) - bail = setBail(sender, split); + // You can only jail your members of your own town. + if (!town.hasResident(jailedResident)) + throw new TownyException(Translatable.of("msg_resident_not_your_town")); - // Set the jail number if the argument is given. - if (split.length >= 3 + offset) { - jail = town.getJail(Integer.parseInt(split[2 + offset])); - if (jail == null) - throw new TownyException(Translatable.of("msg_err_the_town_does_not_have_that_many_jails")); - } + // Make sure they aren't already jailed. + if (jailedResident.isJailed()) + throw new TownyException(Translatable.of("msg_err_resident_is_already_jailed", jailedResident.getName())); - // Set the jail cell if the argument is given. - if (split.length == 4 + offset) { - cell = Integer.parseInt(split[3 + offset]); - if (!jail.hasJailCell(cell)) - throw new TownyException(Translatable.of("msg_err_that_jail_plot_does_not_have_that_many_cells")); - } - } + // Make sure they're not a new player who is jail-immune. + if (TownySettings.newPlayerJailImmunity() > 0) { + long time = (jailedResident.getRegistered() + TownySettings.newPlayerJailImmunity()) - System.currentTimeMillis(); + if (time > 0) + throw new TownyException(Translatable.of("msg_resident_has_not_played_long_enough_to_be_jailed", jailedResident.getName(), TimeMgmt.getFormattedTimeValue(time))); + } - // Check if Town has reached max potential jailed and react according to maxJailedNewJailBehavior in config - if (TownySettings.getMaxJailedPlayerCount() > 0 && town.getJailedPlayerCount() >= TownySettings.getMaxJailedPlayerCount()) { - if (TownySettings.getMaxJailedNewJailBehavior() == 0) - // simple mode, rejects new jailed people outright - throw new TownyException(Translatable.of("msg_town_has_no_jailslots")); - //Pass to JailUtil method - JailUtil.maxJailedUnjail(town); - } + if (!jailedResident.isOnline()) + throw new TownyException(Translatable.of("msg_player_is_not_online", jailedResident.getName())); - // Jail the resident. - JailUtil.jailResidentWithBail(jailedResident, jail, cell, hours, bail, JailReason.MAYOR, sender); + return jailedResident; + } - // Send an admin a message if the player was jailed via Admin. - if (admin) - TownyMessaging.sendMsg(sender, Translatable.of("msg_player_has_been_sent_to_jail_number", jailedPlayer.getName(), jailNum)); + private static void checkTeleportExploitsOrThrow(CommandSender sender, boolean admin, Resident jailedResident) throws TownyException { + Player jailedPlayer = jailedResident.getPlayer(); + // Make sure this isn't someone jailing themselves to get a free teleport. + if (!admin && jailedPlayer.getUniqueId().equals(((Player) sender).getUniqueId())) + throw new TownyException(Translatable.of("msg_no_self_jailing")); - // If fee exists (already sanitised for) deduct it from Town bank and inform in chat - if (initialJailFee > 0) { - town.getAccount().withdraw(initialJailFee, "New Prisoner fee for " + jailedResident.getName()); - TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_x_has_been_withdrawn_for_jailing_of_prisoner_x", initialJailFee,jailedResident)); - } + // Test if a player is located where they are outlawed/enemied and unable to teleport. + Town jaileeLocTown = TownyAPI.getInstance().getTown(jailedPlayer.getLocation()); + if (jaileeLocTown != null) { + if (!TownySettings.canOutlawsTeleportOutOfTowns() && jaileeLocTown.hasOutlaw(jailedResident)) + throw new TownyException(Translatable.of("msg_err_resident_cannot_be_jailed_because_they_are_outlawed_there")); - } catch (NullPointerException e) { - plugin.getLogger().log(Level.WARNING, "while parsing jail command", e); + Nation jaileeLocNation = jaileeLocTown.getNationOrNull(); + + if (jaileeLocNation != null && jailedResident.hasNation() && + TownySettings.getDisallowedTownSpawnZones().contains("enemy") && + jaileeLocNation.hasEnemy(jailedResident.getNationOrNull())) + throw new TownyException(Translatable.of("msg_err_resident_cannot_be_jailed_because_they_are_enemied_there")); } } @@ -1637,9 +1635,9 @@ private static boolean checkArgumentsPassedForJail(CommandSender sender, String[ return true; } - private static int setJailHours(CommandSender sender, String[] split) { - int hours = Math.min(2, Integer.parseInt(split[1])); - + private static int setJailHours(CommandSender sender, String[] split) throws TownyException { + int hours = Math.min(2, MathUtil.getPositiveIntOrThrow(split[1])); + if (hours > TownySettings.getJailedMaxHours()) { hours = TownySettings.getJailedMaxHours(); TownyMessaging.sendMsg(sender, Translatable.of("msg_err_higher_than_max_allowed_hours_x", TownySettings.getJailedMaxHours())); @@ -1647,9 +1645,9 @@ private static int setJailHours(CommandSender sender, String[] split) { return hours; } - private static double setBail(CommandSender sender, String[] split) { - double bail = Math.max(1, Double.parseDouble(split[2])); - + private static double setBail(CommandSender sender, String[] split) throws TownyException { + double bail = Math.max(1, MathUtil.getDoubleOrThrow(split[2])); + if (bail > TownySettings.getBailMaxAmount()) { bail = TownySettings.getBailMaxAmount(); TownyMessaging.sendMsg(sender, Translatable.of("msg_err_higher_than_max_allowed_bail_x", TownySettings.getBailMaxAmount())); @@ -1657,6 +1655,21 @@ private static double setBail(CommandSender sender, String[] split) { return bail; } + private static void testTownCanJailResidentOrThrow(Town town, double initialJailFee, Resident jailedResident) throws TownyException { + // Make sure the town can afford to jail. + if (initialJailFee > 0 && !town.getAccount().canPayFromHoldings(initialJailFee)) + throw new TownyException(Translatable.of("msg_not_enough_money_in_bank_to_jail_x_fee_is_x", jailedResident, initialJailFee)); + + // Check if Town has reached max potential jailed and react according to maxJailedNewJailBehavior in config + if (TownySettings.getMaxJailedPlayerCount() > 0 && town.getJailedPlayerCount() >= TownySettings.getMaxJailedPlayerCount()) { + if (TownySettings.getMaxJailedNewJailBehavior() == 0) + // simple mode, rejects new jailed people outright + throw new TownyException(Translatable.of("msg_town_has_no_jailslots")); + //Pass to JailUtil method to unjail someone to make room. + JailUtil.maxJailedUnjail(town); + } + } + private static void parseJailListCommand(CommandSender sender, Town town, String[] args) { try { if (sender instanceof Player player) { diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index e4043e99fe..954fcf7b84 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9415,4 +9415,6 @@ v0.92.0.11: the old node towny.command.town.buy will continue to point to towny.command.town.buy.bonus, although it is recommended you change over to using the new towny.command.town.buy.* instead. - Bump com.github.seeseemelk:MockBukkit-v1.20 from 3.58.0 to 3.60.0. - - Bump net.coreprotect:coreprotect from 22.2 to 22.3. \ No newline at end of file + - Bump net.coreprotect:coreprotect from 22.2 to 22.3. +0.100.0.22: + - Small refactor to the parseJailCommand class. \ No newline at end of file From 9bf39352cbda8d9f79091cc7ea241821aa6c5777 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Tue, 9 Jan 2024 12:47:45 -0600 Subject: [PATCH 34/74] - Refactor the parseTownClaimCommand method. --- .../bukkit/towny/command/TownCommand.java | 199 +++++++++--------- Towny/src/main/resources/ChangeLog.txt | 3 +- 2 files changed, 107 insertions(+), 95 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 352c658bb1..fe0f52f042 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 @@ -63,6 +63,7 @@ import com.palmergames.bukkit.towny.object.Translatable; import com.palmergames.bukkit.towny.object.comparators.ComparatorCaches; import com.palmergames.bukkit.towny.object.comparators.ComparatorType; +import com.palmergames.bukkit.towny.object.economy.Account; import com.palmergames.bukkit.towny.object.Nation; import com.palmergames.bukkit.towny.object.Resident; import com.palmergames.bukkit.towny.object.SpawnType; @@ -3497,69 +3498,102 @@ public static void parseTownClaimCommand(Player player, String[] split) throws T } catchRuinedTown(player); - Resident resident = getResidentOrThrow(player); - Town town = getTownFromResidentOrThrow(resident); + Town town = getTownFromPlayerOrThrow(player); + catchBankruptTownWithLand(town); + final boolean outpost = split.length == 1 && split[0].equalsIgnoreCase("outpost"); + + // Make initial selection of WorldCoord(s), test whether the player has the + // required permission node, and vet the selection for proximity, biome, + // wilderness rules. + final List selection = getTownClaimSelectionOrThrow(player, split, town); + + // Check the Town can claim the vetted selection, available claimblocks/adjacent + // claims/edge blocks, etc. + vetTownAllowedTheseClaims(town, outpost, selection); + + // Allow other plugins to have a say in whether the claim is allowed. + fireTownPreClaimEventOrThrow(player, town, outpost, selection); + // See if the Town can pay (if required.) + vetTheTownCanPayIfRequired(player, town, outpost, selection); + + // Begin the actual TownClaim task. + plugin.getScheduler().runAsync(new TownClaim(plugin, player, town, selection, outpost, true, false)); + } + + private static void catchBankruptTownWithLand(Town town) throws TownyException { // Allow a bankrupt town to claim a single plot. if (town.isBankrupt() && !town.getTownBlocks().isEmpty()) throw new TownyException(Translatable.of("msg_err_bankrupt_town_cannot_claim")); + } - final TownyWorld world = TownyAPI.getInstance().getTownyWorld(player.getWorld()); + private static List getTownClaimSelectionOrThrow(Player player, String[] split, Town town) throws TownyException { + List selection; + WorldCoord playerWorldCoord = WorldCoord.parseWorldCoord(player); + final TownyWorld world = playerWorldCoord.getTownyWorld(); if (world == null || !world.isUsingTowny()) throw new TownyException(Translatable.of("msg_set_use_towny_off")); - + if (!world.isClaimable()) throw new TownyException(Translatable.of("msg_not_claimable")); - List selection; - boolean outpost = false; - boolean isAdmin = resident.isAdmin(); - WorldCoord key = WorldCoord.parseWorldCoord(player); + // Prevent someone manually running /t claim world x z (a command which should only be run via /plot claim world x z) + if (split.length != 0 && TownyAPI.getInstance().getTownyWorld(split[0]) != null) + throw new TownyException(Translatable.of("tc_err_invalid_command")); - /* - * Make initial selection of WorldCoord(s) - */ if (split.length == 1 && split[0].equalsIgnoreCase("outpost")) { - if (!TownySettings.isAllowingOutposts()) throw new TownyException(Translatable.of("msg_outpost_disable")); checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_CLAIM_OUTPOST.getNode()); - + + Resident resident = getResidentOrThrow(player); // Run various tests required by configuration/permissions through Util. - OutpostUtil.OutpostTests(town, resident, world, key, isAdmin, false); - - if (key.hasTownBlock()) - throw new TownyException(Translatable.of("msg_already_claimed_1", key)); + OutpostUtil.OutpostTests(town, resident, world, playerWorldCoord, resident.isAdmin(), false); + + if (playerWorldCoord.hasTownBlock()) + throw new TownyException(Translatable.of("msg_already_claimed", playerWorldCoord.getTownOrNull())); // Select a single WorldCoord using the AreaSelectionUtil. selection = new ArrayList<>(); - selection.add(key); - outpost = true; + selection.add(playerWorldCoord); } else if (split.length == 1 && "fill".equalsIgnoreCase(split[0])) { checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_CLAIM_FILL.getNode()); - - final BorderUtil.FloodfillResult result = BorderUtil.getFloodFillableCoords(town, key); + + final BorderUtil.FloodfillResult result = BorderUtil.getFloodFillableCoords(town, playerWorldCoord); if (result.type() != BorderUtil.FloodfillResult.Type.SUCCESS) throw result.feedback() != null ? new TownyException(result.feedback()) : new TownyException(); else if (result.feedback() != null) TownyMessaging.sendMsg(player, result.feedback()); - + selection = new ArrayList<>(result.coords()); } else { - - // Prevent someone manually running /t claim world x z (a command which should only be run via /plot claim world x z) - if (split.length != 0 && TownyAPI.getInstance().getTownyWorld(split[0]) != null) - throw new TownyException(Translatable.of("tc_err_invalid_command")); - + // Standard /t claim [args] behaviour checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_CLAIM_TOWN.getNode()); // Select the area, can be one or many. - selection = AreaSelectionUtil.selectWorldCoordArea(town, new WorldCoord(world.getName(), key), split, true); + selection = AreaSelectionUtil.selectWorldCoordArea(town, playerWorldCoord, split, true); + + // Fast fail when we're claiming a single worldcoord and it is already claimed. + if (selection.size() == 1 && playerWorldCoord.hasTownBlock()) + throw new TownyException(Translatable.of("msg_already_claimed", playerWorldCoord.getTownOrNull())); } + if (selection.isEmpty()) + throw new TownyException(Translatable.of("msg_err_empty_area_selection")); + + // Vet the selection for all sorts of proximity, biome, already-claimed, etc rules. + return vetTownClaimSelection(player, town, selection); + } + + private static List vetTownClaimSelection(Player player, Town town, List selection) throws TownyException { + /* + * Filter out any unallowed claims. + */ + TownyMessaging.sendDebugMsg("townClaim: Pre-Filter Selection ["+selection.size()+"] " + Arrays.toString(selection.toArray(new WorldCoord[0]))); + // Filter out any TownBlocks which aren't Wilderness. selection = AreaSelectionUtil.filterOutTownOwnedBlocks(selection); @@ -3568,23 +3602,10 @@ else if (result.feedback() != null) // Filter out any TownBlocks which have too much ocean biomes, when enabled. selection = AreaSelectionUtil.filterOutOceanBiomeWorldCoords(player, selection); - + if (selection.isEmpty()) throw new TownyException(Translatable.of("msg_err_empty_area_selection")); - // Not enough available claims. - if (!town.hasUnlimitedClaims() && selection.size() > town.availableTownBlocks()) - throw new TownyException(Translatable.of("msg_err_not_enough_blocks")); - - // If this is a single claim and it is already claimed, by someone else. - if (selection.size() == 1 && selection.get(0).getTownOrNull() != null) - throw new TownyException(Translatable.of("msg_already_claimed", selection.get(0).getTownOrNull())); - - /* - * Filter out any unallowed claims. - */ - TownyMessaging.sendDebugMsg("townClaim: Pre-Filter Selection ["+selection.size()+"] " + Arrays.toString(selection.toArray(new WorldCoord[0]))); - // Filter out townblocks too close to another Town's homeblock. selection = AreaSelectionUtil.filterInvalidProximityToHomeblock(selection, town); if (selection.isEmpty()) @@ -3595,6 +3616,15 @@ else if (result.feedback() != null) if (selection.isEmpty()) throw new TownyException(Translatable.of("msg_too_close2", Translatable.of("townblock"))); + TownyMessaging.sendDebugMsg("townClaim: Post-Filter Selection [" + selection.size() + "] " + Arrays.toString(selection.toArray(new WorldCoord[0]))); + return selection; + } + + private static void vetTownAllowedTheseClaims(Town town, boolean outpost, List selection) throws TownyException { + // Not enough available claims. + if (!town.hasUnlimitedClaims() && selection.size() > town.availableTownBlocks()) + throw new TownyException(Translatable.of("msg_err_not_enough_blocks")); + // Prevent straight line claims if configured, and the town has enough townblocks claimed, and this is not an outpost. int minAdjacentBlocks = TownySettings.getMinAdjacentBlocks(); if (!outpost && minAdjacentBlocks > 0 && townHasClaimedEnoughLandToBeRestrictedByAdjacentClaims(town, minAdjacentBlocks)) { @@ -3605,76 +3635,57 @@ else if (result.feedback() != null) if (numAdjacent < minAdjacentBlocks && numAdjacentOutposts(town, firstWorldCoord) == 0) throw new TownyException(Translatable.of("msg_min_adjacent_blocks", minAdjacentBlocks, numAdjacent)); } - - TownyMessaging.sendDebugMsg("townClaim: Post-Filter Selection ["+selection.size()+"] " + Arrays.toString(selection.toArray(new WorldCoord[0]))); - + // When not claiming an outpost, make sure at least one of the selection is attached to a claimed plot. if (!outpost && !isEdgeBlock(town, selection) && !town.getTownBlocks().isEmpty()) throw new TownyException(Translatable.of("msg_err_not_attached_edge")); - - /* - * Allow other plugins to have a say in whether the claim is allowed. - */ - int blockedClaims = 0; + } + + private static boolean townHasClaimedEnoughLandToBeRestrictedByAdjacentClaims(Town town, int minAdjacentBlocks) { + if (minAdjacentBlocks == 3 && town.getTownBlocks().size() < 5) + // Special rule that makes sure a town can claim a fifth plot after claiming a 2x2 square. + return false; + return town.getTownBlocks().size() > minAdjacentBlocks; + } + private static void fireTownPreClaimEventOrThrow(Player player, Town town, boolean outpost, List selection) throws TownyException { + int blockedClaims = 0; String cancelMessage = ""; boolean isHomeblock = town.getTownBlocks().size() == 0; for (WorldCoord coord : selection) { - //Use the user's current world - TownPreClaimEvent preClaimEvent = new TownPreClaimEvent(town, new TownBlock(coord.getX(), coord.getZ(), world), player, outpost, isHomeblock, false); + TownPreClaimEvent preClaimEvent = new TownPreClaimEvent(town, new TownBlock(coord), player, outpost, isHomeblock, false); if(BukkitTools.isEventCancelled(preClaimEvent)) { blockedClaims++; cancelMessage = preClaimEvent.getCancelMessage(); } } - - if (blockedClaims > 0) { + if (blockedClaims > 0) throw new TownyException(String.format(cancelMessage, blockedClaims, selection.size())); - } - - /* - * See if the Town can pay (if required.) - */ + } + + private static void vetTheTownCanPayIfRequired(Player player, Town town, final boolean outpost, final List selection) throws TownyException { if (TownyEconomyHandler.isActive()) { - final boolean isOutpost = outpost; - final List finalSelection = selection; - - TownyEconomyHandler.economyExecutor().execute(() -> { - double blockCost; - try { - if (isOutpost) - blockCost = TownySettings.getOutpostCost(); - else if (finalSelection.size() == 1) - blockCost = town.getTownBlockCost(); - else - blockCost = town.getTownBlockCostN(finalSelection.size()); - - if (!town.getAccount().canPayFromHoldings(blockCost)) { - double missingAmount = blockCost - town.getAccount().getHoldingBalance(); - throw new TownyException(Translatable.of("msg_no_funds_claim2", finalSelection.size(), prettyMoney(blockCost), prettyMoney(missingAmount), new DecimalFormat("#").format(missingAmount))); - } + Account townAccount = town.getAccount(); + if (townAccount == null) // This is usually right about the time when admins find out their Economy plugin doesn't work well with Towny. + throw new TownyException("The server economy plugin " + TownyEconomyHandler.getVersion() + " could not return the Town account!"); - town.getAccount().withdraw(blockCost, String.format("Town Claim (%d) by %s", finalSelection.size(), player.getName())); - - // Start the claiming process after a successful withdraw. - plugin.getScheduler().runAsync(new TownClaim(plugin, player, town, finalSelection, isOutpost, true, false)); - } catch (NullPointerException e2) { - TownyMessaging.sendErrorMsg(player, "The server economy plugin " + TownyEconomyHandler.getVersion() + " could not return the Town account!"); - } catch (TownyException e) { - TownyMessaging.sendErrorMsg(player, e.getMessage(player)); - } - }); - } else { - // Economy isn't enabled, start the claiming process immediately. - plugin.getScheduler().runAsync(new TownClaim(plugin, player, town, selection, outpost, true, false)); + int selectionSize = selection.size(); + double blockCost = getSelectionCost(town, outpost, selectionSize); + + if (!townAccount.canPayFromHoldings(blockCost)) { + double missingAmount = blockCost - townAccount.getHoldingBalance(); + throw new TownyException(Translatable.of("msg_no_funds_claim2", selectionSize, prettyMoney(blockCost), prettyMoney(missingAmount), new DecimalFormat("#").format(missingAmount))); + } + + // Charge the town for the claim. + TownyEconomyHandler.economyExecutor().execute(() -> + town.getAccount().withdraw(blockCost, String.format("Town Claim (%d) by %s", selectionSize, player.getName()))); } } - private static boolean townHasClaimedEnoughLandToBeRestrictedByAdjacentClaims(Town town, int minAdjacentBlocks) { - if (minAdjacentBlocks == 3 && town.getTownBlocks().size() < 5) - // Special rule that makes sure a town can claim a fifth plot after claiming a 2x2 square. - return false; - return town.getTownBlocks().size() > minAdjacentBlocks; + private static double getSelectionCost(Town town, final boolean outpost, int selectionSize) throws TownyException { + return outpost ? TownySettings.getOutpostCost() + : selectionSize == 1 ? town.getTownBlockCost() : town.getTownBlockCostN(selectionSize); } public static void parseTownUnclaimCommand(Player player, String[] split) throws TownyException { diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index 954fcf7b84..3929e836da 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9417,4 +9417,5 @@ v0.92.0.11: - Bump com.github.seeseemelk:MockBukkit-v1.20 from 3.58.0 to 3.60.0. - Bump net.coreprotect:coreprotect from 22.2 to 22.3. 0.100.0.22: - - Small refactor to the parseJailCommand class. \ No newline at end of file + - Refactor the parseJailCommand method. + - Refactor the parseTownClaimCommand method. \ No newline at end of file From b851fe03d51629bec2538547a440b260d77a2ac4 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Tue, 9 Jan 2024 15:39:46 -0600 Subject: [PATCH 35/74] - Fix new outlaws being teleported when they have in fact left the town's borders. --- .../bukkit/towny/command/TownCommand.java | 51 ++++++++++--------- Towny/src/main/resources/ChangeLog.txt | 3 +- 2 files changed, 28 insertions(+), 26 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 fe0f52f042..dae3256fbe 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 @@ -945,36 +945,37 @@ private static void parseTownOutlawAddCommand(CommandSender sender, boolean admi } catch (AlreadyRegisteredException ignored) {} town.save(); - // 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); - } - } + // Send feedback messages and potentially teleport the new outlaw out of town. + if (target.isOnline()) + handleOnlineNewlyMintedOutlaw(town, target); 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())); } + private static void handleOnlineNewlyMintedOutlaw(Town town, Resident target) { + TownyMessaging.sendMsg(target, Translatable.of("msg_you_have_been_declared_outlaw", town.getName())); + Player player = target.getPlayer(); + Location loc = player.getLocation(); + + if (!TownySettings.areNewOutlawsTeleportedAway() || TownyAPI.getInstance().isWilderness(loc) + || !TownyAPI.getInstance().getTown(loc).equals(town) || !BukkitTools.isEventCancelled(new OutlawTeleportEvent(target, town, loc))) + return; + + // If the newly-outlawed player is within the town's borders send them using the + // outlaw teleport warmup time, potentially giving them the chance to escape the + // borders. + int warmupTime = TownySettings.getOutlawTeleportWarmup(); + if (warmupTime > 0) + TownyMessaging.sendMsg(target, Translatable.of("msg_outlaw_kick_cooldown", town, TimeMgmt.formatCountdownTime(warmupTime))); + + plugin.getScheduler().runLater(() -> { + // Send them away if they're still within the town. + if (player.isOnline() && TownyAPI.getInstance().getTown(player.getLocation()).equals(town)) + SpawnUtil.outlawTeleport(town, target); + }, warmupTime * 20L); + } + 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")); diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index 3929e836da..1160d77cb5 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9418,4 +9418,5 @@ v0.92.0.11: - Bump net.coreprotect:coreprotect from 22.2 to 22.3. 0.100.0.22: - Refactor the parseJailCommand method. - - Refactor the parseTownClaimCommand method. \ No newline at end of file + - Refactor the parseTownClaimCommand method. + - Fix new outlaws being teleported when they have in fact left the town's borders. \ No newline at end of file From d216eba1016b732b01c3335648383e990114fe75 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Tue, 9 Jan 2024 15:46:44 -0600 Subject: [PATCH 36/74] - Fix residents being able to see vanished online players who are in their town. --- .../bukkit/towny/command/TownCommand.java | 18 ++++++------------ Towny/src/main/resources/ChangeLog.txt | 3 ++- 2 files changed, 8 insertions(+), 13 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 dae3256fbe..093c8cedea 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 @@ -1058,18 +1058,12 @@ private void parseTownOnlineCommand(Player player, String[] split) throws TownyE checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_ONLINE.getNode()); catchRuinedTown(player); Translator translator = Translator.locale(player); - if (split.length > 0) { - Town town = getTownOrThrow(split[0]); - - List onlineResidents = ResidentUtil.getOnlineResidentsViewable(player, town); - if (onlineResidents.size() > 0) { - TownyMessaging.sendMessage(player, TownyFormatter.getFormattedOnlineResidents(translator.of("msg_town_online"), town, player)); - } else { - TownyMessaging.sendMessage(player, Colors.White + "0 " + translator.of("res_list") + " " + (translator.of("msg_town_online") + ": " + town)); - } - } else { - TownyMessaging.sendMessage(player, TownyFormatter.getFormattedOnlineResidents(translator.of("msg_town_online"), getTownFromPlayerOrThrow(player), player)); - } + Town town = split.length > 0 ? getTownOrThrow(split[0]) : getTownFromPlayerOrThrow(player); + List onlineResidents = ResidentUtil.getOnlineResidentsViewable(player, town); + String output = onlineResidents.size() > 0 + ? TownyFormatter.getFormattedOnlineResidents(translator.of("msg_town_online"), town, player) + : Colors.White + "0 " + translator.of("res_list") + " " + (translator.of("msg_town_online") + ": " + town); + TownyMessaging.sendMessage(player, output); } private void parseTownHereCommand(final Player player) throws NoPermissionException, TownyException { diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index 1160d77cb5..56c989ad75 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9419,4 +9419,5 @@ v0.92.0.11: 0.100.0.22: - Refactor the parseJailCommand method. - Refactor the parseTownClaimCommand method. - - Fix new outlaws being teleported when they have in fact left the town's borders. \ No newline at end of file + - Fix new outlaws being teleported when they have in fact left the town's borders. + - Fix residents being able to see vanished online players who are in their town. \ No newline at end of file From 24f5345488f5680f423ae8b989c4b72d1e3a7908 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Tue, 9 Jan 2024 17:38:41 -0600 Subject: [PATCH 37/74] - Refactor the townRank method. --- .../bukkit/towny/command/HelpMenu.java | 8 ++ .../bukkit/towny/command/TownCommand.java | 99 ++++++++----------- Towny/src/main/resources/ChangeLog.txt | 3 +- 3 files changed, 51 insertions(+), 59 deletions(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/command/HelpMenu.java b/Towny/src/main/java/com/palmergames/bukkit/towny/command/HelpMenu.java index cd709c2aed..5466f56d68 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/command/HelpMenu.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/command/HelpMenu.java @@ -564,6 +564,14 @@ protected MenuBuilder load() { .add("{page #} by online", Translatable.of("town_list_help_6")); } }, + + TOWN_RANK { + @Override + protected MenuBuilder load() { + return new MenuBuilder("town rank") + .add("add|remove [resident] [rank]", Translatable.of("nation_help_17")); // This fits for the town command. + } + }, TOWN_SET { @Override 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 093c8cedea..e861e4b409 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 @@ -1724,88 +1724,71 @@ public void townRank(Player player, String[] split) throws TownyException { catchRuinedTown(player); if (split.length == 0) { // Help output. - TownyMessaging.sendMessage(player, ChatTools.formatTitle("/town rank")); - TownyMessaging.sendMessage(player, ChatTools.formatCommand("", "/town rank", "add/remove [resident] rank", "")); + HelpMenu.TOWN_RANK.send(player); return; } - Resident target; - Town town = null; - String rank; - - /* - * Does the command have enough arguments? - */ + // Does the command have enough arguments? if (split.length < 3) throw new TownyException("Eg: /town rank add/remove [resident] [rank]"); - target = getResidentOrThrow(split[1]); - town = getTownFromPlayerOrThrow(player); - - if (town != target.getTown()) + // Make sure the target resident is part of the Player's town. + Resident target = getResidentOrThrow(split[1]); + if (!getTownFromPlayerOrThrow(player).hasResident(target)) throw new TownyException(Translatable.of("msg_resident_not_your_town")); - /* - * Match casing to an existing rank, returns null if Town rank doesn't exist. - */ - rank = TownyPerms.matchTownRank(split[2]); + // Match casing to an existing rank, returns null if Town rank doesn't exist. + String rank = TownyPerms.matchTownRank(split[2]); if (rank == null) throw new TownyException(Translatable.of("msg_unknown_rank_available_ranks", split[2], StringMgmt.join(TownyPerms.getTownRanks(), ", "))); - /* - * Only allow the player to assign ranks if they have the grant perm - * for it. - */ + // Only allow the player to assign ranks if they have the grant perm for it. checkPermOrThrowWithMessage(player, PermissionNodes.TOWNY_COMMAND_TOWN_RANK.getNode(rank.toLowerCase(Locale.ROOT)), Translatable.of("msg_no_permission_to_give_rank")); - if (split[0].equalsIgnoreCase("add")) { + // Try to apply the rank to the resident. + switch (split[0].toLowerCase(Locale.ROOT)) { + case "add" -> rankAdd(player, target, rank); + case "remove" -> rankRemove(player, target, rank); + default -> HelpMenu.TOWN_RANK.send(player); + } + } - if (!target.hasTownRank(rank)) { - BukkitTools.ifCancelledThenThrow(new TownAddResidentRankEvent(target, rank, town)); + private void rankAdd(Player player, Resident target, String rank) throws TownyException { + Translatable townWord = Translatable.of("town_sing"); + if (target.hasTownRank(rank)) + throw new TownyException(Translatable.of("msg_resident_already_has_rank", target.getName(), townWord)); - target.addTownRank(rank); - if (target.isOnline()) { - TownyMessaging.sendMsg(target, Translatable.of("msg_you_have_been_given_rank", Translatable.of("town_sing"), rank)); - plugin.deleteCache(TownyAPI.getInstance().getPlayer(target)); - } - TownyMessaging.sendMsg(player, Translatable.of("msg_you_have_given_rank", Translatable.of("town_sing"), rank, target.getName())); - } else { - // Must already have this rank - TownyMessaging.sendMsg(player, Translatable.of("msg_resident_already_has_rank", target.getName(), Translatable.of("town_sing"))); - return; - } + BukkitTools.ifCancelledThenThrow(new TownAddResidentRankEvent(target, rank, target.getTownOrNull())); - } else if (split[0].equalsIgnoreCase("remove")) { + target.addTownRank(rank); + target.save(); - if (target.hasTownRank(rank)) { - BukkitTools.ifCancelledThenThrow(new TownRemoveResidentRankEvent(target, rank, town)); + // Feedback + TownyMessaging.sendMsg(player, Translatable.of("msg_you_have_given_rank", townWord, rank, target.getName())); + if (target.isOnline()) { + TownyMessaging.sendMsg(target, Translatable.of("msg_you_have_been_given_rank", townWord, rank)); + plugin.deleteCache(TownyAPI.getInstance().getPlayer(target)); + } + } - target.removeTownRank(rank); - if (target.isOnline()) { - TownyMessaging.sendMsg(target, Translatable.of("msg_you_have_had_rank_taken", Translatable.of("town_sing"), rank)); - plugin.deleteCache(TownyAPI.getInstance().getPlayer(target)); - } - TownyMessaging.sendMsg(player, Translatable.of("msg_you_have_taken_rank_from", Translatable.of("town_sing"), rank, target.getName())); - } else { - // Doesn't have this rank - TownyMessaging.sendMsg(player, Translatable.of("msg_resident_doesnt_have_rank", target.getName(), Translatable.of("town_sing"))); - return; - } + private void rankRemove(Player player, Resident target, String rank) throws TownyException { + Translatable townWord = Translatable.of("town_sing"); + if (!target.hasTownRank(rank)) + throw new TownyException(Translatable.of("msg_resident_doesnt_have_rank", target.getName(), townWord)); - } else { - TownyMessaging.sendErrorMsg(player, Translatable.of("msg_err_invalid_property", split[0])); - return; - } + BukkitTools.ifCancelledThenThrow(new TownRemoveResidentRankEvent(target, rank, target.getTownOrNull())); - /* - * If we got here we have made a change Save the altered resident - * data. - */ + target.removeTownRank(rank); target.save(); + // Feedback + TownyMessaging.sendMsg(player, Translatable.of("msg_you_have_taken_rank_from", townWord, rank, target.getName())); + if (target.isOnline()) { + TownyMessaging.sendMsg(target, Translatable.of("msg_you_have_had_rank_taken", townWord, rank)); + plugin.deleteCache(TownyAPI.getInstance().getPlayer(target)); + } } - private void parseTownSayCommand(final Player player, String[] split) throws NoPermissionException, TownyException { checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_SAY.getNode()); catchRuinedTown(player); diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index 56c989ad75..9d7459bd7a 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9420,4 +9420,5 @@ v0.92.0.11: - Refactor the parseJailCommand method. - Refactor the parseTownClaimCommand method. - Fix new outlaws being teleported when they have in fact left the town's borders. - - Fix residents being able to see vanished online players who are in their town. \ No newline at end of file + - Fix residents being able to see vanished online players who are in their town. + - Refactor the townRank method. \ No newline at end of file From 78bbf07336a8d14286b76c76fc2db7423b1d05e3 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Tue, 9 Jan 2024 17:56:32 -0600 Subject: [PATCH 38/74] - Add claiming particle effect when new towns are made. Adds a delay to the new town advice message as well. --- .../towny/listeners/TownyCustomListener.java | 25 ++++++++++++------- Towny/src/main/resources/ChangeLog.txt | 3 ++- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyCustomListener.java b/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyCustomListener.java index 729c426752..e776a2c36d 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyCustomListener.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyCustomListener.java @@ -100,17 +100,24 @@ public void onPlayerChangePlotEvent(PlayerChangePlotEvent event) { @EventHandler(priority = EventPriority.NORMAL) public void onPlayerCreateTown(NewTownEvent event) { - Town town = event.getTown(); - double upkeep = TownySettings.getTownUpkeepCost(town); - if (TownyEconomyHandler.isActive() && TownySettings.isTaxingDaily() && upkeep > 0) { - String cost = TownyEconomyHandler.getFormattedBalance(upkeep); - String time = TimeMgmt.formatCountdownTime(TimeMgmt.townyTime(true)); - TownyMessaging.sendTownMessagePrefixed(town, Translatable.of("msg_new_town_advice", cost, time)); - } + final Town town = event.getTown(); + Resident mayor = town.getMayor(); + if (mayor.isOnline() && town.hasHomeBlock()) + CellSurface.getCellSurface(town.getHomeBlockOrNull().getWorldCoord()).runClaimingParticleOverSurfaceAtPlayer(mayor.getPlayer()); + + // Run the bank warning with a 10 second delay. + plugin.getScheduler().runLater(() -> { + double upkeep = TownySettings.getTownUpkeepCost(town); + if (TownyEconomyHandler.isActive() && TownySettings.isTaxingDaily() && upkeep > 0) { + String cost = TownyEconomyHandler.getFormattedBalance(upkeep); + String time = TimeMgmt.formatCountdownTime(TimeMgmt.townyTime(true)); + TownyMessaging.sendTownMessagePrefixed(town, Translatable.of("msg_new_town_advice", cost, time)); + } + }, 200L); + //TODO: at some point it might be nice to have a written_book given to mayors // which could contain the above advice about depositing money, or containing // links to the commands page on the wiki. - } /** @@ -216,7 +223,7 @@ public void onTownClaim(TownClaimEvent event) { if (event.getTown().availableTownBlocks() <= TownySettings.getTownBlockRatio()) TownyMessaging.sendMsg(event.getResident(), Translatable.literal(Colors.Red).append(Translatable.of("msg_warning_you_are_almost_out_of_townblocks"))); } - + /** * Used to warn towns when they've lost a resident, so they know they're at risk * of having claims stolen in the takeoverclaim feature. diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index 9d7459bd7a..dda818d1c7 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9421,4 +9421,5 @@ v0.92.0.11: - Refactor the parseTownClaimCommand method. - Fix new outlaws being teleported when they have in fact left the town's borders. - Fix residents being able to see vanished online players who are in their town. - - Refactor the townRank method. \ No newline at end of file + - Refactor the townRank method. + - Add claiming particle effect when new towns are made. \ No newline at end of file From cad7580a0c83228c6fc4b8c8ce307cde65ff42fa Mon Sep 17 00:00:00 2001 From: LlmDl Date: Tue, 9 Jan 2024 18:04:00 -0600 Subject: [PATCH 39/74] Make showing claiming particles on new town obey the config setting. --- .../bukkit/towny/listeners/TownyCustomListener.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyCustomListener.java b/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyCustomListener.java index e776a2c36d..02b3d24fe3 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyCustomListener.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyCustomListener.java @@ -102,8 +102,8 @@ public void onPlayerChangePlotEvent(PlayerChangePlotEvent event) { public void onPlayerCreateTown(NewTownEvent event) { final Town town = event.getTown(); Resident mayor = town.getMayor(); - if (mayor.isOnline() && town.hasHomeBlock()) - CellSurface.getCellSurface(town.getHomeBlockOrNull().getWorldCoord()).runClaimingParticleOverSurfaceAtPlayer(mayor.getPlayer()); + if (mayor.isOnline() && town.hasHomeBlock() && TownySettings.isShowingClaimParticleEffect()) + CellSurface.getCellSurface(town.getHomeBlockOrNull().getWorldCoord()).runClaimingParticleOverSurfaceAtPlayer(mayor.getPlayer()); // Run the bank warning with a 10 second delay. plugin.getScheduler().runLater(() -> { From 5672b85fd7fcf8e0bfd2e7e2d0545fd7ceca5215 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Wed, 10 Jan 2024 11:51:40 -0600 Subject: [PATCH 40/74] New Crowdin updates (#7178) * Update source file en-US.yml * New translations en-us.yml (Chinese Simplified) * New translations en-us.yml (German) * New translations en-us.yml (Romanian) * New translations en-us.yml (French) * New translations en-us.yml (Spanish) * New translations en-us.yml (Bulgarian) * New translations en-us.yml (Czech) * New translations en-us.yml (Danish) * New translations en-us.yml (Hebrew) * New translations en-us.yml (Italian) * New translations en-us.yml (Japanese) * New translations en-us.yml (Korean) * New translations en-us.yml (Lithuanian) * New translations en-us.yml (Dutch) * New translations en-us.yml (Norwegian) * New translations en-us.yml (Polish) * New translations en-us.yml (Portuguese) * New translations en-us.yml (Russian) * New translations en-us.yml (Albanian) * New translations en-us.yml (Swedish) * New translations en-us.yml (Turkish) * New translations en-us.yml (Ukrainian) * New translations en-us.yml (Chinese Traditional) * New translations en-us.yml (Vietnamese) * New translations en-us.yml (Portuguese, Brazilian) * New translations en-us.yml (Indonesian) * New translations en-us.yml (Spanish, Argentina) * New translations en-us.yml (Spanish, Chile) * New translations en-us.yml (Spanish, Mexico) * New translations en-us.yml (Spanish, Uruguay) * New translations en-us.yml (Spanish, Venezuela) * New translations en-us.yml (Spanish, Ecuador) * New translations en-us.yml (Thai) * New translations en-us.yml (Azerbaijani) * New translations en-us.yml (English, United Kingdom) * New translations en-us.yml (Tagalog) * New translations en-us.yml (Pirate English) * New translations en-us.yml (Serbian (Latin)) * New translations en-us.yml (English (upside down)) * New translations en-us.yml (LOLCAT) * New translations en-us.yml (Classical Chinese) * Update source file en-US.yml --- Towny/src/main/resources/lang/az-AZ.yml | 1 + Towny/src/main/resources/lang/bg-BG.yml | 1 + Towny/src/main/resources/lang/cs-CZ.yml | 1 + Towny/src/main/resources/lang/da-DK.yml | 1 + Towny/src/main/resources/lang/de-DE.yml | 1 + Towny/src/main/resources/lang/en-GB.yml | 1 + Towny/src/main/resources/lang/en-PT.yml | 1 + Towny/src/main/resources/lang/en-UD.yml | 1 + Towny/src/main/resources/lang/es-AR.yml | 1 + Towny/src/main/resources/lang/es-CL.yml | 1 + Towny/src/main/resources/lang/es-EC.yml | 1 + Towny/src/main/resources/lang/es-ES.yml | 1 + Towny/src/main/resources/lang/es-MX.yml | 1 + Towny/src/main/resources/lang/es-UY.yml | 1 + Towny/src/main/resources/lang/es-VE.yml | 1 + Towny/src/main/resources/lang/fr-FR.yml | 1 + Towny/src/main/resources/lang/he-IL.yml | 1 + Towny/src/main/resources/lang/id-ID.yml | 1 + Towny/src/main/resources/lang/it-IT.yml | 1 + Towny/src/main/resources/lang/ja-JP.yml | 1 + Towny/src/main/resources/lang/ko-KR.yml | 1 + Towny/src/main/resources/lang/lol-US.yml | 1 + Towny/src/main/resources/lang/lt-LT.yml | 1 + Towny/src/main/resources/lang/lzh.yml | 1 + Towny/src/main/resources/lang/nl-NL.yml | 1 + Towny/src/main/resources/lang/no-NO.yml | 1 + Towny/src/main/resources/lang/pl-PL.yml | 1 + Towny/src/main/resources/lang/pt-BR.yml | 1 + Towny/src/main/resources/lang/pt-PT.yml | 1 + Towny/src/main/resources/lang/ro-RO.yml | 1 + Towny/src/main/resources/lang/ru-RU.yml | 1 + Towny/src/main/resources/lang/sq-AL.yml | 1 + Towny/src/main/resources/lang/sr-CS.yml | 1 + Towny/src/main/resources/lang/sv-SE.yml | 1 + Towny/src/main/resources/lang/th-TH.yml | 1 + Towny/src/main/resources/lang/tl-PH.yml | 1 + Towny/src/main/resources/lang/tr-TR.yml | 1 + Towny/src/main/resources/lang/uk-UA.yml | 1 + Towny/src/main/resources/lang/vi-VN.yml | 1 + Towny/src/main/resources/lang/zh-CN.yml | 1 + Towny/src/main/resources/lang/zh-TW.yml | 1 + 41 files changed, 41 insertions(+) diff --git a/Towny/src/main/resources/lang/az-AZ.yml b/Towny/src/main/resources/lang/az-AZ.yml index fbea7b983a..0f4e7fedb9 100644 --- a/Towny/src/main/resources/lang/az-AZ.yml +++ b/Towny/src/main/resources/lang/az-AZ.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lists the Trusted residents of a town." town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Şəhərə bağlı olmayan iddia sahəsi' mayor_help_4: 'Ətrafınızdakı radiusun x olduğunu iddia edin' mayor_help_5: 'Maksimum radius iddia' diff --git a/Towny/src/main/resources/lang/bg-BG.yml b/Towny/src/main/resources/lang/bg-BG.yml index 7b43b0ed0a..8544fa1f78 100644 --- a/Towny/src/main/resources/lang/bg-BG.yml +++ b/Towny/src/main/resources/lang/bg-BG.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lists the Trusted residents of a town." town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Заявена земя, която не е свързана към града' mayor_help_4: 'Изисквайте земя около вас в радиус Х' mayor_help_5: 'Изисквайте земя в максималния радиус' diff --git a/Towny/src/main/resources/lang/cs-CZ.yml b/Towny/src/main/resources/lang/cs-CZ.yml index cf327c6ae3..007d9827dc 100644 --- a/Towny/src/main/resources/lang/cs-CZ.yml +++ b/Towny/src/main/resources/lang/cs-CZ.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lists the Trusted residents of a town." town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Zaber území nepřipojené k tvému městu' mayor_help_4: 'Zaber území kolem sebe do vzdálenosti X' mayor_help_5: 'Zaber území do maximální vzdálenosti' diff --git a/Towny/src/main/resources/lang/da-DK.yml b/Towny/src/main/resources/lang/da-DK.yml index a9838faef7..6eca2209df 100644 --- a/Towny/src/main/resources/lang/da-DK.yml +++ b/Towny/src/main/resources/lang/da-DK.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lists the Trusted residents of a town." town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Gør krav på område som ikke er tilknyttet byen' mayor_help_4: 'Gør krav på områder rundt om dig med en radius på X' mayor_help_5: 'Gør krav på områder rundt om dig med den maximale radius' diff --git a/Towny/src/main/resources/lang/de-DE.yml b/Towny/src/main/resources/lang/de-DE.yml index 4bd1b85ad2..25f7cffff9 100644 --- a/Towny/src/main/resources/lang/de-DE.yml +++ b/Towny/src/main/resources/lang/de-DE.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lists the Trusted residents of a town." town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Anspruchsbereich grenzt nicht an die Stadt.' mayor_help_4: 'Beanspruche Land um dich herum in einem Radius von X' mayor_help_5: 'Beanspruche Land mit dem maximalen Radius' diff --git a/Towny/src/main/resources/lang/en-GB.yml b/Towny/src/main/resources/lang/en-GB.yml index a79fdfff5f..4f001c2b46 100644 --- a/Towny/src/main/resources/lang/en-GB.yml +++ b/Towny/src/main/resources/lang/en-GB.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lists the Trusted residents of a town." town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Claim area not attached to town' mayor_help_4: 'Claim around you to a radius of X' mayor_help_5: 'Claim to the maximum radius' diff --git a/Towny/src/main/resources/lang/en-PT.yml b/Towny/src/main/resources/lang/en-PT.yml index 690ba0cac1..f4edcb3ad5 100644 --- a/Towny/src/main/resources/lang/en-PT.yml +++ b/Towny/src/main/resources/lang/en-PT.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lists the Trusted residents of a town." town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Claim area not attached to town' mayor_help_4: 'Claim around you to a radius of X' mayor_help_5: 'Claim to the maximum radius' diff --git a/Towny/src/main/resources/lang/en-UD.yml b/Towny/src/main/resources/lang/en-UD.yml index 0e833ef726..39b7d29f68 100644 --- a/Towny/src/main/resources/lang/en-UD.yml +++ b/Towny/src/main/resources/lang/en-UD.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lists the Trusted residents of a town." town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Claim area not attached to town' mayor_help_4: 'Claim around you to a radius of X' mayor_help_5: 'Claim to the maximum radius' diff --git a/Towny/src/main/resources/lang/es-AR.yml b/Towny/src/main/resources/lang/es-AR.yml index 839bc3b7a0..bd05a5d6cc 100644 --- a/Towny/src/main/resources/lang/es-AR.yml +++ b/Towny/src/main/resources/lang/es-AR.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lists the Trusted residents of a town." town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Reclamar área no adjunta a la ciudad' mayor_help_4: 'Reclamar alrededor de ti a un radio X.' mayor_help_5: 'Reclamar al radio máximo.' diff --git a/Towny/src/main/resources/lang/es-CL.yml b/Towny/src/main/resources/lang/es-CL.yml index 2a5d3582b6..97abbfb7a8 100644 --- a/Towny/src/main/resources/lang/es-CL.yml +++ b/Towny/src/main/resources/lang/es-CL.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Ver los residentes de confianza de la ciudad." town_towntrust_help_0: "Confía en otra ciudad." town_towntrust_help_1: "Deja de confíar en otra ciudad." town_towntrust_help_2: "Ver las ciudades de confianza de la ciudad." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Reclamar área no adjunta a la ciudad' mayor_help_4: 'Reclamar alrededor de ti a un radio X.' mayor_help_5: 'Reclamar al radio máximo.' diff --git a/Towny/src/main/resources/lang/es-EC.yml b/Towny/src/main/resources/lang/es-EC.yml index 591bb50e15..4b388c684e 100644 --- a/Towny/src/main/resources/lang/es-EC.yml +++ b/Towny/src/main/resources/lang/es-EC.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lists the Trusted residents of a town." town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Reclamar área no adjunta a la ciudad' mayor_help_4: 'Reclamar alrededor de ti a un radio X.' mayor_help_5: 'Reclamar al radio máximo.' diff --git a/Towny/src/main/resources/lang/es-ES.yml b/Towny/src/main/resources/lang/es-ES.yml index 5d5d4e6d3b..0bf1b91dc4 100644 --- a/Towny/src/main/resources/lang/es-ES.yml +++ b/Towny/src/main/resources/lang/es-ES.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lists the Trusted residents of a town." town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Claimear area externa' mayor_help_4: 'Claimear area de un radio X' mayor_help_5: 'Claimear el máximo radio posible' diff --git a/Towny/src/main/resources/lang/es-MX.yml b/Towny/src/main/resources/lang/es-MX.yml index ecab186628..c52e30f8ce 100644 --- a/Towny/src/main/resources/lang/es-MX.yml +++ b/Towny/src/main/resources/lang/es-MX.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lists the Trusted residents of a town." town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Reclamar área no adjunta a la ciudad' mayor_help_4: 'Reclamar alrededor de ti a un radio X.' mayor_help_5: 'Reclamar al radio máximo.' diff --git a/Towny/src/main/resources/lang/es-UY.yml b/Towny/src/main/resources/lang/es-UY.yml index 591bb50e15..4b388c684e 100644 --- a/Towny/src/main/resources/lang/es-UY.yml +++ b/Towny/src/main/resources/lang/es-UY.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lists the Trusted residents of a town." town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Reclamar área no adjunta a la ciudad' mayor_help_4: 'Reclamar alrededor de ti a un radio X.' mayor_help_5: 'Reclamar al radio máximo.' diff --git a/Towny/src/main/resources/lang/es-VE.yml b/Towny/src/main/resources/lang/es-VE.yml index 591bb50e15..4b388c684e 100644 --- a/Towny/src/main/resources/lang/es-VE.yml +++ b/Towny/src/main/resources/lang/es-VE.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lists the Trusted residents of a town." town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Reclamar área no adjunta a la ciudad' mayor_help_4: 'Reclamar alrededor de ti a un radio X.' mayor_help_5: 'Reclamar al radio máximo.' diff --git a/Towny/src/main/resources/lang/fr-FR.yml b/Towny/src/main/resources/lang/fr-FR.yml index 3803c69e6d..0ceaaf7b3c 100644 --- a/Towny/src/main/resources/lang/fr-FR.yml +++ b/Towny/src/main/resources/lang/fr-FR.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lists the Trusted residents of a town." town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Parcelle non attachée à la ville' mayor_help_4: 'Annexe autour de vous dans un rayon de X' mayor_help_5: 'Annexe au rayon maximal' diff --git a/Towny/src/main/resources/lang/he-IL.yml b/Towny/src/main/resources/lang/he-IL.yml index 95fc27204b..7d8f52adb0 100644 --- a/Towny/src/main/resources/lang/he-IL.yml +++ b/Towny/src/main/resources/lang/he-IL.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lists the Trusted residents of a town." town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'תבע בעלות של שטח שלא מחובר לעיר' mayor_help_4: 'מסביבך X תבע בעלות ברדיוס של' mayor_help_5: 'תבע בעלות עד הרדיוס המקסימלי' diff --git a/Towny/src/main/resources/lang/id-ID.yml b/Towny/src/main/resources/lang/id-ID.yml index 066b9718f7..f0e438d7d7 100644 --- a/Towny/src/main/resources/lang/id-ID.yml +++ b/Towny/src/main/resources/lang/id-ID.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lists the Trusted residents of a town." town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Wilayah yang ingin di ambil tidak berdekatan dengan kota' mayor_help_4: 'Ambil wilayah di sekitar mu sampai radius X' mayor_help_5: 'Ambil wilayah sampai radius maksimal' diff --git a/Towny/src/main/resources/lang/it-IT.yml b/Towny/src/main/resources/lang/it-IT.yml index 9588f17b62..adf8eee75f 100644 --- a/Towny/src/main/resources/lang/it-IT.yml +++ b/Towny/src/main/resources/lang/it-IT.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lists the Trusted residents of a town." town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Claima una zona non confinante con la città' mayor_help_4: 'Claima intorno a te in un raggio X' mayor_help_5: 'Claima per il raggio massimo' diff --git a/Towny/src/main/resources/lang/ja-JP.yml b/Towny/src/main/resources/lang/ja-JP.yml index 746da44ba7..4ab6acc595 100644 --- a/Towny/src/main/resources/lang/ja-JP.yml +++ b/Towny/src/main/resources/lang/ja-JP.yml @@ -129,6 +129,7 @@ town_trust_help_2: "町の信頼できる住民をリストします。" town_towntrust_help_0: "町を信頼できる町として追加します。" town_towntrust_help_1: "町をその町内の信頼済みとして削除します。" town_towntrust_help_2: "町の信頼できる町をリストします。" +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: '町でないエリアの領有を主張する' mayor_help_4: 'あなたの周囲Xブロック分(円又は四角)のエリアの領有を主張する' mayor_help_5: '自動で最大半径のエリアの領有を主張する' diff --git a/Towny/src/main/resources/lang/ko-KR.yml b/Towny/src/main/resources/lang/ko-KR.yml index 762287f192..9fef214591 100644 --- a/Towny/src/main/resources/lang/ko-KR.yml +++ b/Towny/src/main/resources/lang/ko-KR.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lists the Trusted residents of a town." town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: '도시에 인접하지 않는 토지 구매' mayor_help_4: '반지름이 X인 땅을 원형으로 구매' mayor_help_5: '최대 반지름 내의 토지 구매' diff --git a/Towny/src/main/resources/lang/lol-US.yml b/Towny/src/main/resources/lang/lol-US.yml index 11ad7ad77f..1487c5972f 100644 --- a/Towny/src/main/resources/lang/lol-US.yml +++ b/Towny/src/main/resources/lang/lol-US.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lists the Trusted residents of a town." town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Claim area not attached to town' mayor_help_4: 'Claim around you to a radius of X' mayor_help_5: 'Claim to the maximum radius' diff --git a/Towny/src/main/resources/lang/lt-LT.yml b/Towny/src/main/resources/lang/lt-LT.yml index b518562e53..d4bc5dc642 100644 --- a/Towny/src/main/resources/lang/lt-LT.yml +++ b/Towny/src/main/resources/lang/lt-LT.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Išvardija miesto patikimus žmones." town_towntrust_help_0: "Prideda miestą į miesto patikimų miestų sąrašą." town_towntrust_help_1: "Pašalina miestą iš miesto patikimų miestų sąrašo." town_towntrust_help_2: "Išvardija miesto patikimus miestus." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Užimti teritoriją, kuri nebūtinai liečiasi su pagrindine miesto teritorija' mayor_help_4: 'Užimti teritoriją aplink save X spinduliu' mayor_help_5: 'Užimti teritoriją didžiausiu spinduliu' diff --git a/Towny/src/main/resources/lang/lzh.yml b/Towny/src/main/resources/lang/lzh.yml index c14195f599..ef0eb5ffeb 100644 --- a/Towny/src/main/resources/lang/lzh.yml +++ b/Towny/src/main/resources/lang/lzh.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lists the Trusted residents of a town." town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: '你所選擇的地段不在市鎮旁' mayor_help_4: '取得周遭X格內的地段' mayor_help_5: '取得最大半徑內的地段' diff --git a/Towny/src/main/resources/lang/nl-NL.yml b/Towny/src/main/resources/lang/nl-NL.yml index 5da64edc86..ab55909c59 100644 --- a/Towny/src/main/resources/lang/nl-NL.yml +++ b/Towny/src/main/resources/lang/nl-NL.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lists the Trusted residents of a town." town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Claim gebied niet gekoppeld aan stad' mayor_help_4: 'Claim om je heen in een radius van X' mayor_help_5: 'Claim in de maximale radius' diff --git a/Towny/src/main/resources/lang/no-NO.yml b/Towny/src/main/resources/lang/no-NO.yml index 5c22fd2e74..3cbdc36d62 100644 --- a/Towny/src/main/resources/lang/no-NO.yml +++ b/Towny/src/main/resources/lang/no-NO.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lists the Trusted residents of a town." town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Kravsområde ikke festet til byen' mayor_help_4: 'Gjør krav om deg i en radius av X' mayor_help_5: 'Gjør krav på maksimal radius' diff --git a/Towny/src/main/resources/lang/pl-PL.yml b/Towny/src/main/resources/lang/pl-PL.yml index 6f4d164b1d..e3d8b5a270 100644 --- a/Towny/src/main/resources/lang/pl-PL.yml +++ b/Towny/src/main/resources/lang/pl-PL.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lista zaufanch mieszkańców w mieście." town_towntrust_help_0: "Dodaje miasto do grona zaufanych twojego miata." town_towntrust_help_1: "Usuwa miasto z grona zaufanych twojego miasta." town_towntrust_help_2: "Lista zaufanych miast podanego miasta." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Pozyskaj teren nieprzylegajacy do miasta' mayor_help_4: 'Pozyskaj dookoła w promieniu X' mayor_help_5: 'Pozyskuje wszystko w maksymalnym promieniu' diff --git a/Towny/src/main/resources/lang/pt-BR.yml b/Towny/src/main/resources/lang/pt-BR.yml index 1130350f9c..96a676da6e 100644 --- a/Towny/src/main/resources/lang/pt-BR.yml +++ b/Towny/src/main/resources/lang/pt-BR.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lista os residentes confiáveis de uma cidade." town_towntrust_help_0: "Adiciona uma cidade como confiável na cidade." town_towntrust_help_1: "Remove uma cidade como confiável na cidade." town_towntrust_help_2: "Lista as cidades confiáveis de uma cidade." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Reivindicar área separada da cidade' mayor_help_4: 'Reivindicar à sua volta num raio de X' mayor_help_5: 'Reivindicar no raio máximo' diff --git a/Towny/src/main/resources/lang/pt-PT.yml b/Towny/src/main/resources/lang/pt-PT.yml index bc0a7d9980..cb9331b367 100644 --- a/Towny/src/main/resources/lang/pt-PT.yml +++ b/Towny/src/main/resources/lang/pt-PT.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lists the Trusted residents of a town." town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Área reivindicada separada do resto da cidade' mayor_help_4: 'Reivindicar à tua volta num raio de X' mayor_help_5: 'Anexar no maior raio possível' diff --git a/Towny/src/main/resources/lang/ro-RO.yml b/Towny/src/main/resources/lang/ro-RO.yml index 6019f510fb..f4cc71a5e1 100644 --- a/Towny/src/main/resources/lang/ro-RO.yml +++ b/Towny/src/main/resources/lang/ro-RO.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lists the Trusted residents of a town." town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Zonă de cucerire neataşată oraşului' mayor_help_4: 'Cucereşte în jurul tău într-o rază de X' mayor_help_5: 'Cucereşte la rază maximă' diff --git a/Towny/src/main/resources/lang/ru-RU.yml b/Towny/src/main/resources/lang/ru-RU.yml index a84a09f15f..d1d56f5911 100644 --- a/Towny/src/main/resources/lang/ru-RU.yml +++ b/Towny/src/main/resources/lang/ru-RU.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Показывает доверенных в этом гор town_towntrust_help_0: "Делает город доверенным в городе." town_towntrust_help_1: "Делает город не доверенным в городе." town_towntrust_help_2: "Показывает доверенные в этом городе города." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Участок не прилегает к городу' mayor_help_4: 'Заприватить местность в радиусе X вокруг вас' mayor_help_5: 'Заприватить максимальный радиус' diff --git a/Towny/src/main/resources/lang/sq-AL.yml b/Towny/src/main/resources/lang/sq-AL.yml index 68d9f440e3..b5a48be825 100644 --- a/Towny/src/main/resources/lang/sq-AL.yml +++ b/Towny/src/main/resources/lang/sq-AL.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lists the Trusted residents of a town." town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Claim area not attached to town' mayor_help_4: 'Claim around you to a radius of X' mayor_help_5: 'Claim to the maximum radius' diff --git a/Towny/src/main/resources/lang/sr-CS.yml b/Towny/src/main/resources/lang/sr-CS.yml index 2de8575f6b..44d543f0de 100644 --- a/Towny/src/main/resources/lang/sr-CS.yml +++ b/Towny/src/main/resources/lang/sr-CS.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lists the Trusted residents of a town." town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Claim-ujte oblast koja nije vezana za grad' mayor_help_4: 'Claim-ujte oko Vas do poluprečnika X' mayor_help_5: 'Claim-ujte do maksimalnog poluprečnika' diff --git a/Towny/src/main/resources/lang/sv-SE.yml b/Towny/src/main/resources/lang/sv-SE.yml index bbaaf2a21a..7fa4af5658 100644 --- a/Towny/src/main/resources/lang/sv-SE.yml +++ b/Towny/src/main/resources/lang/sv-SE.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lists the Trusted residents of a town." town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Marken är inte sammankopplad med din stad.' mayor_help_4: 'Köp marken omkring dig med en radius på X' mayor_help_5: 'Köp all mark du kan åt alla håll.' diff --git a/Towny/src/main/resources/lang/th-TH.yml b/Towny/src/main/resources/lang/th-TH.yml index 619ae6a0e2..dec934e944 100644 --- a/Towny/src/main/resources/lang/th-TH.yml +++ b/Towny/src/main/resources/lang/th-TH.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lists the Trusted residents of a town." town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Claim พื้นที่ไม่ติดเมือง' mayor_help_4: 'Claim รอบตัวคุณในรัศมี X' mayor_help_5: 'Claim ในรัศมีสูงสุด' diff --git a/Towny/src/main/resources/lang/tl-PH.yml b/Towny/src/main/resources/lang/tl-PH.yml index a40fe22afd..3e365358ea 100644 --- a/Towny/src/main/resources/lang/tl-PH.yml +++ b/Towny/src/main/resources/lang/tl-PH.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lists the Trusted residents of a town." town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Ang angkinin ay hindi kalakip sa bayan' mayor_help_4: 'Pwede mo angkinin ang paligid mo hangang sa radius nang X' mayor_help_5: 'Angkinin hangang sa pinakamataas na radius' diff --git a/Towny/src/main/resources/lang/tr-TR.yml b/Towny/src/main/resources/lang/tr-TR.yml index 4c973b6fc1..ddb89da742 100644 --- a/Towny/src/main/resources/lang/tr-TR.yml +++ b/Towny/src/main/resources/lang/tr-TR.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lists the Trusted residents of a town." town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Talep alanı şehire bağlı değil' mayor_help_4: 'Etrafınızda X yarıçapına kadar hak iddia edin' mayor_help_5: 'Maksimum yarıçap için hak talebinde bulunun' diff --git a/Towny/src/main/resources/lang/uk-UA.yml b/Towny/src/main/resources/lang/uk-UA.yml index 6532b53f33..0ae7ccd3f7 100644 --- a/Towny/src/main/resources/lang/uk-UA.yml +++ b/Towny/src/main/resources/lang/uk-UA.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Список довірених жителів(гравці town_towntrust_help_0: "Додати місто як довірене в місті." town_towntrust_help_1: "Видалити місто як довірене в місті." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Територія не приєднана до міста' mayor_help_4: 'Привласнити місцевість в радіусі X навколо вас' mayor_help_5: 'Привласнити максимальний радіус' diff --git a/Towny/src/main/resources/lang/vi-VN.yml b/Towny/src/main/resources/lang/vi-VN.yml index ea8b4d3783..d792178f11 100644 --- a/Towny/src/main/resources/lang/vi-VN.yml +++ b/Towny/src/main/resources/lang/vi-VN.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lists the Trusted residents of a town." town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: 'Chiếm khu vực không thuộc thị trấn' mayor_help_4: 'Chiếm khu vực xung quanh bạn trong bán kính X' mayor_help_5: 'Chiếm theo bán kính lớn nhất' diff --git a/Towny/src/main/resources/lang/zh-CN.yml b/Towny/src/main/resources/lang/zh-CN.yml index 24dee305f7..35c3fc091c 100644 --- a/Towny/src/main/resources/lang/zh-CN.yml +++ b/Towny/src/main/resources/lang/zh-CN.yml @@ -129,6 +129,7 @@ town_trust_help_2: "列出一个城镇中受信任的玩家。" town_towntrust_help_0: "在这个城镇中,增加一个受信任的城镇。" town_towntrust_help_1: "在这个城镇中,移除一个受信任的城镇。" town_towntrust_help_2: "列出一个城镇所信任的城镇。" +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: '你所选择的区域不附属于城镇' mayor_help_4: '声明你附近半径为X的区块' mayor_help_5: '声明最大半径内的所有区块' diff --git a/Towny/src/main/resources/lang/zh-TW.yml b/Towny/src/main/resources/lang/zh-TW.yml index d7da466bb7..ae400e91ce 100644 --- a/Towny/src/main/resources/lang/zh-TW.yml +++ b/Towny/src/main/resources/lang/zh-TW.yml @@ -129,6 +129,7 @@ town_trust_help_2: "Lists the Trusted residents of a town." town_towntrust_help_0: "Adds a town as Trusted in the town." town_towntrust_help_1: "Removes a town as Trusted in the town." town_towntrust_help_2: "Lists the Trusted towns of a town." +town_buy_help: "Purchases bonus townblocks to increase the claim limit of the town." mayor_help_3: '你所選擇的地段不在市鎮旁' mayor_help_4: '取得周遭X格內的地段' mayor_help_5: '取得最大半徑內的地段' From 74e63dd321147dd4de33aef04db2e9ef9bc35acd Mon Sep 17 00:00:00 2001 From: LlmDl Date: Wed, 10 Jan 2024 11:55:34 -0600 Subject: [PATCH 41/74] - Bump version for release. --- README.md | 2 +- Towny/pom.xml | 2 +- Towny/src/main/resources/ChangeLog.txt | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b666fca5f0..3536d6b6b5 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ ___ - + diff --git a/Towny/pom.xml b/Towny/pom.xml index 71ca45ddf0..ecdc270eac 100644 --- a/Towny/pom.xml +++ b/Towny/pom.xml @@ -13,7 +13,7 @@ townyjar - 0.100.0.22 + 0.100.1.0 diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index dda818d1c7..b66f455904 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9422,4 +9422,6 @@ v0.92.0.11: - Fix new outlaws being teleported when they have in fact left the town's borders. - Fix residents being able to see vanished online players who are in their town. - Refactor the townRank method. - - Add claiming particle effect when new towns are made. \ No newline at end of file + - Add claiming particle effect when new towns are made. +0.100.1.0: + - Bump version for release. \ No newline at end of file From 4b1c485f538a9bf043daa09f736c67648f196d16 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Wed, 10 Jan 2024 13:50:00 -0600 Subject: [PATCH 42/74] Refactor town join command, which was not able to be run from the (#7183) console. --- .../bukkit/towny/command/TownCommand.java | 92 +++++-------------- 1 file changed, 24 insertions(+), 68 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 e861e4b409..1d16019999 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 @@ -3101,79 +3101,35 @@ private void parseTownReclaimCommand(final Player player) throws NoPermissionExc 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] - * - * @param sender - Sender of command. - * @param args - Current command arguments. - */ - public static void parseTownJoin(CommandSender sender, String[] args) { + private static void parseTownJoin(Player player, String[] args) throws TownyException { + checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_JOIN.getNode()); + Resident resident = getResidentOrThrow(player); + if (resident.hasTown()) + throw new TownyException(Translatable.of("msg_err_already_res2", "You")); - try { - Resident resident; - Town town; - String residentName, townName, contextualResidentName; - boolean console = false; - String exceptionMsg; - - if (sender instanceof Player) { - // Player - if (args.length < 1) - 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"; - exceptionMsg = "msg_err_already_res2"; - } else { - // Console - if (args.length < 2) - throw new TownyException(Translatable.of("msg_usage", "town join [resident] [town]")); - - residentName = args[0]; - townName = args[1]; - contextualResidentName = residentName; - exceptionMsg = "msg_err_already_res"; - } - - resident = getResidentOrThrow(residentName); - town = getTownOrThrow(townName); - - // Check if resident is currently in a town. - if (resident.hasTown()) - throw new TownyException(Translatable.of(exceptionMsg, contextualResidentName)); - - if (!console) { - // Check if town is town is free to join. - if (!town.isOpen()) - throw new TownyException(Translatable.of("msg_err_not_open", town.getFormattedName())); - if (town.hasNation() && TownySettings.getMaxResidentsPerNation() > 0 && town.getNationOrNull().getResidents().size() >= TownySettings.getMaxResidentsPerNation()) - throw new TownyException(Translatable.of("msg_err_cannot_join_nation_over_resident_limit", TownySettings.getMaxResidentsPerNation())); - if (TownySettings.getMaxResidentsPerTown() > 0 && town.getResidents().size() >= TownySettings.getMaxResidentsForTown(town)) - throw new TownyException(Translatable.of("msg_err_max_residents_per_town_reached", TownySettings.getMaxResidentsForTown(town))); - if (TownySettings.getMaxNumResidentsWithoutNation() > 0 && !town.hasNation() && town.getResidents().size() >= TownySettings.getMaxNumResidentsWithoutNation()) - throw new TownyException(Translatable.of("msg_err_unable_to_add_more_residents_without_nation", TownySettings.getMaxNumResidentsWithoutNation())); - if (town.hasOutlaw(resident)) - throw new TownyException(Translatable.of("msg_err_outlaw_in_open_town")); - } + Town town = getTownOrThrow(args[0]); - BukkitTools.ifCancelledThenThrow(new TownPreAddResidentEvent(town, resident)); + // Check if town is town is free to join. + if (!town.isOpen()) + throw new TownyException(Translatable.of("msg_err_not_open", town.getFormattedName())); - // Check if player is already in selected town (Pointless) - // Then add player to town. - townAddResident(town, resident); + if (town.hasNation() && TownySettings.getMaxResidentsPerNation() > 0 && town.getNationOrNull().getResidents().size() >= TownySettings.getMaxResidentsPerNation()) + throw new TownyException(Translatable.of("msg_err_cannot_join_nation_over_resident_limit", TownySettings.getMaxResidentsPerNation())); - // Resident was added successfully. - TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_join_town", resident.getName())); + if (TownySettings.getMaxResidentsPerTown() > 0 && town.getResidents().size() >= TownySettings.getMaxResidentsForTown(town)) + throw new TownyException(Translatable.of("msg_err_max_residents_per_town_reached", TownySettings.getMaxResidentsForTown(town))); - } catch (TownyException e) { - TownyMessaging.sendErrorMsg(sender, e.getMessage(sender)); - } catch (Exception e) { - TownyMessaging.sendErrorMsg(sender, e.getMessage()); - } + if (TownySettings.getMaxNumResidentsWithoutNation() > 0 && !town.hasNation() && town.getResidents().size() >= TownySettings.getMaxNumResidentsWithoutNation()) + throw new TownyException(Translatable.of("msg_err_unable_to_add_more_residents_without_nation", TownySettings.getMaxNumResidentsWithoutNation())); + + if (town.hasOutlaw(resident)) + throw new TownyException(Translatable.of("msg_err_outlaw_in_open_town")); + + BukkitTools.ifCancelledThenThrow(new TownPreAddResidentEvent(town, resident)); + + townAddResident(town, resident); + + TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_join_town", resident.getName())); } /** From 9e0c53dfca52e5f4d0cb15ff5400bea265f2d704 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Wed, 10 Jan 2024 13:50:52 -0600 Subject: [PATCH 43/74] Refactor the TownyWorldCommand. (#7181) Switch statements and dropping the static globalWorld. --- .../towny/command/TownyWorldCommand.java | 553 +++++++++--------- 1 file changed, 284 insertions(+), 269 deletions(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownyWorldCommand.java b/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownyWorldCommand.java index 6bcbd7ee32..a3a0001888 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownyWorldCommand.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownyWorldCommand.java @@ -9,6 +9,7 @@ import com.palmergames.bukkit.towny.confirmations.Confirmation; import com.palmergames.bukkit.towny.TownyCommandAddonAPI.CommandType; import com.palmergames.bukkit.towny.event.TownBlockSettingsChangedEvent; +import com.palmergames.bukkit.towny.exceptions.NoPermissionException; import com.palmergames.bukkit.towny.exceptions.TownyException; import com.palmergames.bukkit.towny.object.TownyWorld; import com.palmergames.bukkit.towny.object.Translatable; @@ -33,16 +34,10 @@ import java.util.Locale; import java.util.Optional; -/** - * Send a list of all general townyworld help commands to player Command: - * /townyworld - */ - public class TownyWorldCommand extends BaseCommand implements CommandExecutor { private final Towny plugin; - private static TownyWorld globalWorld; // TODO: Make this not static, should be passed through the methods instead. - + private static final List townyWorldTabCompletes = Arrays.asList( "list", "toggle", @@ -86,13 +81,16 @@ public TownyWorldCommand(Towny instance) { @Override public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String commandLabel, String[] args) { - if (plugin.isError() && sender instanceof Player) { TownyMessaging.sendErrorMsg(sender, "Locked in Safe mode!"); return true; } - - parseWorldCommand(sender, args); + + try { + parseWorldCommand(sender, args); + } catch (TownyException e) { + TownyMessaging.sendErrorMsg(sender, e.getMessage(sender)); + } return true; } @@ -128,79 +126,67 @@ else if (showWorlds && BukkitTools.getWorldNames(true).contains(args[0].toLowerC return Collections.emptyList(); } - public void parseWorldCommand(CommandSender sender, String[] split) { + public void parseWorldCommand(CommandSender sender, String[] split) throws TownyException { - if (sender instanceof Player player) { - if (split.length > 0 && !townyWorldTabCompletes.contains(split[0].toLowerCase(Locale.ROOT)) && TownyAPI.getInstance().getTownyWorld(split[0]) != null) { - globalWorld = TownyAPI.getInstance().getTownyWorld(split[0]); - split = StringMgmt.remFirstArg(split); - } else - globalWorld = TownyAPI.getInstance().getTownyWorld(player.getWorld()); - - if (globalWorld == null) { - TownyMessaging.sendErrorMsg(player, Translatable.of("msg_area_not_recog")); - return; - } - } else { + TownyWorld world; + if (!(sender instanceof Player player)) { if (split.length == 0) { HelpMenu.TOWNYWORLD_HELP_CONSOLE.send(sender); return; } - - globalWorld = TownyAPI.getInstance().getTownyWorld(split[0]); - if (globalWorld == null) { + + world = TownyAPI.getInstance().getTownyWorld(split[0]); + if (world == null) { Translatable error = Translatable.of("msg_err_invalid_townyworld", split[0]); - + if (townyWorldTabCompletes.contains(split[0].toLowerCase(Locale.ROOT))) error = Translatable.of("msg_err_enter_world_name_first"); - - TownyMessaging.sendErrorMsg(sender, error); - return; + + throw new TownyException(error); } split = StringMgmt.remFirstArg(split); + } else { // We have a Player using the /tw command. + if (split.length > 0 && !townyWorldTabCompletes.contains(split[0].toLowerCase(Locale.ROOT)) && TownyAPI.getInstance().getTownyWorld(split[0]) != null) { + world = TownyAPI.getInstance().getTownyWorld(split[0]); + split = StringMgmt.remFirstArg(split); + } else + world = TownyAPI.getInstance().getTownyWorld(player.getWorld()); + + if (world == null) + throw new TownyException(Translatable.of("msg_area_not_recog")); } if (split.length == 0) { - TownyMessaging.sendStatusScreen(sender, TownyFormatter.getStatus(globalWorld, sender)); + TownyMessaging.sendStatusScreen(sender, TownyFormatter.getStatus(world, sender)); return; } - try { - - if (split[0].equalsIgnoreCase("?")) { - if (sender instanceof Player) - HelpMenu.TOWNYWORLD_HELP.send(sender); - else - HelpMenu.TOWNYWORLD_HELP_CONSOLE.send(sender); - } else if (split[0].equalsIgnoreCase("list")) { - - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_LIST.getNode()); - - listWorlds(sender); - - } else if (split[0].equalsIgnoreCase("set")) { - - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_SET.getNode()); - - worldSet(sender, StringMgmt.remFirstArg(split)); - - } else if (split[0].equalsIgnoreCase("toggle")) { - - worldToggle(sender, StringMgmt.remFirstArg(split)); - } else if (TownyCommandAddonAPI.hasCommand(CommandType.TOWNYWORLD, split[0])) { + if (split[0].equalsIgnoreCase("?")) { + if (sender instanceof Player) + HelpMenu.TOWNYWORLD_HELP.send(sender); + else + HelpMenu.TOWNYWORLD_HELP_CONSOLE.send(sender); + return; + } + + String[] subArgs = StringMgmt.remFirstArg(split); + switch (split[0].toLowerCase(Locale.ROOT)) { + case "list" -> listWorlds(sender); + case "set" -> worldSet(sender, world, subArgs); + case "toggle" -> worldToggle(sender, world, subArgs); + default -> { + if (TownyCommandAddonAPI.hasCommand(CommandType.TOWNYWORLD, split[0])) { TownyCommandAddonAPI.getAddonCommand(CommandType.TOWNYWORLD, split[0]).execute(sender, "townyworld", split); - } else { - TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_err_invalid_property", "townyworld")); + return; } + TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_err_invalid_property", "townyworld")); + }} - } catch (TownyException e) { - TownyMessaging.sendErrorMsg(sender, e.getMessage(sender)); - } } - public void listWorlds(CommandSender sender) { - + public void listWorlds(CommandSender sender) throws NoPermissionException { + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_LIST.getNode()); TownyMessaging.sendMessage(sender, ChatTools.formatTitle(Translatable.of("world_plu").forLocale(sender))); ArrayList formattedList = new ArrayList<>(); @@ -213,261 +199,290 @@ public void listWorlds(CommandSender sender) { TownyMessaging.sendMessage(sender, ChatTools.list(formattedList)); } - public void worldToggle(CommandSender sender, String[] split) throws TownyException { + public void worldToggle(CommandSender sender, TownyWorld world, String[] split) throws TownyException { if (split.length == 0 ) { - if (sender instanceof Player) + if (sender instanceof Player) HelpMenu.TOWNYWORLD_TOGGLE.send(sender); else HelpMenu.TOWNYWORLD_TOGGLE_CONSOLE.send(sender); + return; + } - } else { + if (!world.isUsingTowny() && !split[0].equalsIgnoreCase("usingtowny")) + throw new TownyException(Translatable.of("msg_err_usingtowny_disabled")); - if (!globalWorld.isUsingTowny() && !split[0].equalsIgnoreCase("usingtowny")) - throw new TownyException(Translatable.of("msg_err_usingtowny_disabled")); + Optional choice = Optional.empty(); + if (split.length == 2) { + choice = parseToggleChoice(split[1]); + } - Optional choice = Optional.empty(); - if (split.length == 2) { - choice = parseToggleChoice(split[1]); + switch (split[0].toLowerCase(Locale.ROOT)) { + case "claimable" -> toggleClaimable(sender, world, choice); + case "usingtowny" -> toggleUsingTowny(sender, world, choice); + case "warallowed" -> toggleWarAllowed(sender, world, choice); + case "pvp" -> togglePVP(sender, world, choice); + case "forcepvp" -> toggleForcePVP(sender, world, choice); + case "friendlyfire" -> toggleFriendlyFire(sender, world, choice); + case "explosion" -> toggleExplosion(sender, world, choice); + case "forceexplosion" -> toggleForceExplosion(sender, world, choice); + case "fire" -> toggleFire(sender, world, choice); + case "forcefire" -> toggleForceFire(sender, world, choice); + case "townmobs" -> toggleTownMobs(sender, world, choice); + case "worldmobs" -> toggleWorldMobs(sender, world, choice); + case "wildernessmobs" -> toggleWildernessMobs(sender, world, choice); + case "revertunclaim" -> toggleRevertUnclaim(sender, world, choice); + case "revertentityexpl" -> toggleRevertEntityExpl(sender, world, choice); + case "revertblockexpl" -> toggleRevertBlockExpl(sender, world, choice); + case "plotcleardelete" -> togglePlotClearDelete(sender, world, choice); + case "unclaimblockdelete" -> toggleUnclaimBlockDelete(sender, world, choice); + case "unclaimentitydelete" -> toggleUnclaimEntityDelete(sender, world, choice); + case "wildernessuse" -> toggleWildernessUse(sender, world, split); + default -> { + if (TownyCommandAddonAPI.hasCommand(CommandType.TOWNYWORLD_TOGGLE, split[0])) { + TownyCommandAddonAPI.getAddonCommand(CommandType.TOWNYWORLD_TOGGLE, split[0]).execute(sender, "townyworld", split); + } else { + TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_err_invalid_property", "'" + split[0] + "'")); + return; } + }} - if (split[0].equalsIgnoreCase("claimable")) { - - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_CLAIMABLE.getNode()); - globalWorld.setClaimable(choice.orElse(!globalWorld.isClaimable())); - TownyMessaging.sendMsg(sender, Translatable.of("msg_set_claim", globalWorld.getName(), formatBool(globalWorld.isClaimable()))); - - } else if (split[0].equalsIgnoreCase("usingtowny")) { + world.save(); - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_USINGTOWNY.getNode()); - globalWorld.setUsingTowny(choice.orElse(!globalWorld.isUsingTowny())); - plugin.resetCache(); - TownyMessaging.sendMsg(sender, globalWorld.isUsingTowny() ? Translatable.of("msg_set_use_towny_on") : Translatable.of("msg_set_use_towny_off")); - - // Towny might be getting shut off in a world in order to stop the revert-on-unclaim feature, here we stop any active reverts. - if (!globalWorld.isUsingTowny() && globalWorld.isUsingPlotManagementRevert()) - TownyRegenAPI.turnOffRevertOnUnclaimForWorld(globalWorld); - - } else if (split[0].equalsIgnoreCase("warallowed")) { - - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_WARALLOWED.getNode()); - globalWorld.setWarAllowed(choice.orElse(!globalWorld.isWarAllowed())); - plugin.resetCache(); - TownyMessaging.sendMsg(sender, globalWorld.isWarAllowed() ? Translatable.of("msg_set_war_allowed_on") : Translatable.of("msg_set_war_allowed_off")); - - } else if (split[0].equalsIgnoreCase("pvp")) { - - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_PVP.getNode()); - globalWorld.setPVP(choice.orElse(!globalWorld.isPVP())); - TownyMessaging.sendMsg(sender, Translatable.of("msg_changed_world_setting", "Global PVP", globalWorld.getName(), formatBool(globalWorld.isPVP()))); + //Change settings event + BukkitTools.fireEvent(new TownBlockSettingsChangedEvent(world)); + } - } else if (split[0].equalsIgnoreCase("forcepvp")) { + private void toggleClaimable(CommandSender sender, TownyWorld world, Optional choice) throws NoPermissionException { + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_CLAIMABLE.getNode()); + world.setClaimable(choice.orElse(!world.isClaimable())); + TownyMessaging.sendMsg(sender, Translatable.of("msg_set_claim", world.getName(), formatBool(world.isClaimable()))); + } - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_FORCEPVP.getNode()); - globalWorld.setForcePVP(choice.orElse(!globalWorld.isForcePVP())); - TownyMessaging.sendMsg(sender, Translatable.of("msg_changed_world_setting", "Force town PVP", globalWorld.getName(), formatBool(globalWorld.isForcePVP(), "forced", "adjustable"))); + private void toggleUsingTowny(CommandSender sender, TownyWorld world, Optional choice) throws NoPermissionException { + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_USINGTOWNY.getNode()); + world.setUsingTowny(choice.orElse(!world.isUsingTowny())); + plugin.resetCache(); + TownyMessaging.sendMsg(sender, world.isUsingTowny() ? Translatable.of("msg_set_use_towny_on") : Translatable.of("msg_set_use_towny_off")); + + // Towny might be getting shut off in a world in order to stop the revert-on-unclaim feature, here we stop any active reverts. + if (!world.isUsingTowny() && world.isUsingPlotManagementRevert()) + TownyRegenAPI.turnOffRevertOnUnclaimForWorld(world); + } - } else if (split[0].equalsIgnoreCase("friendlyfire")) { + private void toggleWarAllowed(CommandSender sender, TownyWorld world, Optional choice) throws NoPermissionException { + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_WARALLOWED.getNode()); + world.setWarAllowed(choice.orElse(!world.isWarAllowed())); + plugin.resetCache(); + TownyMessaging.sendMsg(sender, world.isWarAllowed() ? Translatable.of("msg_set_war_allowed_on") : Translatable.of("msg_set_war_allowed_off")); + } - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_FRIENDLYFIRE.getNode()); - globalWorld.setFriendlyFire(choice.orElse(!globalWorld.isFriendlyFireEnabled())); - TownyMessaging.sendMsg(sender, Translatable.of("msg_changed_world_setting", "Friendly Fire", globalWorld.getName(), formatBool(globalWorld.isFriendlyFireEnabled()))); + private void togglePVP(CommandSender sender, TownyWorld world, Optional choice) throws NoPermissionException { + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_PVP.getNode()); + world.setPVP(choice.orElse(!world.isPVP())); + TownyMessaging.sendMsg(sender, Translatable.of("msg_changed_world_setting", "Global PVP", world.getName(), formatBool(world.isPVP()))); + } - } else if (split[0].equalsIgnoreCase("explosion")) { + private void toggleForcePVP(CommandSender sender, TownyWorld world, Optional choice) throws NoPermissionException { + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_FORCEPVP.getNode()); + world.setForcePVP(choice.orElse(!world.isForcePVP())); + TownyMessaging.sendMsg(sender, Translatable.of("msg_changed_world_setting", "Force town PVP", world.getName(), formatBool(world.isForcePVP(), "forced", "adjustable"))); + } - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_EXPLOSION.getNode()); - globalWorld.setExpl(choice.orElse(!globalWorld.isExpl())); - TownyMessaging.sendMsg(sender, Translatable.of("msg_changed_world_setting", "Explosions", globalWorld.getName(), formatBool(globalWorld.isExpl()))); + private void toggleFriendlyFire(CommandSender sender, TownyWorld world, Optional choice) throws NoPermissionException { + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_FRIENDLYFIRE.getNode()); + world.setFriendlyFire(choice.orElse(!world.isFriendlyFireEnabled())); + TownyMessaging.sendMsg(sender, Translatable.of("msg_changed_world_setting", "Friendly Fire", world.getName(), formatBool(world.isFriendlyFireEnabled()))); + } - } else if (split[0].equalsIgnoreCase("forceexplosion")) { + private void toggleExplosion(CommandSender sender, TownyWorld world, Optional choice) throws NoPermissionException { + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_EXPLOSION.getNode()); + world.setExpl(choice.orElse(!world.isExpl())); + TownyMessaging.sendMsg(sender, Translatable.of("msg_changed_world_setting", "Explosions", world.getName(), formatBool(world.isExpl()))); + } - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_FORCEEXPLOSION.getNode()); - globalWorld.setForceExpl(choice.orElse(!globalWorld.isForceExpl())); - TownyMessaging.sendMsg(sender, Translatable.of("msg_changed_world_setting", "Force town Explosions", globalWorld.getName(), formatBool(globalWorld.isForceExpl(), "forced", "adjustable"))); + private void toggleForceExplosion(CommandSender sender, TownyWorld world, Optional choice) throws NoPermissionException { + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_FORCEEXPLOSION.getNode()); + world.setForceExpl(choice.orElse(!world.isForceExpl())); + TownyMessaging.sendMsg(sender, Translatable.of("msg_changed_world_setting", "Force town Explosions", world.getName(), formatBool(world.isForceExpl(), "forced", "adjustable"))); + } - } else if (split[0].equalsIgnoreCase("fire")) { + private void toggleFire(CommandSender sender, TownyWorld world, Optional choice) throws NoPermissionException { + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_FIRE.getNode()); + world.setFire(choice.orElse(!world.isFire())); + TownyMessaging.sendMsg(sender, Translatable.of("msg_changed_world_setting", "Fire Spread", world.getName(), formatBool(world.isFire()))); + } - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_FIRE.getNode()); - globalWorld.setFire(choice.orElse(!globalWorld.isFire())); - TownyMessaging.sendMsg(sender, Translatable.of("msg_changed_world_setting", "Fire Spread", globalWorld.getName(), formatBool(globalWorld.isFire()))); + private void toggleForceFire(CommandSender sender, TownyWorld world, Optional choice) throws NoPermissionException { + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_FORCEFIRE.getNode()); + world.setForceFire(choice.orElse(!world.isForceFire())); + TownyMessaging.sendMsg(sender, Translatable.of("msg_changed_world_setting", "Force town Fire Spread", world.getName(), formatBool(world.isForceFire(), "forced", "adjustable"))); + } - } else if (split[0].equalsIgnoreCase("forcefire")) { + private void toggleTownMobs(CommandSender sender, TownyWorld world, Optional choice) throws NoPermissionException { + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_TOWNMOBS.getNode()); + world.setForceTownMobs(choice.orElse(!world.isForceTownMobs())); + TownyMessaging.sendMsg(sender, Translatable.of("msg_changed_world_setting", "Town Mob spawns", world.getName(), formatBool(world.isForceTownMobs(), "forced", "adjustable"))); + } - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_FORCEFIRE.getNode()); - globalWorld.setForceFire(choice.orElse(!globalWorld.isForceFire())); - TownyMessaging.sendMsg(sender, Translatable.of("msg_changed_world_setting", "Force town Fire Spread", globalWorld.getName(), formatBool(globalWorld.isForceFire(), "forced", "adjustable"))); + private void toggleWorldMobs(CommandSender sender, TownyWorld world, Optional choice) throws NoPermissionException { + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_WORLDMOBS.getNode()); + world.setWorldMobs(choice.orElse(!world.hasWorldMobs())); + TownyMessaging.sendMsg(sender, Translatable.of("msg_changed_world_setting", "World Mob spawns", world.getName(), formatBool(world.hasWorldMobs()))); + } - } else if (split[0].equalsIgnoreCase("townmobs")) { + private void toggleWildernessMobs(CommandSender sender, TownyWorld world, Optional choice) throws NoPermissionException { + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_WILDERNESSMOBS.getNode()); + world.setWildernessMobs(choice.orElse(!world.hasWildernessMobs())); + TownyMessaging.sendMsg(sender, Translatable.of("msg_changed_world_setting", "Wilderness Mob spawns", world.getName(), formatBool(world.hasWildernessMobs()))); + } - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_TOWNMOBS.getNode()); - globalWorld.setForceTownMobs(choice.orElse(!globalWorld.isForceTownMobs())); - TownyMessaging.sendMsg(sender, Translatable.of("msg_changed_world_setting", "Town Mob spawns", globalWorld.getName(), formatBool(globalWorld.isForceTownMobs(), "forced", "adjustable"))); + private void toggleRevertUnclaim(CommandSender sender, TownyWorld world, Optional choice) throws NoPermissionException { + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_REVERTUNCLAIM.getNode()); + world.setUsingPlotManagementRevert(choice.orElse(!world.isUsingPlotManagementRevert())); + if (!world.isUsingPlotManagementRevert()) + TownyRegenAPI.turnOffRevertOnUnclaimForWorld(world); + TownyMessaging.sendMsg(sender, Translatable.of("msg_changed_world_setting", "Unclaim Revert", world.getName(), formatBool(world.isUsingPlotManagementRevert()))); + } - } else if (split[0].equalsIgnoreCase("worldmobs")) { + private void toggleRevertEntityExpl(CommandSender sender, TownyWorld world, Optional choice) throws NoPermissionException { + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_REVERTENTITYEXPL.getNode()); + world.setUsingPlotManagementWildEntityRevert(choice.orElse(!world.isUsingPlotManagementWildEntityRevert())); + TownyMessaging.sendMsg(sender, Translatable.of("msg_changed_world_setting", "Wilderness Entity Explosion Revert", world.getName(), formatBool(world.isUsingPlotManagementWildEntityRevert()))); + } - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_WORLDMOBS.getNode()); - globalWorld.setWorldMobs(choice.orElse(!globalWorld.hasWorldMobs())); - TownyMessaging.sendMsg(sender, Translatable.of("msg_changed_world_setting", "World Mob spawns", globalWorld.getName(), formatBool(globalWorld.hasWorldMobs()))); + private void toggleRevertBlockExpl(CommandSender sender, TownyWorld world, Optional choice) throws NoPermissionException { + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_REVERTBLOCKEXPL.getNode()); + world.setUsingPlotManagementWildBlockRevert(choice.orElse(!world.isUsingPlotManagementWildBlockRevert())); + TownyMessaging.sendMsg(sender, Translatable.of("msg_changed_world_setting", "Wilderness Block Explosion Revert", world.getName(), formatBool(world.isUsingPlotManagementWildBlockRevert()))); + } - } else if (split[0].equalsIgnoreCase("wildernessmobs")) { + private void togglePlotClearDelete(CommandSender sender, TownyWorld world, Optional choice) throws NoPermissionException { + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_PLOTCLEARDELETE.getNode()); + world.setUsingPlotManagementMayorDelete(choice.orElse(!world.isUsingPlotManagementMayorDelete())); + TownyMessaging.sendMsg(sender, Translatable.of("msg_changed_world_setting", "Plot Clear Delete", world.getName(), formatBool(world.isUsingPlotManagementMayorDelete()))); + } - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_WILDERNESSMOBS.getNode()); - globalWorld.setWildernessMobs(choice.orElse(!globalWorld.hasWildernessMobs())); - TownyMessaging.sendMsg(sender, Translatable.of("msg_changed_world_setting", "Wilderness Mob spawns", globalWorld.getName(), formatBool(globalWorld.hasWildernessMobs()))); + private void toggleUnclaimBlockDelete(CommandSender sender, TownyWorld world, Optional choice) throws NoPermissionException { + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_UNCLAIMBLOCKDELETE.getNode()); + world.setUsingPlotManagementDelete(choice.orElse(!world.isUsingPlotManagementDelete())); + TownyMessaging.sendMsg(sender, Translatable.of("msg_changed_world_setting", "Unclaim Block Delete", world.getName(), formatBool(world.isUsingPlotManagementDelete()))); + } - } else if (split[0].equalsIgnoreCase("revertunclaim")) { + private void toggleUnclaimEntityDelete(CommandSender sender, TownyWorld world, Optional choice) throws NoPermissionException { + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_UNCLAIMENTITYDELETE.getNode()); + world.setDeletingEntitiesOnUnclaim(choice.orElse(!world.isDeletingEntitiesOnUnclaim())); + TownyMessaging.sendMsg(sender, Translatable.of("msg_changed_world_setting", "Unclaim Entity Delete", world.getName(), formatBool(world.isDeletingEntitiesOnUnclaim()))); + } - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_REVERTUNCLAIM.getNode()); - globalWorld.setUsingPlotManagementRevert(choice.orElse(!globalWorld.isUsingPlotManagementRevert())); + private void toggleWildernessUse(CommandSender sender, TownyWorld world, String[] split) throws NoPermissionException { + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_WILDERNESSUSE.getNode()); + String value = split.length > 1 ? split[1] : ""; + boolean toggle = parseToggleChoice(value).orElse(!world.getUnclaimedZoneBuild()); + + world.setUnclaimedZoneBuild(toggle); + world.setUnclaimedZoneDestroy(toggle); + world.setUnclaimedZoneItemUse(toggle); + world.setUnclaimedZoneSwitch(toggle); + + TownyMessaging.sendMsg(sender, Translatable.of("msg_wilderness_use_set_to", toggle, world.getName())); + } - if (!globalWorld.isUsingPlotManagementRevert()) - TownyRegenAPI.turnOffRevertOnUnclaimForWorld(globalWorld); - - TownyMessaging.sendMsg(sender, Translatable.of("msg_changed_world_setting", "Unclaim Revert", globalWorld.getName(), formatBool(globalWorld.isUsingPlotManagementRevert()))); + public void worldSet(CommandSender sender, TownyWorld world, String[] split) { - } else if (split[0].equalsIgnoreCase("revertentityexpl")) { + if (split.length == 0) { + HelpMenu.TOWNYWORLD_SET.send(sender); + return; + } - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_REVERTENTITYEXPL.getNode()); - globalWorld.setUsingPlotManagementWildEntityRevert(choice.orElse(!globalWorld.isUsingPlotManagementWildEntityRevert())); - TownyMessaging.sendMsg(sender, Translatable.of("msg_changed_world_setting", "Wilderness Entity Explosion Revert", globalWorld.getName(), formatBool(globalWorld.isUsingPlotManagementWildEntityRevert()))); + switch(split[0].toLowerCase(Locale.ROOT)) { + case "usedefault" -> setUseDefaults(sender, world); + case "wildperm" -> setWildPerm(sender, world, split); + case "wildignore" -> setWildIgnore(sender, world, split); + case "wildregen" -> setWildRegen(sender, world, split); + case "wildname" -> setWildName(sender, world, split); + default -> { + if (TownyCommandAddonAPI.hasCommand(CommandType.TOWNYWORLD_SET, split[0])) { + try { + TownyCommandAddonAPI.getAddonCommand(CommandType.TOWNYWORLD_SET, split[0]).execute(sender, "townyworld", split); + } catch (Exception e) { + TownyMessaging.sendErrorMsg(sender, e.getMessage()); + } + } else { + TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_err_invalid_property", "world")); + return; + } + } + } - } else if (split[0].equalsIgnoreCase("revertblockexpl")) { + world.save(); + } - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_REVERTBLOCKEXPL.getNode()); - globalWorld.setUsingPlotManagementWildBlockRevert(choice.orElse(!globalWorld.isUsingPlotManagementWildBlockRevert())); - TownyMessaging.sendMsg(sender, Translatable.of("msg_changed_world_setting", "Wilderness Block Explosion Revert", globalWorld.getName(), formatBool(globalWorld.isUsingPlotManagementWildBlockRevert()))); + private void setUseDefaults(CommandSender sender, TownyWorld world) { + Confirmation.runOnAccept(() -> { + world.setUsingDefault(); + plugin.resetCache(); + TownyMessaging.sendMsg(sender, Translatable.of("msg_usedefault", world.getName())); + }) + .setTitle(Translatable.of("confirmation_are_you_sure_you_want_to_reset_this_worlds_settings")) + .sendTo(sender); + } - } else if (split[0].equalsIgnoreCase("plotcleardelete")) { + private void setWildPerm(CommandSender sender, TownyWorld world, String[] split) { + if (split.length < 2) { + // set default wildperm settings (/tw set wildperm) + world.setUsingDefault(); + TownyMessaging.sendMsg(sender, Translatable.of("msg_usedefault", world.getName())); + } else + try { + List perms = Arrays.asList(String.join(",", StringMgmt.remFirstArg(split)).toLowerCase(Locale.ROOT).split(",")); + world.setUnclaimedZoneBuild(perms.contains("build")); + world.setUnclaimedZoneDestroy(perms.contains("destroy")); + world.setUnclaimedZoneSwitch(perms.contains("switch")); + world.setUnclaimedZoneItemUse(perms.contains("itemuse") || perms.contains("item_use")); - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_PLOTCLEARDELETE.getNode()); - globalWorld.setUsingPlotManagementMayorDelete(choice.orElse(!globalWorld.isUsingPlotManagementMayorDelete())); - TownyMessaging.sendMsg(sender, Translatable.of("msg_changed_world_setting", "Plot Clear Delete", globalWorld.getName(), formatBool(globalWorld.isUsingPlotManagementMayorDelete()))); + plugin.resetCache(); + TownyMessaging.sendMsg(sender, Translatable.of("msg_set_wild_perms", world.getName(), perms.toString())); + } catch (Exception e) { + TownyMessaging.sendErrorMsg(sender, "Eg: /townyworld set wildperm build destroy "); + } + } - } else if (split[0].equalsIgnoreCase("unclaimblockdelete")) { + private void setWildIgnore(CommandSender sender, TownyWorld world, String[] split) { + if (split.length < 2) + TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_err_invalid_input", "/townyworld set wildignore OAK_SAPLING GOLD_ORE IRON_ORE")); + else + try { + List mats = Arrays.asList(StringMgmt.remFirstArg(split)); + world.setUnclaimedZoneIgnore(mats); - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_UNCLAIMBLOCKDELETE.getNode()); - globalWorld.setUsingPlotManagementDelete(choice.orElse(!globalWorld.isUsingPlotManagementDelete())); - TownyMessaging.sendMsg(sender, Translatable.of("msg_changed_world_setting", "Unclaim Block Delete", globalWorld.getName(), formatBool(globalWorld.isUsingPlotManagementDelete()))); + plugin.resetCache(); + TownyMessaging.sendMsg(sender, Translatable.of("msg_set_wild_ignore", world.getName(), world.getUnclaimedZoneIgnoreMaterials())); - } else if (split[0].equalsIgnoreCase("unclaimentitydelete")) { + } catch (Exception e) { + TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_err_invalid_input", "/townyworld set wildignore OAK_SAPLING GOLD_ORE IRON_ORE")); + } + } - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_UNCLAIMENTITYDELETE.getNode()); - globalWorld.setDeletingEntitiesOnUnclaim(choice.orElse(!globalWorld.isDeletingEntitiesOnUnclaim())); - TownyMessaging.sendMsg(sender, Translatable.of("msg_changed_world_setting", "Unclaim Entity Delete", globalWorld.getName(), formatBool(globalWorld.isDeletingEntitiesOnUnclaim()))); + private void setWildRegen(CommandSender sender, TownyWorld world, String[] split) { + if (split.length < 2) + TownyMessaging.sendErrorMsg(sender, "Eg: /townyworld set wildregen Creeper,EnderCrystal,EnderDragon,Fireball,SmallFireball,LargeFireball,TNTPrimed,ExplosiveMinecart"); + else { + + String[] entities = String.join(",", StringMgmt.remFirstArg(split)).split(","); + List entityList = new ArrayList<>(Arrays.asList(entities)); - } else if (split[0].equalsIgnoreCase("wildernessuse")) { + world.setPlotManagementWildRevertEntities(entityList); - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYWORLD_TOGGLE_WILDERNESSUSE.getNode()); - String value = split.length > 1 ? split[1] : ""; - boolean toggle = parseToggleChoice(value).orElse(!globalWorld.getUnclaimedZoneBuild()); - - globalWorld.setUnclaimedZoneBuild(toggle); - globalWorld.setUnclaimedZoneDestroy(toggle); - globalWorld.setUnclaimedZoneItemUse(toggle); - globalWorld.setUnclaimedZoneSwitch(toggle); - - TownyMessaging.sendMsg(sender, Translatable.of("msg_wilderness_use_set_to", toggle, globalWorld.getName())); - - } else if (TownyCommandAddonAPI.hasCommand(CommandType.TOWNYWORLD_TOGGLE, split[0])) { - TownyCommandAddonAPI.getAddonCommand(CommandType.TOWNYWORLD_TOGGLE, split[0]).execute(sender, "townyworld", split); - } else { - TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_err_invalid_property", "'" + split[0] + "'")); - return; - } - - globalWorld.save(); - - //Change settings event - BukkitTools.fireEvent(new TownBlockSettingsChangedEvent(globalWorld)); + TownyMessaging.sendMsg(sender, Translatable.of("msg_set_wild_regen", world.getName(), world.getPlotManagementWildRevertEntities())); } - } - public void worldSet(CommandSender sender, String[] split) { - - if (split.length == 0) { - HelpMenu.TOWNYWORLD_SET.send(sender); + private void setWildName(CommandSender sender, TownyWorld world, String[] split) { + if (split.length < 2) { + TownyMessaging.sendErrorMsg(sender, "Eg: /townyworld set wildname Wildy"); } else { - - if (split[0].equalsIgnoreCase("usedefault")) { - - Confirmation.runOnAccept(() -> { - globalWorld.setUsingDefault(); - plugin.resetCache(); - TownyMessaging.sendMsg(sender, Translatable.of("msg_usedefault", globalWorld.getName())); - }) - .setTitle(Translatable.of("confirmation_are_you_sure_you_want_to_reset_this_worlds_settings")) - .sendTo(sender); - - } else if (split[0].equalsIgnoreCase("wildperm")) { - - if (split.length < 2) { - // set default wildperm settings (/tw set wildperm) - globalWorld.setUsingDefault(); - TownyMessaging.sendMsg(sender, Translatable.of("msg_usedefault", globalWorld.getName())); - } else - try { - List perms = Arrays.asList(String.join(",", StringMgmt.remFirstArg(split)).toLowerCase(Locale.ROOT).split(",")); - globalWorld.setUnclaimedZoneBuild(perms.contains("build")); - globalWorld.setUnclaimedZoneDestroy(perms.contains("destroy")); - globalWorld.setUnclaimedZoneSwitch(perms.contains("switch")); - globalWorld.setUnclaimedZoneItemUse(perms.contains("itemuse") || perms.contains("item_use")); - - plugin.resetCache(); - TownyMessaging.sendMsg(sender, Translatable.of("msg_set_wild_perms", globalWorld.getName(), perms.toString())); - } catch (Exception e) { - TownyMessaging.sendErrorMsg(sender, "Eg: /townyworld set wildperm build destroy "); - } - - } else if (split[0].equalsIgnoreCase("wildignore")) { - - if (split.length < 2) - TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_err_invalid_input", "/townyworld set wildignore OAK_SAPLING GOLD_ORE IRON_ORE")); - else - try { - List mats = Arrays.asList(StringMgmt.remFirstArg(split)); - globalWorld.setUnclaimedZoneIgnore(mats); - - plugin.resetCache(); - TownyMessaging.sendMsg(sender, Translatable.of("msg_set_wild_ignore", globalWorld.getName(), globalWorld.getUnclaimedZoneIgnoreMaterials())); - - } catch (Exception e) { - TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_err_invalid_input", "/townyworld set wildignore OAK_SAPLING GOLD_ORE IRON_ORE")); - } - - } else if (split[0].equalsIgnoreCase("wildregen")) { - - if (split.length < 2) - TownyMessaging.sendErrorMsg(sender, "Eg: /townyworld set wildregen Creeper,EnderCrystal,EnderDragon,Fireball,SmallFireball,LargeFireball,TNTPrimed,ExplosiveMinecart"); - else { - - String[] entities = String.join(",", StringMgmt.remFirstArg(split)).split(","); - List entityList = new ArrayList<>(Arrays.asList(entities)); - - globalWorld.setPlotManagementWildRevertEntities(entityList); - - TownyMessaging.sendMsg(sender, Translatable.of("msg_set_wild_regen", globalWorld.getName(), globalWorld.getPlotManagementWildRevertEntities())); - } - - } else if (split[0].equalsIgnoreCase("wildname")) { - - if (split.length < 2) { - TownyMessaging.sendErrorMsg(sender, "Eg: /townyworld set wildname Wildy"); - } else { - globalWorld.setUnclaimedZoneName(split[1]); - TownyMessaging.sendMsg(sender, Translatable.of("msg_set_wild_name", globalWorld.getName(), split[1])); - } - } else if (TownyCommandAddonAPI.hasCommand(CommandType.TOWNYWORLD_SET, split[0])) { - try { - TownyCommandAddonAPI.getAddonCommand(CommandType.TOWNYWORLD_SET, split[0]).execute(sender, "townyworld", split); - } catch (Exception e) { - TownyMessaging.sendErrorMsg(sender, e.getMessage()); - } - } else { - TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_err_invalid_property", "world")); - return; - } - - globalWorld.save(); + world.setUnclaimedZoneName(split[1]); + TownyMessaging.sendMsg(sender, Translatable.of("msg_set_wild_name", world.getName(), split[1])); } } From 31f72fa12b45472ee6b87f6163b6fc68df9a5d41 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Wed, 10 Jan 2024 13:51:31 -0600 Subject: [PATCH 44/74] Refactor townAddResident. (#7180) --- .../bukkit/towny/command/TownCommand.java | 100 ++++++++---------- .../palmergames/bukkit/towny/object/Town.java | 4 +- 2 files changed, 48 insertions(+), 56 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 1d16019999..23c3b4272b 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 @@ -2878,64 +2878,56 @@ public static void townKick(Player player, String[] names) throws TownyException plugin.resetCache(); } - public static void townAddResidents(CommandSender sender, Town town, List invited) { - String name; - boolean admin = false; - if (sender instanceof Player) { - name = ((Player) sender).getName(); - if (TownyUniverse.getInstance().getPermissionSource().isTownyAdmin((Player) sender)) - admin = true; - } else { - name = "Console"; - admin = true; - } + public static void townAddResidents(CommandSender sender, Town town, List invited) throws TownyException { + List invitedResidents = invited.stream() + .filter(res -> inviteResidentToTownOrThrow(sender, res, town)) + .map(Resident::getName) + .collect(Collectors.toList()); - for (Resident newMember : new ArrayList<>(invited)) { - try { + if (invitedResidents.isEmpty()) + throw new TownyException(Translatable.of("msg_invalid_name")); - if (!admin) - BukkitTools.ifCancelledThenThrow(new TownPreAddResidentEvent(town, newMember)); - - // only add players with the right permissions. - if (!newMember.isOnline()) { // Not online - TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_offline_no_join", newMember.getName())); - invited.remove(newMember); - } else if (!newMember.hasPermissionNode(PermissionNodes.TOWNY_TOWN_RESIDENT.getNode())) { - TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_not_allowed_join", newMember.getName())); - invited.remove(newMember); - } else if (TownySettings.getMaxResidentsPerTown() > 0 && town.getResidents().size() >= TownySettings.getMaxResidentsForTown(town)){ - TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_err_max_residents_per_town_reached", TownySettings.getMaxResidentsForTown(town))); - invited.remove(newMember); - } else if (town.hasNation() && TownySettings.getMaxResidentsPerNation() > 0 && town.getNationOrNull().getResidents().size() >= TownySettings.getMaxResidentsPerNation()) { - TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_err_cannot_add_nation_over_resident_limit", TownySettings.getMaxResidentsPerNation(), newMember.getName())); - invited.remove(newMember); - } else if (!admin && TownySettings.getTownInviteCooldown() > 0 && ( (System.currentTimeMillis()/1000 - newMember.getRegistered()/1000) < (TownySettings.getTownInviteCooldown()) )) { - TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_err_resident_doesnt_meet_invite_cooldown", newMember)); - invited.remove(newMember); - } else if (TownySettings.getMaxNumResidentsWithoutNation() > 0 && !town.hasNation() && town.getResidents().size() >= TownySettings.getMaxNumResidentsWithoutNation()) { - TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_err_unable_to_add_more_residents_without_nation", TownySettings.getMaxNumResidentsWithoutNation())); - invited.remove(newMember); - } else { - town.addResidentCheck(newMember); - townInviteResident(sender, town, newMember); - } - } catch (TownyException e) { - invited.remove(newMember); - TownyMessaging.sendErrorMsg(sender, e.getMessage(sender)); - } - } + String name = sender instanceof Player player ? player.getName() : "Console"; + TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_invited_join_town", name, StringMgmt.join(invitedResidents, ", "))); + town.save(); + } + + private static boolean inviteResidentToTownOrThrow(CommandSender sender, Resident newMember, Town town) { + final boolean admin = !(sender instanceof Player player) || TownyUniverse.getInstance().getPermissionSource().isTownyAdmin(player); + try { + if (!admin) + BukkitTools.ifCancelledThenThrow(new TownPreAddResidentEvent(town, newMember)); - if (invited.size() > 0) { - StringBuilder msg = new StringBuilder(); - for (Resident newMember : invited) - msg.append(newMember.getName()).append(", "); + // Not online + if (!newMember.isOnline()) + throw new TownyException(Translatable.of("msg_offline_no_join", newMember.getName())); - msg = new StringBuilder(msg.substring(0, msg.length() - 2)); - - TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_invited_join_town", name, msg.toString())); - town.save(); - } else - TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_invalid_name")); + // only add players with the right permissions. + if (!newMember.hasPermissionNode(PermissionNodes.TOWNY_TOWN_RESIDENT.getNode())) + throw new TownyException(Translatable.of("msg_not_allowed_join", newMember.getName())); + + if (TownySettings.getMaxResidentsPerTown() > 0 && town.getResidents().size() >= TownySettings.getMaxResidentsForTown(town)) + throw new TownyException(Translatable.of("msg_err_max_residents_per_town_reached", TownySettings.getMaxResidentsForTown(town))); + + if (town.hasNation() && TownySettings.getMaxResidentsPerNation() > 0 && town.getNationOrNull().getResidents().size() >= TownySettings.getMaxResidentsPerNation()) + throw new TownyException(Translatable.of("msg_err_cannot_add_nation_over_resident_limit", TownySettings.getMaxResidentsPerNation(), newMember.getName())); + + if (!admin && TownySettings.getTownInviteCooldown() > 0 && (System.currentTimeMillis()/1000 - newMember.getRegistered()/1000) < TownySettings.getTownInviteCooldown()) + throw new TownyException(Translatable.of("msg_err_resident_doesnt_meet_invite_cooldown", newMember)); + + if (TownySettings.getMaxNumResidentsWithoutNation() > 0 && !town.hasNation() && town.getResidents().size() >= TownySettings.getMaxNumResidentsWithoutNation()) + throw new TownyException(Translatable.of("msg_err_unable_to_add_more_residents_without_nation", TownySettings.getMaxNumResidentsWithoutNation())); + + // Throws when the player has a town or is in this town already. + town.addResidentCheck(newMember); + + // Throws when the player cannot use the invite. Otherwise this will send an invite to the resident. + townInviteResident(sender, town, newMember); + } catch (TownyException e) { + TownyMessaging.sendErrorMsg(sender, e.getMessage(sender)); + return false; + } + return true; } public static void townAddResident(Town town, Resident resident) throws AlreadyRegisteredException { diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/object/Town.java b/Towny/src/main/java/com/palmergames/bukkit/towny/object/Town.java index 235acfc041..1a33b5f9aa 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/object/Town.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/object/Town.java @@ -399,8 +399,8 @@ public void addResidentCheck(Resident resident) throws AlreadyRegisteredExceptio throw new AlreadyRegisteredException(Translation.of("msg_err_already_in_town", resident.getName(), getFormattedName())); final Town residentTown = resident.getTownOrNull(); - if (residentTown != null && !this.equals(residentTown)) { - throw new AlreadyRegisteredException(Translation.of("msg_err_already_in_town", resident.getName(), residentTown.getFormattedName())); } + if (residentTown != null && !this.equals(residentTown)) + throw new AlreadyRegisteredException(Translation.of("msg_err_already_in_town", resident.getName(), residentTown.getFormattedName())); } public boolean isMayor(Resident resident) { From 674a6ee0ee933d3f618159416556d97a4e947511 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Wed, 10 Jan 2024 13:52:17 -0600 Subject: [PATCH 45/74] Refactor townSet and the subcommands. (#7179) * Refactor townSet and the subcommands. * Accidentally took out part of a comment. --- .../bukkit/towny/command/TownCommand.java | 405 ++++++++---------- 1 file changed, 168 insertions(+), 237 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 23c3b4272b..e2e3867c35 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 @@ -51,7 +51,6 @@ import com.palmergames.bukkit.towny.exceptions.AlreadyRegisteredException; import com.palmergames.bukkit.towny.exceptions.InvalidNameException; import com.palmergames.bukkit.towny.exceptions.NoPermissionException; -import com.palmergames.bukkit.towny.exceptions.NotRegisteredException; import com.palmergames.bukkit.towny.exceptions.TownyException; import com.palmergames.bukkit.towny.exceptions.CancelledEventException; import com.palmergames.bukkit.towny.invites.Invite; @@ -1814,129 +1813,41 @@ public static void townSet(CommandSender sender, String[] split, boolean admin, } else // Have the resident being tested be the mayor. resident = town.getMayor(); - if (split[0].equalsIgnoreCase("board")) { - - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_BOARD.getNode()); - townSetBoard(sender, String.join(" ", StringMgmt.remFirstArg(split)), town); - - } else if (split[0].equalsIgnoreCase("title")) { - - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_TITLE.getNode()); - townSetTitle(sender, split, admin); - - } else if (split[0].equalsIgnoreCase("taxpercentcap")) { - - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_TAXPERCENTCAP.getNode()); - townSetTaxPercent(sender, split, town); - - } else if (split[0].equalsIgnoreCase("surname")) { - - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_SURNAME.getNode()); - townSetSurname(sender, split, admin); - - } else if (split[0].equalsIgnoreCase("mayor")) { - - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_MAYOR.getNode()); - townSetMayor(sender, split, admin, town, resident); - - } else if (split[0].equalsIgnoreCase("taxes")) { - - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_TAXES.getNode()); - townSetTaxes(sender, split, admin, town); - - } else if (split[0].equalsIgnoreCase("plottax")) { - - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_PLOTTAX.getNode()); - townSetPlotTax(sender, split, admin, town); - - } else if (split[0].equalsIgnoreCase("shoptax")) { - - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_SHOPTAX.getNode()); - townSetShopTax(sender, split, admin, town); - - } else if (split[0].equalsIgnoreCase("embassytax")) { - - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_EMBASSYTAX.getNode()); - townSetEmbassyTax(sender, split, admin, town); - - } else if (split[0].equalsIgnoreCase("plotprice")) { - - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_PLOTPRICE.getNode()); - townSetPlotPrice(sender, split, admin, town); - - } else if (split[0].equalsIgnoreCase("shopprice")) { - - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_SHOPPRICE.getNode()); - townSetShopPrice(sender, split, admin, town); - - } else if (split[0].equalsIgnoreCase("embassyprice")) { - - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_EMBASSYPRICE.getNode()); - townSetEmbassyPrice(sender, split, admin, town); - - } else if (split[0].equalsIgnoreCase("spawncost")) { - - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_SPAWNCOST.getNode()); - townSetSpawnCost(sender, split, admin, town); - - } else if (split[0].equalsIgnoreCase("name")) { - - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_NAME.getNode()); - townSetName(sender, split, town); - - } else if (split[0].equalsIgnoreCase("tag")) { - - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_TAG.getNode()); - townSetTag(sender, split, admin, town); - - } else if (split[0].equalsIgnoreCase("homeblock")) { - - catchConsole(sender); - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_HOMEBLOCK.getNode()); - townSetHomeblock(player, town); - - } else if (split[0].equalsIgnoreCase("spawn")) { - - catchConsole(sender); - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_SPAWN.getNode()); - townSetSpawn(player, town, admin); - - } else if (split[0].equalsIgnoreCase("outpost")) { - - catchConsole(sender); - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_OUTPOST.getNode()); - townSetOutpost(sender, town, player); - - } else if (split[0].equalsIgnoreCase("perm")) { - - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_PERM.getNode()); - // Make sure we are allowed to set these permissions. - toggleTest(town, StringMgmt.join(split, " ")); - setTownBlockOwnerPermissions(sender, town, StringMgmt.remFirstArg(split)); - - } else if (split[0].equalsIgnoreCase("primaryjail")) { - - catchConsole(sender); - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_PRIMARYJAIL.getNode()); - townSetPrimaryJail(player, town); - - } else if (split[0].equalsIgnoreCase("mapcolor")) { - - checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_MAPCOLOR.getNode()); - townSetMapColor(sender, split, town); - - } else if (TownyCommandAddonAPI.hasCommand(CommandType.TOWN_SET, split[0])) { - TownyCommandAddonAPI.getAddonCommand(CommandType.TOWN_SET, split[0]).execute(sender, "town", split); - } else { - TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_err_invalid_property", "town")); - return; - } - - town.save(); + String[] subArgs = StringMgmt.remFirstArg(split); + String arg = split[0].toLowerCase(Locale.ROOT); + switch (arg) { + case "board" -> townSetBoard(sender, String.join(" ", subArgs), town); + case "title" -> townSetTitle(sender, subArgs, admin); + case "taxpercentcap" -> townSetTaxPercent(sender, subArgs, town); + case "surname" -> townSetSurname(sender, subArgs, admin); + case "mayor" -> townSetMayor(sender, subArgs, admin, town, resident); + case "taxes" -> townSetTaxes(sender, subArgs, admin, town); + case "plottax" -> townSetPlotTax(sender, subArgs, admin, town); + case "shoptax" -> townSetShopTax(sender, subArgs, admin, town); + case "embassytax" -> townSetEmbassyTax(sender, subArgs, admin, town); + case "plotprice" -> townSetPlotPrice(sender, subArgs, admin, town); + case "shopprice" -> townSetShopPrice(sender, subArgs, admin, town); + case "embassyprice" -> townSetEmbassyPrice(sender, subArgs, admin, town); + case "spawncost" -> townSetSpawnCost(sender, subArgs, admin, town); + case "name" -> townSetName(sender, subArgs, town); + case "tag" -> townSetTag(sender, subArgs, admin, town); + case "homeblock" -> townSetHomeblock(sender, town); + case "spawn" -> townSetSpawn(sender, town, admin); + case "outpost" -> townSetOutpost(sender, town); + case "perm" -> setTownBlockOwnerPermissions(sender, town, subArgs); + case "primaryjail" -> townSetPrimaryJail(sender, town); + case "mapcolor" -> townSetMapColor(sender, subArgs, town); + default -> { + if (TownyCommandAddonAPI.hasCommand(CommandType.TOWN_SET, arg)) { + TownyCommandAddonAPI.getAddonCommand(CommandType.TOWN_SET, arg).execute(sender, "town", split); + return; + } + HelpMenu.TOWN_SET.send(sender); + }} } public static void townSetBoard(CommandSender sender, String board, Town town) throws TownyException { - + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_BOARD.getNode()); if (board.isEmpty()) throw new TownyException("Eg: /town set board " + Translatable.of("town_help_9").forLocale(sender)); @@ -1964,12 +1875,13 @@ public static void townSetBoard(CommandSender sender, String board, Town town) t } public static void townSetTitle(@NotNull CommandSender sender, @NotNull String[] split, boolean admin) throws TownyException { + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_TITLE.getNode()); // Give the resident a title - if (split.length < 2) + if (split.length == 0) throw new TownyException("Eg: /town set title bilbo Jester"); - Resident resident = getResidentOrThrow(split[1]); - String title = StringMgmt.join(NameValidation.checkAndFilterArray(StringMgmt.remArgs(split, 2))); + Resident resident = getResidentOrThrow(split[0]); + String title = StringMgmt.join(NameValidation.checkAndFilterArray(StringMgmt.remArgs(split, 1))); townSetTitle(sender, resident, title, admin); } @@ -2011,12 +1923,13 @@ public static void townSetTitle(@NotNull CommandSender sender, @NotNull Resident } public static void townSetSurname(CommandSender sender, String[] split, boolean admin) throws TownyException { + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_SURNAME.getNode()); // Give the resident a surname - if (split.length < 2) + if (split.length == 0) throw new TownyException("Eg: /town set surname bilbo the dwarf "); - Resident resident = getResidentOrThrow(split[1]); - String surname = StringMgmt.join(NameValidation.checkAndFilterArray(StringMgmt.remArgs(split, 2))); + Resident resident = getResidentOrThrow(split[0]); + String surname = StringMgmt.join(NameValidation.checkAndFilterArray(StringMgmt.remArgs(split, 1))); townSetSurname(sender, resident, surname, admin); } @@ -2057,15 +1970,16 @@ public static void townSetSurname(@NotNull CommandSender sender, @NotNull Reside TownyMessaging.sendMsg(sender, message); } - public static void townSetMayor(CommandSender sender, String[] split, boolean admin, Town town, Resident resident) throws TownyException, NotRegisteredException { - if (split.length < 2) + public static void townSetMayor(CommandSender sender, String[] split, boolean admin, Town town, Resident resident) throws TownyException { + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_MAYOR.getNode()); + if (split.length == 0) throw new TownyException("Eg: /town set mayor Dumbo"); if (!admin && !resident.isMayor()) // We already know the resident is a mayor if admin if true, prevents an NPE in rare cases of resident being null. throw new TownyException(Translatable.of("msg_not_mayor")); Resident oldMayor = town.getMayor(); - Resident newMayor = getResidentOrThrow(split[1]); + Resident newMayor = getResidentOrThrow(split[0]); Confirmation.runOnAccept(() -> { try { @@ -2109,9 +2023,10 @@ public static void townSetMayor(CommandSender sender, String[] split, boolean ad } public static void townSetTaxes(CommandSender sender, String[] split, boolean admin, Town town) throws TownyException { - if (split.length < 2) + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_TAXES.getNode()); + if (split.length == 0) throw new TownyException("Eg: /town set taxes 7"); - Double amount = MathUtil.getDoubleOrThrow(split[1]); + Double amount = MathUtil.getDoubleOrThrow(split[0]); if (amount < 0 && !TownySettings.isNegativeTownTaxAllowed()) throw new TownyException(Translatable.of("msg_err_negative_money")); if (town.isTaxPercentage() && (amount > 100 || amount < 0.0)) @@ -2119,127 +2034,123 @@ public static void townSetTaxes(CommandSender sender, String[] split, boolean ad if (!TownySettings.isNegativeTownTaxAllowed() && TownySettings.getTownDefaultTaxMinimumTax() > amount) throw new TownyException(Translatable.of("msg_err_tax_minimum_not_met", TownySettings.getTownDefaultTaxMinimumTax())); town.setTaxes(amount); - if (admin) TownyMessaging.sendMsg(sender, Translatable.of("msg_town_set_tax", sender.getName(), town.getTaxes())); - TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_town_set_tax", sender.getName(), town.getTaxes())); + town.save(); + String slug = town.isTaxPercentage() ? amount.toString() + "%" : prettyMoney(town.getTaxes()); + if (admin) TownyMessaging.sendMsg(sender, Translatable.of("msg_town_set_tax", sender.getName(), slug)); + TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_town_set_tax", sender.getName(), slug)); } public static void townSetPlotTax(CommandSender sender, String[] split, boolean admin, Town town) throws TownyException { - if (split.length < 2) + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_PLOTTAX.getNode()); + if (split.length == 0) throw new TownyException("Eg: /town set plottax 10"); - try { - double amount = Double.parseDouble(split[1]); - if (!TownySettings.isNegativePlotTaxAllowed() && amount < 0) - throw new TownyException(Translatable.of("msg_err_negative_money")); - town.setPlotTax(amount); - if (admin) TownyMessaging.sendMsg(sender, Translatable.of("msg_town_set_plottax", sender.getName(), town.getPlotTax())); - TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_town_set_plottax", sender.getName(), town.getPlotTax())); - } catch (NumberFormatException e) { - throw new TownyException(Translatable.of("msg_error_must_be_num")); - } + double amount = MathUtil.getDoubleOrThrow(split[0]); + if (!TownySettings.isNegativePlotTaxAllowed() && amount < 0) + throw new TownyException(Translatable.of("msg_err_negative_money")); + town.setPlotTax(amount); + town.save(); + String price = prettyMoney(town.getPlotTax()); + if (admin) TownyMessaging.sendMsg(sender, Translatable.of("msg_town_set_plottax", sender.getName(), price)); + TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_town_set_plottax", sender.getName(), price)); } public static void townSetShopTax(CommandSender sender, String[] split, boolean admin, Town town) throws TownyException { - if (split.length < 2) + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_SHOPTAX.getNode()); + if (split.length == 0) throw new TownyException("Eg: /town set shoptax 10"); - try { - double amount = Double.parseDouble(split[1]); - if (!TownySettings.isNegativePlotTaxAllowed() && amount < 0) - throw new TownyException(Translatable.of("msg_err_negative_money")); - town.setCommercialPlotTax(amount); - if (admin) TownyMessaging.sendMsg(sender, Translatable.of("msg_town_set_alttax", sender.getName(), "shop", town.getCommercialPlotTax())); - TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_town_set_alttax", sender.getName(), "shop", town.getCommercialPlotTax())); - } catch (NumberFormatException e) { - throw new TownyException(Translatable.of("msg_error_must_be_num")); - } + double amount = MathUtil.getDoubleOrThrow(split[0]); + if (!TownySettings.isNegativePlotTaxAllowed() && amount < 0) + throw new TownyException(Translatable.of("msg_err_negative_money")); + town.setCommercialPlotTax(amount); + town.save(); + String price = prettyMoney(town.getCommercialPlotTax()); + if (admin) TownyMessaging.sendMsg(sender, Translatable.of("msg_town_set_alttax", sender.getName(), "shop", price)); + TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_town_set_alttax", sender.getName(), "shop", price)); } public static void townSetEmbassyTax(CommandSender sender, String[] split, boolean admin, Town town) throws TownyException { - if (split.length < 2) + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_EMBASSYTAX.getNode()); + if (split.length == 0) throw new TownyException("Eg: /town set embassytax 10"); - try { - double amount = Double.parseDouble(split[1]); - if (!TownySettings.isNegativePlotTaxAllowed() && amount < 0) - throw new TownyException(Translatable.of("msg_err_negative_money")); - town.setEmbassyPlotTax(amount); - if (admin) TownyMessaging.sendMsg(sender, Translatable.of("msg_town_set_alttax", sender.getName(), "embassy", town.getEmbassyPlotTax())); - TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_town_set_alttax", sender.getName(), "embassy", town.getEmbassyPlotTax())); - } catch (NumberFormatException e) { - throw new TownyException(Translatable.of("msg_error_must_be_num")); - } + double amount = MathUtil.getDoubleOrThrow(split[0]); + if (!TownySettings.isNegativePlotTaxAllowed() && amount < 0) + throw new TownyException(Translatable.of("msg_err_negative_money")); + town.setEmbassyPlotTax(amount); + town.save(); + String price = prettyMoney(town.getEmbassyPlotTax()); + if (admin) TownyMessaging.sendMsg(sender, Translatable.of("msg_town_set_alttax", sender.getName(), "embassy", price)); + TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_town_set_alttax", sender.getName(), "embassy", price)); } public static void townSetPlotPrice(CommandSender sender, String[] split, boolean admin, Town town) throws TownyException { - if (split.length < 2) + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_PLOTPRICE.getNode()); + if (split.length == 0) throw new TownyException("Eg: /town set plotprice 50"); - try { - double amount = Double.parseDouble(split[1]); - if (amount < 0) - throw new TownyException(Translatable.of("msg_err_negative_money")); + double amount = MathUtil.getDoubleOrThrow(split[0]); + if (amount < 0) + throw new TownyException(Translatable.of("msg_err_negative_money")); - town.setPlotPrice(amount); - if (admin) TownyMessaging.sendMsg(sender, Translatable.of("msg_town_set_plotprice", sender.getName(), town.getPlotPrice())); - TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_town_set_plotprice", sender.getName(), town.getPlotPrice())); - } catch (NumberFormatException e) { - throw new TownyException(Translatable.of("msg_error_must_be_num")); - } + town.setPlotPrice(amount); + town.save(); + String price = prettyMoney(town.getPlotPrice()); + if (admin) TownyMessaging.sendMsg(sender, Translatable.of("msg_town_set_plotprice", sender.getName(), price)); + TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_town_set_plotprice", sender.getName(), price)); } public static void townSetShopPrice(CommandSender sender, String[] split, boolean admin, Town town) throws TownyException { - if (split.length < 2) + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_SHOPPRICE.getNode()); + if (split.length == 0) throw new TownyException("Eg: /town set shopprice 50"); - try { - double amount = Double.parseDouble(split[1]); - if (amount < 0) - throw new TownyException(Translatable.of("msg_err_negative_money")); + double amount = MathUtil.getDoubleOrThrow(split[0]); + if (amount < 0) + throw new TownyException(Translatable.of("msg_err_negative_money")); - town.setCommercialPlotPrice(amount); - if (admin) TownyMessaging.sendMsg(sender, Translatable.of("msg_town_set_altprice", sender.getName(), "shop", town.getCommercialPlotPrice())); - TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_town_set_altprice", sender.getName(), "shop", town.getCommercialPlotPrice())); - } catch (NumberFormatException e) { - throw new TownyException(Translatable.of("msg_error_must_be_num")); - } + town.setCommercialPlotPrice(amount); + town.save(); + String price = prettyMoney(town.getCommercialPlotPrice()); + if (admin) TownyMessaging.sendMsg(sender, Translatable.of("msg_town_set_altprice", sender.getName(), "shop", price)); + TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_town_set_altprice", sender.getName(), "shop", price)); } public static void townSetEmbassyPrice(CommandSender sender, String[] split, boolean admin, Town town) throws TownyException { - if (split.length < 2) + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_EMBASSYPRICE.getNode()); + if (split.length == 0) throw new TownyException("Eg: /town set embassyprice 50"); - try { - double amount = Double.parseDouble(split[1]); - if (amount < 0) - throw new TownyException(Translatable.of("msg_err_negative_money")); + double amount = MathUtil.getDoubleOrThrow(split[0]); + if (amount < 0) + throw new TownyException(Translatable.of("msg_err_negative_money")); - town.setEmbassyPlotPrice(amount); - if (admin) TownyMessaging.sendMsg(sender, Translatable.of("msg_town_set_altprice", sender.getName(), "embassy", town.getEmbassyPlotPrice())); - TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_town_set_altprice", sender.getName(), "embassy", town.getEmbassyPlotPrice())); - } catch (NumberFormatException e) { - throw new TownyException(Translatable.of("msg_error_must_be_num")); - } + town.setEmbassyPlotPrice(amount); + town.save(); + String price = prettyMoney(town.getEmbassyPlotPrice()); + if (admin) TownyMessaging.sendMsg(sender, Translatable.of("msg_town_set_altprice", sender.getName(), "embassy", price)); + TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_town_set_altprice", sender.getName(), "embassy", price)); } public static void townSetSpawnCost(CommandSender sender, String[] split, boolean admin, Town town) throws TownyException { - if (split.length < 2) + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_SPAWNCOST.getNode()); + if (split.length == 0) throw new TownyException("Eg: /town set spawncost 50"); - try { - double amount = Double.parseDouble(split[1]); - if (amount < 0) - throw new TownyException(Translatable.of("msg_err_negative_money")); + double amount = MathUtil.getDoubleOrThrow(split[0]); + if (amount < 0) + throw new TownyException(Translatable.of("msg_err_negative_money")); - if (TownySettings.getSpawnTravelCost() < amount) - throw new TownyException(Translatable.of("msg_err_cannot_set_spawn_cost_more_than", TownySettings.getSpawnTravelCost())); + if (TownySettings.getSpawnTravelCost() < amount) + throw new TownyException(Translatable.of("msg_err_cannot_set_spawn_cost_more_than", TownySettings.getSpawnTravelCost())); - town.setSpawnCost(amount); - if (admin) TownyMessaging.sendMsg(sender, Translatable.of("msg_spawn_cost_set_to", sender.getName(), Translatable.of("town_sing"), split[1])); - TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_spawn_cost_set_to", sender.getName(), Translatable.of("town_sing"), split[1])); - } catch (NumberFormatException e) { - throw new TownyException(Translatable.of("msg_error_must_be_num")); - } + town.setSpawnCost(amount); + town.save(); + String price = prettyMoney(amount); + if (admin) TownyMessaging.sendMsg(sender, Translatable.of("msg_spawn_cost_set_to", sender.getName(), Translatable.of("town_sing"), price)); + TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_spawn_cost_set_to", sender.getName(), Translatable.of("town_sing"), price)); } public static void townSetName(CommandSender sender, String[] split, Town town) throws TownyException { - if (split.length < 2) + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_NAME.getNode()); + if (split.length == 0) throw new TownyException("Eg: /town set name BillyBobTown"); - String name = String.join("_", StringMgmt.remFirstArg(split)); + String name = String.join("_", split); if (NameValidation.isBlacklistName(name) || TownyUniverse.getInstance().hasTown(name) @@ -2263,24 +2174,28 @@ public static void townSetName(CommandSender sender, String[] split, Town town) } } - public static void townSetTag(CommandSender sender, String[] split, boolean admin, Town town) throws TownyException, InvalidNameException { - if (split.length < 2) + public static void townSetTag(CommandSender sender, String[] split, boolean admin, Town town) throws TownyException { + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_TAG.getNode()); + if (split.length == 0) throw new TownyException("Eg: /town set tag PLTC"); - else if (split[1].equalsIgnoreCase("clear")) { + else if (split[0].equalsIgnoreCase("clear")) { town.setTag(" "); if (admin) TownyMessaging.sendMsg(sender, Translatable.of("msg_reset_town_tag", sender.getName())); TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_reset_town_tag", sender.getName())); } else { - if (split[1].length() > TownySettings.getMaxTagLength()) + if (split[0].length() > TownySettings.getMaxTagLength()) throw new TownyException(Translatable.of("msg_err_tag_too_long")); - town.setTag(NameValidation.checkAndFilterName(split[1])); + town.setTag(NameValidation.checkAndFilterName(split[0])); + town.save(); if (admin) TownyMessaging.sendMsg(sender, Translatable.of("msg_set_town_tag", sender.getName(), town.getTag())); TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_set_town_tag", sender.getName(), town.getTag())); } } - public static void townSetHomeblock(Player player, final Town town) throws TownyException { + public static void townSetHomeblock(CommandSender sender, final Town town) throws TownyException { + Player player = catchConsole(sender); + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_HOMEBLOCK.getNode()); final TownBlock townBlock = TownyAPI.getInstance().getTownBlock(player); final TownyWorld world = TownyAPI.getInstance().getTownyWorld(player.getWorld()); @@ -2313,6 +2228,7 @@ public static void townSetHomeblock(Player player, final Town town) throws Towny Confirmation.runOnAccept(() -> { // Set town homeblock and remove the out of range towns. town.playerSetsHomeBlock(townBlock, playerLocation, player); + town.save(); ProximityUtil.removeOutOfRangeTowns(nation); }) .setTitle(Translatable.of("msg_warn_the_following_towns_will_be_removed_from_your_nation", StringMgmt.join(removedTowns, ", "))) @@ -2322,9 +2238,12 @@ public static void townSetHomeblock(Player player, final Town town) throws Towny // Phew, the nation won't lose any towns, let's do this. } town.playerSetsHomeBlock(townBlock, player.getLocation(), player); + town.save(); } - public static void townSetSpawn(Player player, Town town, boolean admin) throws TownyException { + public static void townSetSpawn(CommandSender sender, Town town, boolean admin) throws TownyException { + Player player = catchConsole(sender); + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_SPAWN.getNode()); // Towns can only set their spawn if they have a homeblock. if (!town.hasHomeBlock()) throw new TownyException(Translatable.of("msg_err_homeblock_has_not_been_set")); @@ -2349,37 +2268,44 @@ public static void townSetSpawn(Player player, Town town, boolean admin) throws // Set the spawn point and send feedback message. town.setSpawn(newSpawn); + town.save(); TownyMessaging.sendMsg(player, Translatable.of("msg_set_town_spawn")); } - public static void townSetOutpost(CommandSender sender, Town town, Player player) throws TownyException { + public static void townSetOutpost(CommandSender sender, Town town) throws TownyException { + Player player = catchConsole(sender); + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_OUTPOST.getNode()); TownBlock townBlock = TownyAPI.getInstance().getTownBlock(player); if (townBlock == null || !townBlock.hasTown() || !townBlock.isOutpost()) throw new TownyException(Translatable.of("msg_err_location_is_not_within_an_outpost_plot")); - if (townBlock.getTownOrNull().equals(town)) { - town.addOutpostSpawn(player.getLocation()); - TownyMessaging.sendMsg(sender, Translatable.of("msg_set_outpost_spawn")); - } else + if (!townBlock.getTownOrNull().equals(town)) throw new TownyException(Translatable.of("msg_not_own_area")); - } - public static void townSetPrimaryJail(Player player, Town town) throws TownyException { + town.addOutpostSpawn(player.getLocation()); + town.save(); + TownyMessaging.sendMsg(sender, Translatable.of("msg_set_outpost_spawn")); + } + public static void townSetPrimaryJail(CommandSender sender, Town town) throws TownyException { + Player player = catchConsole(sender); + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_PRIMARYJAIL.getNode()); TownBlock tb = TownyAPI.getInstance().getTownBlock(player); if (tb == null || !tb.isJail()) throw new TownyException(Translatable.of("msg_err_location_is_not_within_a_jail_plot")); Jail jail = tb.getJail(); town.setPrimaryJail(jail); + town.save(); TownyMessaging.sendMsg(player, Translatable.of("msg_primary_jail_set_for_town")); } public static void townSetMapColor(CommandSender sender, String[] split, Town town) throws TownyException { - if (split.length < 2) + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_MAPCOLOR.getNode()); + if (split.length == 0) throw new TownyException("Eg: /town set mapcolor brown."); - String color = StringMgmt.join(StringMgmt.remFirstArg(split), " ").toLowerCase(Locale.ROOT); + String color = StringMgmt.join(split, " ").toLowerCase(Locale.ROOT); if (!TownySettings.getTownColorsMap().containsKey(color)) throw new TownyException(Translatable.of("msg_err_invalid_nation_map_color", TownySettings.getTownColorsMap().keySet().toString())); @@ -2401,13 +2327,15 @@ private static void setTownMapColor(Town town, String color) { } public static void townSetTaxPercent(CommandSender sender, String[] split, Town town) throws TownyException { + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_TAXPERCENTCAP.getNode()); if (!town.isTaxPercentage()) throw new TownyException(Translatable.of("msg_max_tax_amount_only_for_percent")); - if (split.length < 2) + if (split.length == 0) throw new TownyException("Eg. /town set taxpercentcap 10000"); - town.setMaxPercentTaxAmount(Double.parseDouble(split[1])); + town.setMaxPercentTaxAmount(MathUtil.getDoubleOrThrow(split[0])); + town.save(); TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_town_set_tax_max_percent_amount", sender.getName(), prettyMoney(town.getMaxPercentTaxAmount()))); } @@ -2755,7 +2683,8 @@ public static void townRename(CommandSender sender, Town town, String newName) { // This should never happen if (town == null) throw new TownyException("Error renaming town! Cannot fetch town with new name " + newName); - + + town.save(); TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_town_set_name", sender.getName(), town.getName())); } catch (TownyException e) { TownyMessaging.sendErrorMsg(sender, e.getMessage(sender)); @@ -3239,9 +3168,11 @@ public static void townAdd(CommandSender sender, Town specifiedTown, String[] na } // wrapper function for non friend setting of perms - public static void setTownBlockOwnerPermissions(CommandSender sender, TownBlockOwner townBlockOwner, String[] split) { - - setTownBlockPermissions(sender, townBlockOwner, townBlockOwner.getPermissions(), split, false); + public static void setTownBlockOwnerPermissions(CommandSender sender, Town town, String[] split) throws TownyException { + checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_SET_PERM.getNode()); + // Make sure we are allowed to set these permissions. + toggleTest(town, StringMgmt.join(split, " ")); + setTownBlockPermissions(sender, town, town.getPermissions(), split, false); } public static void setTownBlockPermissions(CommandSender sender, TownBlockOwner townBlockOwner, TownyPermission perm, String[] split, boolean friend) { From 6adb90cb34184faaee10a3165125b51c26181f8b Mon Sep 17 00:00:00 2001 From: LlmDl Date: Wed, 10 Jan 2024 13:52:38 -0600 Subject: [PATCH 46/74] Refactor the plot claim task to not be a mess. (#7166) * Refactor the plot claim task to not be a mess. * Handle the messages at the end better. --- .../bukkit/towny/tasks/PlotClaim.java | 499 +++++++----------- Towny/src/main/resources/lang/en-US.yml | 1 + 2 files changed, 198 insertions(+), 302 deletions(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/PlotClaim.java b/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/PlotClaim.java index 1bf7a621ad..04a273fde7 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/PlotClaim.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/PlotClaim.java @@ -5,9 +5,8 @@ import com.palmergames.bukkit.towny.TownyEconomyHandler; import com.palmergames.bukkit.towny.TownyMessaging; import com.palmergames.bukkit.towny.TownySettings; -import com.palmergames.bukkit.towny.exceptions.AlreadyRegisteredException; -import com.palmergames.bukkit.towny.exceptions.NotRegisteredException; import com.palmergames.bukkit.towny.exceptions.TownyException; +import com.palmergames.bukkit.towny.object.EconomyHandler; import com.palmergames.bukkit.towny.object.PlotGroup; import com.palmergames.bukkit.towny.object.Resident; import com.palmergames.bukkit.towny.object.Town; @@ -16,10 +15,12 @@ import com.palmergames.bukkit.towny.object.Translatable; import com.palmergames.bukkit.towny.object.WorldCoord; import org.bukkit.entity.Player; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; /** * @author ElgarL @@ -42,7 +43,7 @@ public class PlotClaim extends Thread { * @param claim or unclaim * @param admin - is this admin overrided. * @param resident - see player parameter - * @param groupClaim Indicates whether the claim is part of a plot group claim. + * @param groupClaim Indicates whether the claim is part of a plot group claim. */ public PlotClaim(Towny plugin, Player player, Resident resident, List selection, boolean claim, boolean admin, boolean groupClaim) { @@ -59,9 +60,6 @@ public PlotClaim(Towny plugin, Player player, Resident resident, List 0) { - - if (group.getResident() != null) { - /* - * The plots are resident owned. - */ - if (!resident.getAccount().payTo(group.getPrice(), group.getResident(), "Plot Group - Buy From Seller")) { - /* - * Should not be possible, as the resident has already been tested to see if they have enough to pay. - */ - TownyMessaging.sendErrorMsg(player, Translatable.of("msg_no_money_purchase_plot")); - break; - } - } else { - /* - * The plots are town-owned. - */ - double bankcap = worldCoord.getTownBlock().getPlotObjectGroup().getTown().getBankCap(); - if (bankcap > 0) { - if (worldCoord.getTownBlock().getPlotObjectGroup().getPrice() + worldCoord.getTownBlock().getPlotObjectGroup().getTown().getAccount().getHoldingBalance() > bankcap) - throw new TownyException(Translatable.of("msg_err_deposit_capped", bankcap)); - } - - if (!resident.getAccount().payTo(group.getPrice(), group.getTown(), "Plot Group - Buy From Town")) { - /* - * Should not be possible, as the resident has already been tested to see if they have enough to pay. - */ - TownyMessaging.sendErrorMsg(player, Translatable.of("msg_no_money_purchase_plot")); - break; - } - } - } - - /* - * Cause the actual claiming here. - */ - if (residentGroupClaim(selection)) { - claimed++; - - - group.setResident(resident); - group.setPrice(-1); - TownyMessaging.sendPrefixedTownMessage(worldCoord.getTownBlock().getTown(), Translatable.of("msg_player_successfully_bought_group_x", player.getName(), group.getName())); - - group.save(); - break; - } - } - } catch (TownyException e) { - TownyMessaging.sendErrorMsg(player, e.getMessage(player)); - } catch (Exception e) { - TownyMessaging.sendErrorMsg(player, e.getMessage()); - } - - // Make sure this is a valid world (mainly when unclaiming). - if (!TownyAPI.getInstance().isTownyWorld(worldCoord.getBukkitWorld())) - continue; - - try { - if (claim) { - if (groupClaim) { - - } else if (!admin) { - if (residentClaim(worldCoord)) - claimed++; - } else { - adminClaim(worldCoord); - claimed++; - } - - - } else { - residentUnclaim(worldCoord); - } - } catch (TownyException x) { - TownyMessaging.sendErrorMsg(player, x.getMessage(player)); - } - - } - } else if (!claim) { + if (selection == null && !claim) { residentUnclaimAll(); + return; } - if (player != null) { - if (claim) { - if ((selection != null) && (selection.size() > 0) && (claimed > 0)) { - TownyMessaging.sendMsg(player, Translatable.of("msg_claimed").append(" ") - .append(selection.size() > 5 ? Translatable.of("msg_total_townblocks").forLocale(player) + selection.size() : Arrays.toString(selection.toArray(new WorldCoord[0])))); - } else { - TownyMessaging.sendMsg(player, Translatable.of("msg_not_claimed_1")); - } - } else if (selection != null) { - TownyMessaging.sendMsg(player, Translatable.of("msg_unclaimed").append(" ") - .append(selection.size() > 5 ? Translatable.of("msg_total_townblocks").forLocale(player) + selection.size() : Arrays.toString(selection.toArray(new WorldCoord[0])))); - } else { - TownyMessaging.sendMsg(player, Translatable.of("msg_unclaimed")); - } + if (groupClaim) { + handleGroupClaim(selection.get(0)); + return; } - - resident.save(); - plugin.resetCache(); - } + if (admin) { + adminClaim(selection); + return; + } - /** - * A similar function to {@link #residentClaim(WorldCoord)}, that deals - * with group member, or more specifically updates plot group values, to - * show group ownership and membership. - * @param worldCoords The coordinates of the blocks to be claimed. - * @return A boolean indicating if the transaction was successful. - * @throws TownyException Whenever an object could not be retrieved. - * @author Suneet Tipirneni (Siris) - */ - private boolean residentGroupClaim(List worldCoords) throws TownyException { - - for (int i = 0; i < worldCoords.size(); ++i) { - - WorldCoord worldCoord = worldCoords.get(i); - - - try { - TownBlock townBlock = worldCoord.getTownBlock(); - Town town = townBlock.getTown(); - PlotGroup group = townBlock.getPlotObjectGroup(); - - if ((resident.hasTown() && (resident.getTown() != town) && (!townBlock.getType().equals(TownBlockType.EMBASSY))) || ((!resident.hasTown()) && (!townBlock.getType().equals(TownBlockType.EMBASSY)))) - throw new TownyException(Translatable.of("msg_err_not_part_town")); - - if (townBlock.getPlotObjectGroup().hasResident()) { - /* - * Plotgroup is resident-owned. - */ - Resident owner = townBlock.getPlotObjectGroup().getResident(); - - if (group.getPrice() != -1) { - // Plot is for sale - - int maxPlots = TownySettings.getMaxResidentPlots(resident); - int extraPlots = TownySettings.getMaxResidentExtraPlots(resident); - - //Infinite plots - if (maxPlots != -1) { - maxPlots = maxPlots + extraPlots; - } - - if (maxPlots >= 0 && resident.getTownBlocks().size() + group.getTownBlocks().size() > maxPlots) - throw new TownyException(Translatable.of("msg_max_plot_own", maxPlots)); - - TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_buy_resident_plot", resident.getName(), owner.getName(), townBlock.getPlotObjectGroup().getPrice())); - - townBlock.setResident(resident); - - // Set the plot permissions to mirror the new owners. - // TODO: Plot types for groups. - //group.setType(townBlock.getType()); - - owner.save(); - group.save(); - townBlock.save(); - - if (i >= worldCoords.size() - 2) { - TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_player_successfully_bought_group_x", resident.getName(), group.getName())); - } - - // Update any caches for this WorldCoord - plugin.updateCache(worldCoord); - } else { - //Should never reach here. - throw new AlreadyRegisteredException(Translatable.of("msg_already_claimed", owner.getName()).forLocale(player)); - } - - } else { - /* - * Plot group is town-owned. - */ - - if (townBlock.getPlotObjectGroup().getPrice() == -1) { - throw new TownyException(Translatable.of("msg_err_plot_nfs")); - } - - townBlock.setResident(resident); - - // Set the plot permissions to mirror the new owners. - townBlock.setType(townBlock.getType()); - townBlock.save(); - - } - } catch (NotRegisteredException e) { - throw new TownyException(Translatable.of("msg_err_not_part_town")); - } - + if (!claim) { + residentUnclaim(selection); + return; + } + + if (claim) { + residentClaim(selection); + return; } - - return true; } - private boolean residentClaim(WorldCoord worldCoord) throws TownyException { + private void handleGroupClaim(WorldCoord worldCoord) { - try { - TownBlock townBlock = worldCoord.getTownBlock(); - Town town = townBlock.getTown(); - if ((resident.hasTown() && (resident.getTown() != town) && (!townBlock.getType().equals(TownBlockType.EMBASSY))) || ((!resident.hasTown()) && (!townBlock.getType().equals(TownBlockType.EMBASSY)))) - throw new TownyException(Translatable.of("msg_err_not_part_town")); - - final Resident owner = townBlock.getResidentOrNull(); - if (owner != null) { - - if (townBlock.getPlotPrice() != -1) { - // Plot is for sale - - if (TownyEconomyHandler.isActive() && townBlock.getPlotPrice() > 0 && !resident.getAccount().payTo(townBlock.getPlotPrice(), owner, "Plot - Buy From Seller")) - throw new TownyException(Translatable.of("msg_no_money_purchase_plot")); - - int maxPlots = TownySettings.getMaxResidentPlots(resident); - int extraPlots = TownySettings.getMaxResidentExtraPlots(resident); - - //Infinite plots - if (maxPlots != -1) { - maxPlots = maxPlots + extraPlots; - } - - if (maxPlots >= 0 && resident.getTownBlocks().size() + 1 > maxPlots) - throw new TownyException(Translatable.of("msg_max_plot_own", maxPlots)); - - TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_buy_resident_plot", resident.getName(), owner.getName(), townBlock.getPlotPrice())); - townBlock.setPlotPrice(-1); - townBlock.setResident(resident); - - // Set the plot permissions to mirror the new owners. - townBlock.setType(townBlock.getType()); - - owner.save(); - townBlock.save(); - - // Update any caches for this WorldCoord - plugin.updateCache(worldCoord); - return true; - } else { - //Should never reach here. - throw new AlreadyRegisteredException(Translatable.of("msg_already_claimed", owner.getName()).forLocale(player)); - } + TownBlock townBlock = worldCoord.getTownBlockOrNull(); + if (townBlock == null || !townBlock.hasPlotObjectGroup()) + return; - } else { - //Plot has no owner so it's the town selling it + final PlotGroup group = townBlock.getPlotObjectGroup(); + try { - if (townBlock.getPlotPrice() == -1) - throw new TownyException(Translatable.of("msg_err_plot_nfs")); - - double bankcap = town.getBankCap(); - if (TownyEconomyHandler.isActive() && bankcap > 0) { - if (townBlock.getPlotPrice() + town.getAccount().getHoldingBalance() > bankcap) + /* + * Test that they can actually own that many townblocks. + */ + testMaxPlotsOrThrow(group.getTownBlocks().size()); + + /* + * Handle paying for the plot here so it is not paid for per-townblock in the group. + */ + double groupPrice = group.getPrice(); + if (TownyEconomyHandler.isActive() && groupPrice > 0) { + EconomyHandler seller = group.hasResident() ? group.getResident() : group.getTown(); + String message = String.format("Plot Group - Buy From %s: %s", (group.hasResident() ? "Seller" : "Town"), seller.getName()); + + if (seller instanceof Town town) { // Test that the town wouldn't go over their bank cap. + double bankcap = town.getBankCap(); + if (bankcap > 0 && groupPrice + town.getAccount().getHoldingBalance() > bankcap) throw new TownyException(Translatable.of("msg_err_deposit_capped", bankcap)); } - if (TownyEconomyHandler.isActive() && townBlock.getPlotPrice() > 0 && !resident.getAccount().payTo(townBlock.getPlotPrice(), town, "Plot - Buy From Town")) + // Make them pay, they have already been tested to see if they can afford it in the PlotCommand class. + if (!resident.getAccount().payTo(groupPrice, seller, message)) throw new TownyException(Translatable.of("msg_no_money_purchase_plot")); + } + } catch (TownyException e) { + TownyMessaging.sendErrorMsg(player, e.getMessage(player)); + return; + } catch (Exception e) { + TownyMessaging.sendErrorMsg(player, e.getMessage()); + return; + } + + /* + * Cause the actual claiming here. + */ + residentGroupClaim(group); + group.setResident(resident); + group.setPrice(-1); + TownyMessaging.sendPrefixedTownMessage(townBlock.getTownOrNull(), Translatable.of("msg_player_successfully_bought_group_x", player.getName(), group.getName())); + group.save(); + finishWithMessage(); + } - townBlock.setPlotPrice(-1); - townBlock.setResident(resident); + private void residentGroupClaim(PlotGroup group) { + Town town = group.getTown(); + @Nullable Resident owner = group.getResident(); + if (owner != null && group.getPrice() > 0) + TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_buy_resident_plot_group", resident.getName(), owner.getName(), group.getPrice())); - // Set the plot permissions to mirror the new owners. - townBlock.setType(townBlock.getType()); - townBlock.save(); + for (TownBlock townBlock : group.getTownBlocks()) + claimTownBlockForResident(townBlock); + } - return true; + private void residentClaim(List selection) { + for (WorldCoord worldCoord : selection) { + try { + if (!residentClaim(worldCoord)) + this.selection.remove(worldCoord); + } catch (TownyException e) { + TownyMessaging.sendErrorMsg(player, e.getMessage(player)); } - } catch (NotRegisteredException e) { - throw new TownyException(Translatable.of("msg_err_not_part_town")); } + finishWithMessage(); } - private boolean residentUnclaim(WorldCoord worldCoord) throws TownyException { + private boolean residentClaim(WorldCoord worldCoord) throws TownyException { - try { - TownBlock townBlock = worldCoord.getTownBlock(); + TownBlock townBlock = worldCoord.getTownBlockOrNull(); + if (townBlock == null) + throw new TownyException(Translatable.of("msg_err_not_part_town")); - townBlock.removeResident(); - townBlock.setPlotPrice(townBlock.getTown().getPlotTypePrice(townBlock.getType())); + if (townBlock.getPlotPrice() == -1) + throw new TownyException(Translatable.of("msg_err_plot_nfs")); - // Set the plot permissions to mirror the towns. - townBlock.setType(townBlock.getType()); - townBlock.save(); + Town town = townBlock.getTownOrNull(); + if (!townBlock.getType().equals(TownBlockType.EMBASSY) && !town.hasResident(resident)) + throw new TownyException(Translatable.of("msg_err_not_part_town")); - plugin.updateCache(worldCoord); + testMaxPlotsOrThrow(1); + + /* + * Handle paying for the plot here. + */ + double price = townBlock.getPlotPrice(); + if (TownyEconomyHandler.isActive() && price > 0) { + EconomyHandler seller = townBlock.hasResident() ? townBlock.getResidentOrNull() : townBlock.getTownOrNull(); + String message = String.format("Plot - Buy From %s: %s", (townBlock.hasResident() ? "Seller" : "Town"), seller.getName()); + + if (seller instanceof Town) { // Test that the town wouldn't go over their bank cap. + double bankcap = town.getBankCap(); + if (bankcap > 0 && price + town.getAccount().getHoldingBalance() > bankcap) + throw new TownyException(Translatable.of("msg_err_deposit_capped", bankcap)); + } - } catch (NotRegisteredException e) { - throw new TownyException(Translatable.of("msg_not_own_place")); + // Make them pay, they have already been tested to see if they can afford it in the PlotCommand class. + if (!resident.getAccount().payTo(price, seller, message)) + throw new TownyException(Translatable.of("msg_no_money_purchase_plot")); } + /* + * Handle actual claiming here. + */ + final Resident owner = townBlock.getResidentOrNull(); + if (owner != null && price > 0) + TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_buy_resident_plot", resident.getName(), owner.getName(), townBlock.getPlotPrice())); + + claimTownBlockForResident(townBlock); return true; } + private void claimTownBlockForResident(TownBlock townBlock) { + townBlock.setResident(resident); + townBlock.setPlotPrice(-1); + townBlock.setType(townBlock.getType()); // Causes the plot perms to mirror the new owner's. + townBlock.save(); + plugin.updateCache(townBlock.getWorldCoord()); + } + private void residentUnclaimAll() { + residentUnclaim(new ArrayList<>(resident.getTownBlocks()).stream().map(TownBlock::getWorldCoord).collect(Collectors.toList())); + } - List selection = new ArrayList<>(resident.getTownBlocks()); + private void residentUnclaim(List selection) { + for (WorldCoord coord : selection) { + if (!TownyAPI.getInstance().isTownyWorld(coord.getBukkitWorld())) + continue; - for (TownBlock townBlock : selection) { - try { - residentUnclaim(townBlock.getWorldCoord()); - } catch (TownyException e) { - TownyMessaging.sendErrorMsg(player, e.getMessage(player)); + if(!residentUnclaim(coord)) { + TownyMessaging.sendErrorMsg(player, Translatable.of("msg_not_own_place")); + this.selection.remove(coord); } - } + finishWithMessage(); + } + + private boolean residentUnclaim(WorldCoord worldCoord) { + if (worldCoord.isWilderness()) + return false; + + TownBlock townBlock = worldCoord.getTownBlockOrNull(); + townBlock.removeResident(); + townBlock.setPlotPrice(townBlock.getTownOrNull().getPlotTypePrice(townBlock.getType())); + // Set the plot permissions to mirror the towns. + townBlock.setType(townBlock.getType()); + townBlock.save(); + plugin.updateCache(worldCoord); + return true; } - /** + /* * Used via /ta plot claim {name} - * - * @param worldCoord - * @throws TownyException */ - private void adminClaim(WorldCoord worldCoord) throws TownyException { + private void adminClaim(List selection) { + for (WorldCoord wc : selection) { + if (!adminClaim(wc)) { + TownyMessaging.sendErrorMsg(player, Translatable.of("msg_not_claimed", wc.toString())); + this.selection.remove(wc); + } + } + finishWithMessage(); + } - try { - TownBlock townBlock = worldCoord.getTownBlock(); - @SuppressWarnings("unused") // Used to make sure a plot/town is here. - Town town = townBlock.getTown(); - - townBlock.setPlotPrice(-1); - townBlock.setResident(resident); - townBlock.setType(townBlock.getType()); - townBlock.save(); - - TownyMessaging.sendMsg(resident, Translatable.of("msg_admin_has_given_you_a_plot", worldCoord.toString())); - } catch (NotRegisteredException e) { - //Probably not owned by a town. - throw new TownyException(Translatable.of("msg_not_claimed_1")); + private boolean adminClaim(WorldCoord worldCoord) { + if (worldCoord.isWilderness()) + return false; + + TownBlock townBlock = worldCoord.getTownBlockOrNull(); + townBlock.setPlotPrice(-1); + townBlock.setResident(resident); + townBlock.setType(townBlock.getType()); + townBlock.save(); + plugin.updateCache(worldCoord); + TownyMessaging.sendMsg(resident, Translatable.of("msg_admin_has_given_you_a_plot", worldCoord.toString())); + return true; + } + private void finishWithMessage() { + if (player == null) + return; + if (claim) { + if ((selection != null) && (selection.size() > 0)) { + TownyMessaging.sendMsg(player, Translatable.of("msg_claimed").append(" ") + .append(selection.size() > 5 ? Translatable.of("msg_total_townblocks").forLocale(player) + selection.size() : Arrays.toString(selection.toArray(new WorldCoord[0])))); + } else { + TownyMessaging.sendMsg(player, Translatable.of("msg_not_claimed_1")); + } + } else if (selection != null) { + TownyMessaging.sendMsg(player, Translatable.of("msg_unclaimed").append(" ") + .append(selection.size() > 5 ? Translatable.of("msg_total_townblocks").forLocale(player) + selection.size() : Arrays.toString(selection.toArray(new WorldCoord[0])))); + } else { + TownyMessaging.sendMsg(player, Translatable.of("msg_unclaimed")); } } + private void testMaxPlotsOrThrow(int plotsToBuy) throws TownyException { + int maxPlots = TownySettings.getMaxResidentPlots(resident); + int extraPlots = TownySettings.getMaxResidentExtraPlots(resident); + + //Infinite plots + if (maxPlots != -1) + maxPlots = maxPlots + extraPlots; + + if (maxPlots >= 0 && resident.getTownBlocks().size() + plotsToBuy > maxPlots) + throw new TownyException(Translatable.of("msg_max_plot_own", maxPlots)); + } + } diff --git a/Towny/src/main/resources/lang/en-US.yml b/Towny/src/main/resources/lang/en-US.yml index e80ba96382..1fbfa7eac3 100644 --- a/Towny/src/main/resources/lang/en-US.yml +++ b/Towny/src/main/resources/lang/en-US.yml @@ -494,6 +494,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' msg_buy: '&bBought %d %s for %s.' msg_buy_resident_plot: '&b%s bought %s''s plot for %s!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s couldn''t pay taxes and was kicked from the %s.' msg_couldnt_pay_plot_taxes: '&b%s couldn''t pay taxes and lost ownership of a plot.' msg_payed_town_tax: '&bPayed town tax of ' From 1ec4de0253c40fdb6a9ad81f41b59ad630b2b159 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Wed, 10 Jan 2024 13:53:23 -0600 Subject: [PATCH 47/74] - Refactor parts of the TownCommand class: - Refactor townAddResident method. - Refactor the town join command. - Refactor townSet and the subcommands. - Refactor the TownyWorldCommand class. - Refactor the PlotClaim task. --- Towny/pom.xml | 2 +- Towny/src/main/resources/ChangeLog.txt | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Towny/pom.xml b/Towny/pom.xml index ecdc270eac..b571efe87a 100644 --- a/Towny/pom.xml +++ b/Towny/pom.xml @@ -13,7 +13,7 @@ towny jar - 0.100.1.0 + 0.100.1.1 diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index b66f455904..5bfea8e7db 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9424,4 +9424,11 @@ v0.92.0.11: - Refactor the townRank method. - Add claiming particle effect when new towns are made. 0.100.1.0: - - Bump version for release. \ No newline at end of file + - Bump version for release. +0.100.1.1: + - Refactor parts of the TownCommand class: + - Refactor townAddResident method. + - Refactor the town join command. + - Refactor townSet and the subcommands. + - Refactor the TownyWorldCommand class. + - Refactor the PlotClaim task. \ No newline at end of file From 759e349c4e82b7f43c385977bbb9215f5717f232 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Wed, 10 Jan 2024 14:11:05 -0600 Subject: [PATCH 48/74] Add method to ProximityUtil to determine ability to claim land, (#7151) * Add method to ProximityUtil to determine ability to claim land, Add TownyAPI method to give other plugins an easy way to determine if someone can claim an area. Closes #6004. * Add a unclaim api method to match the claiming version. * Typo * Revert "Add ability for admins using /ta town new [townname] to bypass the rules for claiming. Closes #7163." This reverts commit eab509d8908bdc4ae2c472ee018af98b82de95ae. * Lost a part of a previous commit in the rebase. --- .../palmergames/bukkit/towny/TownyAPI.java | 34 ++++++ .../bukkit/towny/command/TownCommand.java | 61 ++-------- .../bukkit/towny/tasks/TownClaim.java | 2 +- .../bukkit/towny/utils/ProximityUtil.java | 108 ++++++++++++++++++ 4 files changed, 150 insertions(+), 55 deletions(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/TownyAPI.java b/Towny/src/main/java/com/palmergames/bukkit/towny/TownyAPI.java index 4e1a5bbee5..6ed895c009 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/TownyAPI.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/TownyAPI.java @@ -19,6 +19,7 @@ import com.palmergames.bukkit.towny.permissions.PermissionNodes; import com.palmergames.bukkit.towny.tasks.TeleportWarmupTimerTask; import com.palmergames.bukkit.towny.utils.CombatUtil; +import com.palmergames.bukkit.towny.utils.ProximityUtil; import com.palmergames.bukkit.util.BukkitTools; import com.palmergames.util.MathUtil; @@ -932,4 +933,37 @@ public void testPlotOwnerOrThrow(@NotNull Resident resident, @NotNull TownBlock // Nothing to complain about, this resident is the owner of the townblock's town or an admin. } } + + /** + * Test a WorldCoord to see if Towny would allow the area to be claimed by the + * given town. + * + * @param town Town who would become owner of the land. + * @param coordToClaim WorldCoord which is to be claimed. + * @param outpost whether this would be an outpost, with no connected town + * land. + * @param newTown whether this would be a brand new town claiming their + * first plot. + * @throws TownyException thrown when Towny would not allow the claim, with + * message for the reason why. + */ + public void testTownClaimOrThrow(Town town, WorldCoord coordToClaim, boolean outpost, boolean newTown) throws TownyException { + if (newTown) + ProximityUtil.allowTownHomeBlockOrThrow(coordToClaim.getTownyWorld(), coordToClaim, town, true); + + ProximityUtil.allowTownClaimOrThrow(coordToClaim.getTownyWorld(), coordToClaim, town, outpost); + } + + /** + * Test a WorldCoord to see if Towny would allow the area to be unclaimed by the + * given town. + * + * @param town Town that would unclaim the land. + * @param coordToUnclaim WorldCoord which is to be unclaimed. + * @throws TownyException thrown when Towny would not allow the unclaim, with + * message for the reason why. + */ + public void testTownUnclaimOrThrow(Town town, WorldCoord coordToUnclaim) throws TownyException { + ProximityUtil.allowTownUnclaimOrThrow(coordToUnclaim.getTownyWorld(), coordToUnclaim, town); + } } 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 e2e3867c35..562e6919f8 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 @@ -142,7 +142,6 @@ import java.util.Comparator; import java.util.List; import java.util.Locale; -import java.util.Objects; import java.util.Optional; import java.util.UUID; import java.util.logging.Level; @@ -3482,29 +3481,16 @@ private static void vetTownAllowedTheseClaims(Town town, boolean outpost, List town.availableTownBlocks()) throw new TownyException(Translatable.of("msg_err_not_enough_blocks")); - // Prevent straight line claims if configured, and the town has enough townblocks claimed, and this is not an outpost. - int minAdjacentBlocks = TownySettings.getMinAdjacentBlocks(); - if (!outpost && minAdjacentBlocks > 0 && townHasClaimedEnoughLandToBeRestrictedByAdjacentClaims(town, minAdjacentBlocks)) { - // Only consider the first worldCoord, larger selection-claims will automatically "bubble" anyways. - WorldCoord firstWorldCoord = selection.get(0); - int numAdjacent = numAdjacentTownOwnedTownBlocks(town, firstWorldCoord); - // The number of adjacement TBs is not enough and there is not a nearby outpost. - if (numAdjacent < minAdjacentBlocks && numAdjacentOutposts(town, firstWorldCoord) == 0) - throw new TownyException(Translatable.of("msg_min_adjacent_blocks", minAdjacentBlocks, numAdjacent)); - } + // Prevent straight line claims if configured, and the town has enough + // townblocks claimed, and this is not an outpost. + ProximityUtil.testAdjacentClaimsRulesOrThrow(selection.get(0), town, outpost); - // When not claiming an outpost, make sure at least one of the selection is attached to a claimed plot. + // When not claiming an outpost, make sure at least one of the selection is + // attached to a claimed plot. if (!outpost && !isEdgeBlock(town, selection) && !town.getTownBlocks().isEmpty()) throw new TownyException(Translatable.of("msg_err_not_attached_edge")); } - private static boolean townHasClaimedEnoughLandToBeRestrictedByAdjacentClaims(Town town, int minAdjacentBlocks) { - if (minAdjacentBlocks == 3 && town.getTownBlocks().size() < 5) - // Special rule that makes sure a town can claim a fifth plot after claiming a 2x2 square. - return false; - return town.getTownBlocks().size() > minAdjacentBlocks; - } - private static void fireTownPreClaimEventOrThrow(Player player, Town town, boolean outpost, List selection) throws TownyException { int blockedClaims = 0; String cancelMessage = ""; @@ -3584,18 +3570,7 @@ public static void parseTownUnclaimCommand(Player player, String[] split) throws } // Prevent unclaiming land that would reduce the number of adjacent claims of neighbouring plots below the threshold. - int minAdjacentBlocks = TownySettings.getMinAdjacentBlocks(); - if (minAdjacentBlocks > 0 && townHasClaimedEnoughLandToBeRestrictedByAdjacentClaims(town, minAdjacentBlocks)) { - WorldCoord firstWorldCoord = selection.get(0); - for (WorldCoord wc : firstWorldCoord.getCardinallyAdjacentWorldCoords(true)) { - if (wc.isWilderness() || !wc.hasTown(town)) - continue; - int numAdjacent = numAdjacentTownOwnedTownBlocks(town, wc); - // The number of adjacement TBs is not enough and there is not a nearby outpost. - if (numAdjacent - 1 < minAdjacentBlocks && numAdjacentOutposts(town, wc) == 0) - throw new TownyException(Translatable.of("msg_err_cannot_unclaim_not_enough_adjacent_claims", wc.getX(), wc.getZ(), numAdjacent)); - } - } + ProximityUtil.testAdjacentUnclaimsRulesOrThrow(selection.get(0), town); BukkitTools.ifCancelledThenThrow(new TownPreUnclaimCmdEvent(town, resident, world, selection)); @@ -3698,14 +3673,7 @@ private void parseTownTakeoverClaimCommand(Player player) throws TownyException 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. - int minAdjacentBlocks = TownySettings.getMinAdjacentBlocks(); - if (minAdjacentBlocks > 0 && town.getTownBlocks().size() > minAdjacentBlocks) { - // Only consider the first worldCoord, larger selection-claims will automatically "bubble" anyways. - int numAdjacent = numAdjacentTownOwnedTownBlocks(town, wc); - // The number of adjacement TBs is not enough and there is not a nearby outpost. - if (numAdjacent < minAdjacentBlocks && numAdjacentOutposts(town, wc) == 0) - throw new TownyException(Translatable.of("msg_min_adjacent_blocks", minAdjacentBlocks, numAdjacent)); - } + ProximityUtil.testAdjacentClaimsRulesOrThrow(wc, town, false); // Prevent claiming that would cut off a section of a town from the main body. if (takeoverWouldCutATownIntoTwoSections(wc, town)) @@ -3933,21 +3901,6 @@ public static boolean isEdgeBlock(TownBlockOwner owner, WorldCoord worldCoord, L return false; } - public static int numAdjacentTownOwnedTownBlocks(Town town, WorldCoord worldCoord) { - return (int) worldCoord.getCardinallyAdjacentWorldCoords(true).stream() - .filter(wc -> wc.hasTown(town)) - .count(); - } - - public static int numAdjacentOutposts(Town town, WorldCoord worldCoord) { - return (int) worldCoord.getCardinallyAdjacentWorldCoords(true).stream() - .filter(wc -> wc.hasTown(town)) - .map(WorldCoord::getTownBlockOrNull) - .filter(Objects::nonNull) - .filter(TownBlock::isOutpost) - .count(); - } - public static List getValidatedResidentsForInviteRevoke(Object sender, String[] names, Town town) { List toRevoke = new ArrayList<>(); for (Invite invite : town.getSentInvites()) { diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/TownClaim.java b/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/TownClaim.java index 941fdb0821..62c59e2e15 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/TownClaim.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/TownClaim.java @@ -260,7 +260,7 @@ private void handleRevertOnUnclaimPossiblities(WorldCoord worldCoord, TownBlock // Check if a plot snapshot exists for this townblock already (inactive, unqueued regeneration.) if (!TownyUniverse.getInstance().getDataSource().hasPlotData(townBlock)) { // Queue to have a snapshot made if there is not already an earlier snapshot. - plugin.getScheduler().run(worldCoord.getLowerMostCornerLocation(), () -> TownyRegenAPI.handleNewSnapshot(townBlock)); + plugin.getScheduler().runAsync(() -> TownyRegenAPI.handleNewSnapshot(townBlock)); } } diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/ProximityUtil.java b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/ProximityUtil.java index 39ef2753bf..b51ff0cf93 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/ProximityUtil.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/ProximityUtil.java @@ -2,6 +2,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; import org.jetbrains.annotations.Nullable; @@ -13,6 +14,7 @@ import com.palmergames.bukkit.towny.object.Nation; import com.palmergames.bukkit.towny.object.Town; import com.palmergames.bukkit.towny.object.TownBlock; +import com.palmergames.bukkit.towny.object.TownBlockOwner; import com.palmergames.bukkit.towny.object.TownyWorld; import com.palmergames.bukkit.towny.object.Translatable; import com.palmergames.bukkit.towny.object.WorldCoord; @@ -63,6 +65,112 @@ public static void allowTownHomeBlockOrThrow(TownyWorld world, Coord key, @Nulla } } + public static void allowTownClaimOrThrow(TownyWorld world, WorldCoord townBlockToClaim, @Nullable Town town, boolean outpost) throws TownyException { + // Check if the town has claims available. + if (!town.hasUnlimitedClaims() && town.availableTownBlocks() <= 0) + throw new TownyException(Translatable.of("msg_err_not_enough_blocks")); + + // Check if this is already claimed by someone. + if (!townBlockToClaim.isWilderness()) + throw new TownyException(Translatable.of("msg_already_claimed", townBlockToClaim.getTownOrNull())); + + // Check distance to other homeblocks. + if (AreaSelectionUtil.isTooCloseToHomeBlock(townBlockToClaim, town)) + throw new TownyException(Translatable.of("msg_too_close2", Translatable.of("homeblock"))); + + // Check distance to other townblocks. + if (world.getMinDistanceFromOtherTownsPlots(townBlockToClaim, town) >= TownySettings.getMinDistanceFromTownPlotblocks()) + throw new TownyException(Translatable.of("msg_too_close2", Translatable.of("townblock"))); + + // Check adjacent claims rules. + testAdjacentClaimsRulesOrThrow(townBlockToClaim, town, outpost); + + // Check that we're on an edge if it is not an outpost. + if (!outpost && !isEdgeBlock(town, townBlockToClaim) && !town.getTownBlocks().isEmpty()) + throw new TownyException(Translatable.of("msg_err_not_attached_edge")); + } + + public static void testAdjacentClaimsRulesOrThrow(WorldCoord townBlockToClaim, Town town, boolean outpost) throws TownyException { + int minAdjacentBlocks = TownySettings.getMinAdjacentBlocks(); + if (!outpost && minAdjacentBlocks > 0 && townHasClaimedEnoughLandToBeRestrictedByAdjacentClaims(town, minAdjacentBlocks)) { + // Only consider the first worldCoord, larger selection-claims will automatically "bubble" anyways. + int numAdjacent = numAdjacentTownOwnedTownBlocks(town, townBlockToClaim); + // The number of adjacement TBs is not enough and there is not a nearby outpost. + if (numAdjacent < minAdjacentBlocks && numAdjacentOutposts(town, townBlockToClaim) == 0) + throw new TownyException(Translatable.of("msg_min_adjacent_blocks", minAdjacentBlocks, numAdjacent)); + } + } + + private static boolean townHasClaimedEnoughLandToBeRestrictedByAdjacentClaims(Town town, int minAdjacentBlocks) { + if (minAdjacentBlocks == 3 && town.getTownBlocks().size() < 5) + // Special rule that makes sure a town can claim a fifth plot after claiming a 2x2 square. + return false; + return town.getTownBlocks().size() > minAdjacentBlocks; + } + + private static int numAdjacentTownOwnedTownBlocks(Town town, WorldCoord worldCoord) { + return (int) worldCoord.getCardinallyAdjacentWorldCoords(true).stream() + .filter(wc -> wc.hasTown(town)) + .count(); + } + + private static int numAdjacentOutposts(Town town, WorldCoord worldCoord) { + return (int) worldCoord.getCardinallyAdjacentWorldCoords(true).stream() + .filter(wc -> wc.hasTown(town)) + .map(WorldCoord::getTownBlockOrNull) + .filter(Objects::nonNull) + .filter(TownBlock::isOutpost) + .count(); + } + + private static boolean isEdgeBlock(TownBlockOwner owner, WorldCoord worldCoord) { + + for (WorldCoord wc : worldCoord.getCardinallyAdjacentWorldCoords()) { + if (wc.isWilderness()) { + continue; + } + if (!wc.getTownBlockOrNull().isOwner(owner)) { + continue; + } + return true; + } + return false; + } + + /* + * Town Unclaim Methods + */ + + public static void allowTownUnclaimOrThrow(TownyWorld world, WorldCoord townBlockToUnclaim, @Nullable Town town) throws TownyException { + + if (townBlockToUnclaim.isWilderness()) + throw new TownyException(Translatable.of("msg_err_empty_area_selection")); + + if (!townBlockToUnclaim.getTownBlockOrNull().getTownOrNull().equals(town)) + throw new TownyException(Translatable.of("msg_not_own_area")); + + if (townBlockToUnclaim.getTownBlock().isHomeBlock()) + throw new TownyException(Translatable.of("msg_err_cannot_unclaim_homeblock")); + + testAdjacentUnclaimsRulesOrThrow(townBlockToUnclaim, town); + } + + public static void testAdjacentUnclaimsRulesOrThrow(WorldCoord townBlockToUnclaim, Town town) throws TownyException { + // Prevent unclaiming land that would reduce the number of adjacent claims of neighbouring plots below the threshold. + int minAdjacentBlocks = TownySettings.getMinAdjacentBlocks(); + if (minAdjacentBlocks > 0 && townHasClaimedEnoughLandToBeRestrictedByAdjacentClaims(town, minAdjacentBlocks)) { + WorldCoord firstWorldCoord = townBlockToUnclaim; + for (WorldCoord wc : firstWorldCoord.getCardinallyAdjacentWorldCoords(true)) { + if (wc.isWilderness() || !wc.hasTown(town)) + continue; + int numAdjacent = numAdjacentTownOwnedTownBlocks(town, wc); + // The number of adjacement TBs is not enough and there is not a nearby outpost. + if (numAdjacent - 1 < minAdjacentBlocks && numAdjacentOutposts(town, wc) == 0) + throw new TownyException(Translatable.of("msg_err_cannot_unclaim_not_enough_adjacent_claims", wc.getX(), wc.getZ(), numAdjacent)); + } + } + } + /* * Nation Promixity Methods */ From 4cfbb931f85ff79aa39596abf570cce1ec881f92 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Wed, 10 Jan 2024 14:13:47 -0600 Subject: [PATCH 49/74] - API: Added new methods to TownyAPI class to determine claim-ability: - TownyAPI#testTownClaimOrThrow(Town town, WorldCoord coordToClaim, boolean outpost, boolean newTown) - TownyAPI#testTownUnclaimOrThrow(Town town, WorldCoord coordToUnclaim) --- Towny/src/main/resources/ChangeLog.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index 5bfea8e7db..6fcffcfc46 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9431,4 +9431,7 @@ v0.92.0.11: - Refactor the town join command. - Refactor townSet and the subcommands. - Refactor the TownyWorldCommand class. - - Refactor the PlotClaim task. \ No newline at end of file + - Refactor the PlotClaim task. + - API: Added new methods to TownyAPI class to determine claim-ability: + - TownyAPI#testTownClaimOrThrow(Town town, WorldCoord coordToClaim, boolean outpost, boolean newTown) + - TownyAPI#testTownUnclaimOrThrow(Town town, WorldCoord coordToUnclaim) \ No newline at end of file From 2747668a8ddf75369dbfe98cad4456aeadfd0432 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Wed, 10 Jan 2024 14:26:54 -0600 Subject: [PATCH 50/74] - Create Town object methods for determining if a town has enough residents to be a part of a nation, or to be the capital of a nation. - Moves backing logic into TownUtil. --- .../bukkit/towny/command/NationCommand.java | 21 +++--- .../bukkit/towny/command/TownCommand.java | 34 +--------- .../palmergames/bukkit/towny/object/Town.java | 13 ++++ .../bukkit/towny/utils/TownUtil.java | 66 +++++++++++++++++++ Towny/src/main/resources/ChangeLog.txt | 4 +- 5 files changed, 92 insertions(+), 46 deletions(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/command/NationCommand.java b/Towny/src/main/java/com/palmergames/bukkit/towny/command/NationCommand.java index 713fb73248..03bf4607c3 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/command/NationCommand.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/command/NationCommand.java @@ -693,7 +693,7 @@ private void parseNationJoin(Player player, String[] args) { if (nation.hasSanctionedTown(town)) throw new TownyException(Translatable.of("msg_err_cannot_join_nation_sanctioned_town", nation.getName())); - if (!testTownHasEnoughResidents(town)) + if (!town.hasEnoughResidentsToJoinANation()) throw new TownyException(Translatable.of("msg_err_not_enough_residents_join_nation", town.getName())); if (!testNationMaxTowns(nation)) @@ -919,19 +919,20 @@ public void listNations(CommandSender sender, String[] split) throws TownyExcept private void newNation(Player player, String[] split) throws TownyException { Resident resident = getResidentOrThrow(player); - if (TownySettings.getNumResidentsCreateNation() > 0 && resident.getTown().getNumResidents() < TownySettings.getNumResidentsCreateNation()) + Town town = getTownFromResidentOrThrow(resident); + if (!town.hasEnoughResidentsToBeANationCapital()) throw new TownyException(Translatable.of("msg_err_not_enough_residents_new_nation")); if (split.length == 1) throw new TownyException(Translatable.of("msg_specify_nation_name")); - if (!resident.isMayor() && !resident.getTown().hasResidentWithRank(resident, "assistant")) + if (!resident.isMayor() && !town.hasResidentWithRank(resident, "assistant")) throw new TownyException(Translatable.of("msg_peasant_right")); boolean noCharge = TownySettings.getNewNationPrice() == 0.0 || !TownyEconomyHandler.isActive(); String nationName = String.join("_", StringMgmt.remFirstArg(split)); - newNation(player, nationName, resident.getTown(), noCharge); + newNation(player, nationName, town, noCharge); } public static void newNation(Player player, String name, Town capitalTown, boolean noCharge) { @@ -1258,7 +1259,7 @@ public static void nationAdd(Player player, Nation nation, List invited) t continue; } - if (!testTownHasEnoughResidents(town)) { + if (!town.hasEnoughResidentsToJoinANation()) { TownyMessaging.sendErrorMsg(player, Translatable.of("msg_err_not_enough_residents_join_nation", town.getName())); continue; } @@ -1303,7 +1304,7 @@ public static void nationAdd(Nation nation, List towns) throws AlreadyRegi continue; } - if (!testTownHasEnoughResidents(town)) { + if (!town.hasEnoughResidentsToJoinANation()) { // Town has dropped below min.-residents-to-join-nation limit. TownyMessaging.sendPrefixedNationMessage(nation, Translatable.of("msg_err_not_enough_residents_join_nation", town.getName())); TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_err_not_enough_residents_join_nation", town.getName())); @@ -1336,12 +1337,6 @@ private static boolean testNationMaxResidents(Nation nation, Town town) { } - private static boolean testTownHasEnoughResidents(Town town) { - if (TownySettings.getNumResidentsJoinNation() < 1) - return true; - return !(town.getNumResidents() < TownySettings.getNumResidentsJoinNation()); - } - private static boolean testNationMaxTowns(Nation nation) { if (TownySettings.getMaxTownsPerNation() < 1) return true; @@ -2318,7 +2313,7 @@ private static void changeNationOwnership(CommandSender sender, final Nation nat return; } - boolean capitalNotEnoughResidents = TownySettings.getNumResidentsCreateNation() > 0 && newCapital.getNumResidents() < TownySettings.getNumResidentsCreateNation(); + boolean capitalNotEnoughResidents = !newCapital.hasEnoughResidentsToBeANationCapital(); if (capitalNotEnoughResidents && !admin) { TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_not_enough_residents_capital", newCapital.getName())); return; 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 562e6919f8..4ca975d270 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 @@ -2711,7 +2711,7 @@ public void townLeave(Player player) throws TownyException { TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_left_town", resident.getName())); TownyMessaging.sendMsg(player, Translatable.of("msg_left_town", resident.getName())); - checkTownResidents(town); + town.checkTownHasEnoughResidentsForNationRequirements(); }) .setCancellableEvent(new TownLeaveEvent(resident, town)) .sendTo(player); @@ -2968,40 +2968,10 @@ public static void townKickResidents(CommandSender sender, Resident resident, To TownyMessaging.sendMessage(sender, Translation.translateTranslatables(sender, "", Translatable.of("default_town_prefix", StringMgmt.remUnderscore(town.getName())), Translatable.of("msg_kicked", kickerName, message))); } town.save(); + town.checkTownHasEnoughResidentsForNationRequirements(); } else { TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_invalid_name")); } - - checkTownResidents(town); - } - - public static void checkTownResidents(Town town) { - if (!town.hasNation()) - return; - Nation nation = town.getNationOrNull(); - if (town.isCapital() && TownySettings.getNumResidentsCreateNation() > 0 && town.getNumResidents() < TownySettings.getNumResidentsCreateNation()) { - for (Town newCapital : nation.getTowns()) - if (newCapital.getNumResidents() >= TownySettings.getNumResidentsCreateNation()) { - nation.setCapital(newCapital); - if (TownySettings.getNumResidentsJoinNation() > 0 && town.getNumResidents() < TownySettings.getNumResidentsJoinNation()) { - town.removeNation(); - TownyMessaging.sendPrefixedNationMessage(nation, Translatable.of("msg_capital_not_enough_residents_left_nation", town.getName())); - } - TownyMessaging.sendPrefixedNationMessage(nation, Translatable.of("msg_not_enough_residents_no_longer_capital", newCapital.getName())); - return; - } - TownyMessaging.sendPrefixedNationMessage(nation, Translatable.of("msg_nation_disbanded_town_not_enough_residents", town.getName())); - TownyMessaging.sendGlobalMessage(Translatable.of("msg_del_nation", nation)); - TownyUniverse.getInstance().getDataSource().removeNation(nation); - - if (TownyEconomyHandler.isActive() && TownySettings.isRefundNationDisbandLowResidents()) { - town.getAccount().deposit(TownySettings.getNewNationPrice(), "nation refund"); - TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_not_enough_residents_refunded", TownySettings.getNewNationPrice())); - } - } else if (!town.isCapital() && TownySettings.getNumResidentsJoinNation() > 0 && town.getNumResidents() < TownySettings.getNumResidentsJoinNation()) { - TownyMessaging.sendPrefixedNationMessage(nation, Translatable.of("msg_town_not_enough_residents_left_nation", town.getName())); - town.removeNation(); - } } private void parseTownRanklistCommand(final Player player, String[] split) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/object/Town.java b/Towny/src/main/java/com/palmergames/bukkit/towny/object/Town.java index 1a33b5f9aa..ef84a4bc71 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/object/Town.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/object/Town.java @@ -37,6 +37,7 @@ import com.palmergames.bukkit.towny.utils.CombatUtil; import com.palmergames.bukkit.towny.utils.MoneyUtil; import com.palmergames.bukkit.towny.utils.ProximityUtil; +import com.palmergames.bukkit.towny.utils.TownUtil; import com.palmergames.bukkit.towny.utils.TownyComponents; import com.palmergames.bukkit.util.BukkitTools; import net.kyori.adventure.audience.Audience; @@ -1909,4 +1910,16 @@ public void setVisibleOnTopLists(boolean visibleOnTopLists) { public void playerBroadCastMessageToTown(Player player, String message) { TownyMessaging.sendPrefixedTownMessage(this, Translatable.of("town_say_format", player.getName(), TownyComponents.stripClickTags(message))); } + + public void checkTownHasEnoughResidentsForNationRequirements() { + TownUtil.checkNationResidentsRequirementsOfTown(this); + } + + public boolean hasEnoughResidentsToJoinANation() { + return TownUtil.townHasEnoughResidentsToJoinANation(this); + } + + public boolean hasEnoughResidentsToBeANationCapital() { + return TownUtil.townHasEnoughResidentsToBeANationCapital(this); + } } diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/TownUtil.java b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/TownUtil.java index 7bde4685ec..591980568a 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/TownUtil.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/TownUtil.java @@ -3,7 +3,14 @@ import java.util.List; import java.util.stream.Collectors; +import com.palmergames.bukkit.towny.TownyEconomyHandler; +import com.palmergames.bukkit.towny.TownyMessaging; +import com.palmergames.bukkit.towny.TownySettings; +import com.palmergames.bukkit.towny.TownyUniverse; +import com.palmergames.bukkit.towny.object.Nation; import com.palmergames.bukkit.towny.object.Resident; +import com.palmergames.bukkit.towny.object.Town; +import com.palmergames.bukkit.towny.object.Translatable; import com.palmergames.bukkit.util.BukkitTools; import com.palmergames.util.TimeTools; @@ -27,4 +34,63 @@ public static List gatherInactiveResidents(List resList, int .collect(Collectors.toList()); } + public static void checkNationResidentsRequirementsOfTown(Town town) { + if (!town.hasNation()) + return; + Nation nation = town.getNationOrNull(); + + // Check non-capital rules first, towns must maintain a number of residents to be a part of a nation. + if (!town.isCapital() && !town.hasEnoughResidentsToJoinANation()) { + TownyMessaging.sendPrefixedNationMessage(nation, Translatable.of("msg_town_not_enough_residents_left_nation", town.getName())); + town.removeNation(); + return; + } + + // Check the nation-creation rules that apply to nation capitals. Towns must maintain a number of residents to do so. + if (town.isCapital() && !town.hasEnoughResidentsToBeANationCapital()) { + // If a new capital can be found we don't delete the nation. + if (findNewCapital(town, nation)) + return; + + // No new capital found, delete the nation and potentially refund the capital town. + TownyMessaging.sendPrefixedNationMessage(nation, Translatable.of("msg_nation_disbanded_town_not_enough_residents", town.getName())); + TownyMessaging.sendGlobalMessage(Translatable.of("msg_del_nation", nation)); + TownyUniverse.getInstance().getDataSource().removeNation(nation); + + if (TownyEconomyHandler.isActive() && TownySettings.isRefundNationDisbandLowResidents()) { + town.getAccount().deposit(TownySettings.getNewNationPrice(), "nation refund"); + TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_not_enough_residents_refunded", TownySettings.getNewNationPrice())); + } + } + } + + private static boolean findNewCapital(Town town, Nation nation) { + for (Town newCapital : nation.getTowns()) + if (newCapital.hasEnoughResidentsToBeANationCapital()) { + // We've found a suitable new capital that has enough residents. + nation.setCapital(newCapital); + // Check if the old capital can remain in the nation as a non-capital town. + if (!town.hasEnoughResidentsToJoinANation()) { + town.removeNation(); + TownyMessaging.sendPrefixedNationMessage(nation, Translatable.of("msg_capital_not_enough_residents_left_nation", town.getName())); + } + // Announce the new capital and return true. + TownyMessaging.sendPrefixedNationMessage(nation, Translatable.of("msg_not_enough_residents_no_longer_capital", newCapital.getName())); + return true; + } + // Return false and require the nation to be deleted. + return false; + } + + public static boolean townHasEnoughResidentsToBeANationCapital(Town town) { + if (TownySettings.getNumResidentsCreateNation() < 1) + return true; + return town.getNumResidents() >= TownySettings.getNumResidentsCreateNation(); + } + + public static boolean townHasEnoughResidentsToJoinANation(Town town) { + if (TownySettings.getNumResidentsJoinNation() < 1) + return true; + return town.getNumResidents() >= TownySettings.getNumResidentsJoinNation(); + } } diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index 6fcffcfc46..0f5ab89071 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9434,4 +9434,6 @@ v0.92.0.11: - Refactor the PlotClaim task. - API: Added new methods to TownyAPI class to determine claim-ability: - TownyAPI#testTownClaimOrThrow(Town town, WorldCoord coordToClaim, boolean outpost, boolean newTown) - - TownyAPI#testTownUnclaimOrThrow(Town town, WorldCoord coordToUnclaim) \ No newline at end of file + - TownyAPI#testTownUnclaimOrThrow(Town town, WorldCoord coordToUnclaim) + - Create Town object methods for determining if a town has enough residents to be a part of a nation, or to be the capital of a nation. + - Moves backing logic into TownUtil. \ No newline at end of file From 6b4fa1305ef3c7c10ce700ef382716aef6bee7c4 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Wed, 10 Jan 2024 15:05:27 -0600 Subject: [PATCH 51/74] - Remove some verbose boolean returns. --- .../com/palmergames/bukkit/towny/utils/ShopPlotUtil.java | 8 ++------ .../main/java/com/palmergames/bukkit/util/BlockUtil.java | 5 +---- Towny/src/main/resources/ChangeLog.txt | 3 ++- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/ShopPlotUtil.java b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/ShopPlotUtil.java index afc89ee443..715747dce3 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/ShopPlotUtil.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/ShopPlotUtil.java @@ -55,9 +55,7 @@ public static boolean doesPlayerOwnShopPlot(Player player, Location location) { * @return true if the player can build and the plot is a shop */ public static boolean doesPlayerHaveAbilityToEditShopPlot(Player player, Location location) { - if (TownyActionEventExecutor.canBuild(player, location, Material.DIRT) && isShopPlot(location)) - return true; - else return false; + return TownyActionEventExecutor.canBuild(player, location, Material.DIRT) && isShopPlot(location); } /** @@ -81,9 +79,7 @@ public static boolean isShopPlot(Location location) { */ public static boolean isShopPlot(TownBlock townblock) { if (townblock != null) { - if (townblock.getType().equals(TownBlockType.COMMERCIAL)) - return true; - else return false; + return townblock.getType().equals(TownBlockType.COMMERCIAL); } else return false; } } diff --git a/Towny/src/main/java/com/palmergames/bukkit/util/BlockUtil.java b/Towny/src/main/java/com/palmergames/bukkit/util/BlockUtil.java index e2de9103d6..ba1618ecc4 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/util/BlockUtil.java +++ b/Towny/src/main/java/com/palmergames/bukkit/util/BlockUtil.java @@ -113,10 +113,7 @@ public static boolean sameOwnerOrHasMayorOverride(Block b1, Block b2, Player pla return false; if (tb.hasResident() != tb2.hasResident()) // One is player-owned and one isn't. - if (isResidentActingMayorOfTown(resident, tb.getTownOrNull())) - return true; - else - return false; + return isResidentActingMayorOfTown(resident, tb.getTownOrNull()); if (!tb.hasResident() && !tb2.hasResident()) // Both plots are town-owned. return true; diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index 0f5ab89071..affa6a159e 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9436,4 +9436,5 @@ v0.92.0.11: - TownyAPI#testTownClaimOrThrow(Town town, WorldCoord coordToClaim, boolean outpost, boolean newTown) - TownyAPI#testTownUnclaimOrThrow(Town town, WorldCoord coordToUnclaim) - Create Town object methods for determining if a town has enough residents to be a part of a nation, or to be the capital of a nation. - - Moves backing logic into TownUtil. \ No newline at end of file + - Moves backing logic into TownUtil. + - Remove some verbose boolean returns. \ No newline at end of file From 60a6c5019cb78e11ff2e2d0fa44b345b2467092a Mon Sep 17 00:00:00 2001 From: LlmDl Date: Wed, 10 Jan 2024 15:06:05 -0600 Subject: [PATCH 52/74] Swap l for L. --- .../palmergames/bukkit/towny/listeners/TownyCustomListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyCustomListener.java b/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyCustomListener.java index 02b3d24fe3..c48ec640c6 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyCustomListener.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyCustomListener.java @@ -80,7 +80,7 @@ public void onPlayerChangePlotEvent(PlayerChangePlotEvent event) { if (resident.hasMode("townunclaim")) TownCommand.parseTownUnclaimCommand(player, new String[] {}); if (resident.hasMode("plotgroup") && resident.hasPlotGroupName()) - Towny.getPlugin().getScheduler().runLater(player, () -> Bukkit.dispatchCommand(player, "plot group add " + resident.getPlotGroupName()), 1l); + Towny.getPlugin().getScheduler().runLater(player, () -> Bukkit.dispatchCommand(player, "plot group add " + resident.getPlotGroupName()), 1L); } catch (TownyException e) { TownyMessaging.sendErrorMsg(player, e.getMessage(player)); } From cd9da7946126ad5b0e25a96cf33d3419d8ffd32b Mon Sep 17 00:00:00 2001 From: LlmDl Date: Wed, 10 Jan 2024 15:06:40 -0600 Subject: [PATCH 53/74] Remove bonus ; --- .../bukkit/towny/event/nation/toggle/NationToggleEvent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/event/nation/toggle/NationToggleEvent.java b/Towny/src/main/java/com/palmergames/bukkit/towny/event/nation/toggle/NationToggleEvent.java index 220c0e68dc..6e89a578d9 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/event/nation/toggle/NationToggleEvent.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/event/nation/toggle/NationToggleEvent.java @@ -23,7 +23,7 @@ public abstract class NationToggleEvent extends CancellableTownyEvent { public NationToggleEvent(CommandSender sender, Nation nation, boolean admin) { this.sender = sender; if (sender instanceof Player) - this.player = (Player) sender;; + this.player = (Player) sender; this.nation = nation; this.isAdminAction = admin; setCancelMessage(Translation.of("msg_err_command_disable")); From 85de0c3c07c47197b9e43260c8ef64e5b941f5f3 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Thu, 11 Jan 2024 10:28:22 -0600 Subject: [PATCH 54/74] - Fix issues discovered in HealthRegenTimerTask where saturation gain was being unable to happen consistently when server TPS drops. - Code is now run Async during player evaluation, becoming Sync'd when we are about to heal someone. - Towny now properly uses the EntityRegainHealthEvent, reporting the correct amount of health gain, as well as not healing players if this event is cancelled. - Added config option to turn on/off the saturation top-up that goes along with the health-regen in towns. - New Config Option: global_town_settings.saturation_regen.also_prevent_saturation_loss - Default: true - When true players cannot become hungrier when in their own or an allied town. --- .../bukkit/config/ConfigNodes.java | 5 ++ .../bukkit/towny/TownySettings.java | 4 ++ .../bukkit/towny/TownyTimerHandler.java | 2 +- .../towny/tasks/HealthRegenTimerTask.java | 70 ++++++++++++------- Towny/src/main/resources/ChangeLog.txt | 9 ++- 5 files changed, 62 insertions(+), 28 deletions(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/config/ConfigNodes.java b/Towny/src/main/java/com/palmergames/bukkit/config/ConfigNodes.java index eb74575b89..672c5385ef 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/config/ConfigNodes.java +++ b/Towny/src/main/java/com/palmergames/bukkit/config/ConfigNodes.java @@ -492,6 +492,11 @@ public enum ConfigNodes { GTOWN_SETTINGS_REGEN_ENABLE( "global_town_settings.health_regen.enable", "true"), + GTOWN_SETTINGS_REGEN_PREVENT_SATURATION_LOSS( + "global_town_settings.saturation_regen.also_prevent_saturation_loss", + "true", + "", + "# When true players cannot become hungrier when in their own or an allied town."), GTOWN_SETTINGS_PVP_COOLDOWN_TIMER( "global_town_settings.pvp_cooldown_time", diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/TownySettings.java b/Towny/src/main/java/com/palmergames/bukkit/towny/TownySettings.java index 1ac847f399..470676a1ef 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/TownySettings.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/TownySettings.java @@ -1533,6 +1533,10 @@ public static boolean hasHealthRegen() { return getBoolean(ConfigNodes.GTOWN_SETTINGS_REGEN_ENABLE); } + public static boolean preventSaturationLoss() { + return getBoolean(ConfigNodes.GTOWN_SETTINGS_REGEN_PREVENT_SATURATION_LOSS); + } + public static boolean getTownDefaultPublic() { return getBoolean(ConfigNodes.TOWN_DEF_PUBLIC); diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/TownyTimerHandler.java b/Towny/src/main/java/com/palmergames/bukkit/towny/TownyTimerHandler.java index fc3c7e8466..57df320da1 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/TownyTimerHandler.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/TownyTimerHandler.java @@ -97,7 +97,7 @@ public static void toggleShortTimer(boolean on) { public static void toggleHealthRegen(boolean on) { if (on && !isHealthRegenRunning()) { - healthRegenTask = plugin.getScheduler().runRepeating(new HealthRegenTimerTask(plugin, BukkitTools.getServer()), 1, TimeTools.convertToTicks(TownySettings.getHealthRegenSpeed())); + healthRegenTask = plugin.getScheduler().runAsyncRepeating(new HealthRegenTimerTask(plugin, BukkitTools.getServer()), 1, TimeTools.convertToTicks(TownySettings.getHealthRegenSpeed())); } else if (!on && isHealthRegenRunning()) { healthRegenTask.cancel(); healthRegenTask = null; diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/HealthRegenTimerTask.java b/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/HealthRegenTimerTask.java index 528238e110..81207c062a 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/HealthRegenTimerTask.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/HealthRegenTimerTask.java @@ -3,6 +3,8 @@ import com.palmergames.bukkit.towny.TownySettings; import com.palmergames.bukkit.towny.TownyTimerHandler; import com.palmergames.bukkit.towny.object.Town; +import com.palmergames.bukkit.towny.object.TownBlock; + import org.bukkit.NamespacedKey; import org.bukkit.Server; import org.bukkit.attribute.Attribute; @@ -12,7 +14,6 @@ import com.palmergames.bukkit.towny.Towny; import com.palmergames.bukkit.towny.TownyAPI; -import com.palmergames.bukkit.towny.object.TownBlock; import com.palmergames.bukkit.towny.object.TownBlockType; import com.palmergames.bukkit.towny.utils.CombatUtil; import com.palmergames.bukkit.util.BukkitTools; @@ -35,45 +36,62 @@ public void run() { if (plugin.isFolia()) { for (Player player : server.getOnlinePlayers()) - plugin.getScheduler().run(player, () -> checkPlayer(player)); + plugin.getScheduler().run(player, () -> evaluatePlayer(player)); } else { for (Player player : server.getOnlinePlayers()) - checkPlayer(player); + evaluatePlayer(player); } } - public void checkPlayer(final Player player) { + public void evaluatePlayer(final Player player) { + // Player is already dead. if (player.getHealth() <= 0) return; - final TownBlock townBlock = TownyAPI.getInstance().getTownBlock(player); - // Is wilderness - if (townBlock == null) + if (!TownyAPI.getInstance().isTownyWorld(player.getWorld())) return; - Town playerTown = TownyAPI.getInstance().getTown(player); + Town town = TownyAPI.getInstance().getTown(player); + // Player has no Town; + if (town == null) + return; - if (playerTown != null - && !playerTown.hasActiveWar() - && CombatUtil.isAlly(townBlock.getTownOrNull(), playerTown) - && !townBlock.getType().equals(TownBlockType.ARENA)) // only regen if not in an arena - incHealth(player); + // Heal and saturate if allowed based on Location. + if (playerAllowedToHealHere(town, TownyAPI.getInstance().getTownBlock(player))); + evaluateHealth(player); } - public void incHealth(Player player) { + private boolean playerAllowedToHealHere(Town playersTown, TownBlock tbAtPlayer) { + if (tbAtPlayer == null) + return false; + Town townAtPlayer = tbAtPlayer.getTownOrNull(); + return !townAtPlayer.hasActiveWar() && CombatUtil.isAlly(townAtPlayer, playersTown) && !tbAtPlayer.getType().equals(TownBlockType.ARENA); + } - // Keep saturation above zero while in town. - if (player.getSaturation() == 0) + private void evaluateHealth(Player player) { + // When enabled, keep saturation above zero while in town, preventing food level loss. + if (TownySettings.preventSaturationLoss() && player.getSaturation() != 1F) player.setSaturation(1F); - - // Heal while in town. - double currentHP = player.getHealth(); - double maxHP = player.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue(); - if (currentHP < maxHP) { - player.setHealth(Math.min(maxHP, ++currentHP)); - - // Raise an event so other plugins can keep in sync. - BukkitTools.fireEvent(new EntityRegainHealthEvent(player, currentHP, RegainReason.REGEN)); - } + + // Heal 1 HP while in town. + final double currentHP = player.getHealth(); + final double futureHP = currentHP + 1; + final double maxHP = player.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue(); + + // Shrink gained to fit below the maxHP. + final double gained = futureHP > maxHP ? 1.0 - (futureHP - maxHP) : 1.0; + if (gained <= 0) + return; + + // Drop back to Sync so we can throw the EntityRegainHealthEvent. + plugin.getScheduler().run(()-> tryIncreaseHealth(player, currentHP, maxHP, gained)); + } + + private void tryIncreaseHealth(Player player, double currentHealth, double maxHealth, double gained) { + EntityRegainHealthEvent event = new EntityRegainHealthEvent(player, gained, RegainReason.REGEN); + if (BukkitTools.isEventCancelled(event)) + return; + + player.setHealth(Math.min(maxHealth, event.getAmount() + currentHealth)); } } diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index affa6a159e..92cd1b6c62 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9437,4 +9437,11 @@ v0.92.0.11: - TownyAPI#testTownUnclaimOrThrow(Town town, WorldCoord coordToUnclaim) - Create Town object methods for determining if a town has enough residents to be a part of a nation, or to be the capital of a nation. - Moves backing logic into TownUtil. - - Remove some verbose boolean returns. \ No newline at end of file + - Remove some verbose boolean returns. + - Fix issues discovered in HealthRegenTimerTask where saturation gain was being unable to happen consistently when server TPS drops. + - Code is now run Async during player evaluation, becoming Sync'd when we are about to heal someone. + - Towny now properly uses the EntityRegainHealthEvent, reporting the correct amount of health gain, as well as not healing players if this event is cancelled. + - Added config option to turn on/off the saturation top-up that goes along with the health-regen in towns. + - New Config Option: global_town_settings.saturation_regen.also_prevent_saturation_loss + - Default: true + - When true players cannot become hungrier when in their own or an allied town. \ No newline at end of file From b7e4842d8e3ae1f9942675774811f5581941d3ea Mon Sep 17 00:00:00 2001 From: LlmDl Date: Thu, 11 Jan 2024 10:29:59 -0600 Subject: [PATCH 55/74] Update the town kicking method, and decouple the admin version of town (#7186) kicking. --- .../bukkit/towny/command/TownCommand.java | 127 ++++++++---------- .../towny/command/TownyAdminCommand.java | 14 +- 2 files changed, 70 insertions(+), 71 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 4ca975d270..45315f20bd 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 @@ -2785,27 +2785,6 @@ public void townDelete(Player player, String[] split) throws TownyException { }).sendTo(player); } - /** - * Transforms a list of names into a list of residents to be kicked. - * Command: /town kick [resident] .. [resident] - * - * @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) 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)); - - // Reset everyones cache permissions as this player leaving can affect - // multiple areas. - plugin.resetCache(); - } - public static void townAddResidents(CommandSender sender, Town town, List invited) throws TownyException { List invitedResidents = invited.stream() .filter(res -> inviteResidentToTownOrThrow(sender, res, town)) @@ -2913,69 +2892,77 @@ private static void townRevokeInviteResident(CommandSender sender, Town town, Li } } + /** + * Transforms a list of names into a list of residents to be kicked. + * Command: /town kick [resident] .. [resident] + * + * @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) 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)); + + // Reset everyones cache permissions as this player leaving can affect + // multiple areas. + plugin.resetCache(); + } + /** * Method for kicking residents from a town. * - * @param sender - CommandSender who initiated the kick. - * @param resident - Resident who initiated the kick. - * @param town - Town the list of Residents are being kicked from. - * @param kicking - List of Residents being kicked from Towny. + * @param sender CommandSender who initiated the kick. + * @param resident Resident who initiated the kick. + * @param town Town the list of Residents are being kicked from. + * @param kicking List of Residents being kicked from Towny. + * @throws TownyException when there is no one to kick. */ - public static void townKickResidents(CommandSender sender, Resident resident, Town town, List kicking) { + private static void townKickResidents(CommandSender sender, Resident resident, Town town, List kicking) throws TownyException { + List kickedResidents = kicking.stream() + .filter(res -> kickResidentFromTownOrThrow(sender, resident, res, town)) + .map(Resident::getName) + .collect(Collectors.toList()); - Resident senderResident = sender instanceof Player player ? TownyAPI.getInstance().getResident(player) : null; - - for (Resident member : new ArrayList<>(kicking)) { - if (!town.hasResident(member)) { - TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_resident_not_your_town")); - kicking.remove(member); - continue; - } + if (kickedResidents.isEmpty()) + throw new TownyException(Translatable.of("msg_invalid_name")); - if (member.equals(resident)) { - TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_you_cannot_kick_yourself")); - kicking.remove(member); - continue; - } + town.checkTownHasEnoughResidentsForNationRequirements(); + town.save(); - // The player being kicked is either the mayor or has an 'unkickable' rank (usually an assistant) - // The rank check is bypassed if the sender is either not a player or not in the same town as the player being kicked, for townyadmin purposes - if (member.isMayor() || (senderResident != null && !senderResident.isMayor() && town.hasResident(senderResident) && TownySettings.getTownUnkickableRanks().stream().anyMatch(member::hasTownRank))) { - TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_you_cannot_kick_this_resident", member)); - kicking.remove(member); - continue; - } + TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_kicked", resident.getName(), StringMgmt.join(kickedResidents, ", "))); + } - TownKickEvent townKickEvent = new TownKickEvent(member, sender); - if (BukkitTools.isEventCancelled(townKickEvent)) { - TownyMessaging.sendErrorMsg(sender, townKickEvent.getCancelMessage()); - kicking.remove(member); - } else - member.removeTown(); - } - - if (kicking.size() > 0) { - String message = kicking.stream().map(Resident::getName).collect(Collectors.joining(", ")); - String kickerName = sender instanceof Player player ? player.getName() : "CONSOLE"; + private static boolean kickResidentFromTownOrThrow(CommandSender sender, Resident senderResident, Resident resToKick, Town town) { + try { + if (!town.hasResident(resToKick)) + throw new TownyException(Translatable.of("msg_resident_not_your_town")); - for (Resident member : kicking) - TownyMessaging.sendMsg(member, Translatable.of("msg_kicked_by", kickerName)); + if (senderResident.equals(resToKick)) + throw new TownyException(Translatable.of("msg_you_cannot_kick_yourself")); - TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_kicked", kickerName, message)); + if (resToKick.isMayor()) + throw new TownyException(Translatable.of("msg_you_cannot_kick_this_resident", resToKick)); - if (!(sender instanceof Player kickingPlayer) || !town.hasResident(kickingPlayer)) { - // For when the an admin uses /ta town {name} kick {residents} - TownyMessaging.sendMessage(sender, Translation.translateTranslatables(sender, "", Translatable.of("default_town_prefix", StringMgmt.remUnderscore(town.getName())), Translatable.of("msg_kicked", kickerName, message))); - } - town.save(); - town.checkTownHasEnoughResidentsForNationRequirements(); - } else { - TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_invalid_name")); + if (!senderResident.isMayor() && TownySettings.getTownUnkickableRanks().stream().anyMatch(resToKick::hasTownRank)) + throw new TownyException(Translatable.of("msg_you_cannot_kick_this_resident", resToKick)); + + BukkitTools.ifCancelledThenThrow(new TownKickEvent(resToKick, sender)); + + // Finally kick the resident. + resToKick.removeTown(); + } catch (TownyException e) { + TownyMessaging.sendErrorMsg(sender, e.getMessage(sender)); + return false; } + return true; } - private void parseTownRanklistCommand(final Player player, String[] split) - throws NoPermissionException, TownyException { + private void parseTownRanklistCommand(final Player player, String[] split) throws NoPermissionException, TownyException { Town town; checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_RANKLIST.getNode()); catchRuinedTown(player); diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownyAdminCommand.java b/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownyAdminCommand.java index 5cb4777dc9..efc435ad7e 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownyAdminCommand.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/command/TownyAdminCommand.java @@ -1198,7 +1198,19 @@ public void parseAdminTownCommand(CommandSender sender, String[] split) throws T break; case "kick": checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYADMIN_TOWN_KICK.getNode()); - TownCommand.townKickResidents(sender, town.getMayor(), town, ResidentUtil.getValidatedResidentsOfTown(sender, town, StringMgmt.remArgs(split, 2))); + // Force-kick command for admins. + if (split.length < 3) + throw new TownyException(Translatable.of("msg_err_invalid_input", "/ta town TOWNNAME kick PLAYERNAME")); + resident = getResidentOrThrow(split[2]); + if (!town.hasResident(resident)) + throw new TownyException(Translatable.of("msg_err_townadmintownrank_wrong_town")); + if (resident.isMayor()) + throw new TownyException(Translatable.of("msg_you_cannot_kick_this_resident", resident.getName())); + resident.removeTown(); + TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_kicked", "Console", resident.getName())); + TownyMessaging.sendMsg(sender, Translatable.of("msg_kicked", "You", resident.getName())); + if (resident.isOnline()) + TownyMessaging.sendMsg(resident, Translatable.of("msg_kicked_by", "Console")); break; case "delete": checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYADMIN_TOWN_DELETE.getNode()); From c6a4115dfd95e93cd2d3f8aba295ef03f5bae82d Mon Sep 17 00:00:00 2001 From: LlmDl Date: Thu, 11 Jan 2024 10:31:36 -0600 Subject: [PATCH 56/74] - Refactor the TownCommand's town kicking method, and decouple the admin version of town kicking. --- Towny/src/main/resources/ChangeLog.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index 92cd1b6c62..4d56f6342a 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9444,4 +9444,5 @@ v0.92.0.11: - Added config option to turn on/off the saturation top-up that goes along with the health-regen in towns. - New Config Option: global_town_settings.saturation_regen.also_prevent_saturation_loss - Default: true - - When true players cannot become hungrier when in their own or an allied town. \ No newline at end of file + - When true players cannot become hungrier when in their own or an allied town. + - Refactor the TownCommand's town kicking method, and decouple the admin version of town kicking. \ No newline at end of file From 08df609c420a099fef22ec354a3173b16a7e503a Mon Sep 17 00:00:00 2001 From: LlmDl Date: Thu, 11 Jan 2024 10:31:56 -0600 Subject: [PATCH 57/74] New Crowdin updates (#7187) * New translations en-us.yml (Chinese Simplified) * New translations en-us.yml (German) * New translations en-us.yml (Romanian) * New translations en-us.yml (French) * New translations en-us.yml (Spanish) * New translations en-us.yml (Bulgarian) * New translations en-us.yml (Czech) * New translations en-us.yml (Danish) * New translations en-us.yml (Hebrew) * New translations en-us.yml (Italian) * New translations en-us.yml (Japanese) * New translations en-us.yml (Korean) * New translations en-us.yml (Lithuanian) * New translations en-us.yml (Dutch) * New translations en-us.yml (Norwegian) * New translations en-us.yml (Polish) * New translations en-us.yml (Portuguese) * New translations en-us.yml (Russian) * New translations en-us.yml (Albanian) * New translations en-us.yml (Swedish) * New translations en-us.yml (Turkish) * New translations en-us.yml (Ukrainian) * New translations en-us.yml (Chinese Traditional) * New translations en-us.yml (Vietnamese) * New translations en-us.yml (Portuguese, Brazilian) * New translations en-us.yml (Indonesian) * New translations en-us.yml (Spanish, Argentina) * New translations en-us.yml (Spanish, Chile) * New translations en-us.yml (Spanish, Mexico) * New translations en-us.yml (Spanish, Uruguay) * New translations en-us.yml (Spanish, Venezuela) * New translations en-us.yml (Spanish, Ecuador) * New translations en-us.yml (Thai) * New translations en-us.yml (Azerbaijani) * New translations en-us.yml (English, United Kingdom) * New translations en-us.yml (Tagalog) * New translations en-us.yml (Pirate English) * New translations en-us.yml (Serbian (Latin)) * New translations en-us.yml (English (upside down)) * New translations en-us.yml (LOLCAT) * New translations en-us.yml (Classical Chinese) --- Towny/src/main/resources/lang/az-AZ.yml | 1 + Towny/src/main/resources/lang/bg-BG.yml | 1 + Towny/src/main/resources/lang/cs-CZ.yml | 1 + Towny/src/main/resources/lang/da-DK.yml | 1 + Towny/src/main/resources/lang/de-DE.yml | 1 + Towny/src/main/resources/lang/en-GB.yml | 1 + Towny/src/main/resources/lang/en-PT.yml | 1 + Towny/src/main/resources/lang/en-UD.yml | 1 + Towny/src/main/resources/lang/es-AR.yml | 1 + Towny/src/main/resources/lang/es-CL.yml | 1 + Towny/src/main/resources/lang/es-EC.yml | 1 + Towny/src/main/resources/lang/es-ES.yml | 1 + Towny/src/main/resources/lang/es-MX.yml | 1 + Towny/src/main/resources/lang/es-UY.yml | 1 + Towny/src/main/resources/lang/es-VE.yml | 1 + Towny/src/main/resources/lang/fr-FR.yml | 1 + Towny/src/main/resources/lang/he-IL.yml | 1 + Towny/src/main/resources/lang/id-ID.yml | 1 + Towny/src/main/resources/lang/it-IT.yml | 1 + Towny/src/main/resources/lang/ja-JP.yml | 1 + Towny/src/main/resources/lang/ko-KR.yml | 1 + Towny/src/main/resources/lang/lol-US.yml | 1 + Towny/src/main/resources/lang/lt-LT.yml | 1 + Towny/src/main/resources/lang/lzh.yml | 1 + Towny/src/main/resources/lang/nl-NL.yml | 1 + Towny/src/main/resources/lang/no-NO.yml | 1 + Towny/src/main/resources/lang/pl-PL.yml | 1 + Towny/src/main/resources/lang/pt-BR.yml | 1 + Towny/src/main/resources/lang/pt-PT.yml | 1 + Towny/src/main/resources/lang/ro-RO.yml | 1 + Towny/src/main/resources/lang/ru-RU.yml | 1 + Towny/src/main/resources/lang/sq-AL.yml | 1 + Towny/src/main/resources/lang/sr-CS.yml | 1 + Towny/src/main/resources/lang/sv-SE.yml | 1 + Towny/src/main/resources/lang/th-TH.yml | 1 + Towny/src/main/resources/lang/tl-PH.yml | 1 + Towny/src/main/resources/lang/tr-TR.yml | 1 + Towny/src/main/resources/lang/uk-UA.yml | 1 + Towny/src/main/resources/lang/vi-VN.yml | 1 + Towny/src/main/resources/lang/zh-CN.yml | 1 + Towny/src/main/resources/lang/zh-TW.yml | 1 + 41 files changed, 41 insertions(+) diff --git a/Towny/src/main/resources/lang/az-AZ.yml b/Towny/src/main/resources/lang/az-AZ.yml index 0f4e7fedb9..02ee7bbe42 100644 --- a/Towny/src/main/resources/lang/az-AZ.yml +++ b/Towny/src/main/resources/lang/az-AZ.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&b%s üçün %d %s alıb.' msg_buy_resident_plot: '&b%s, %s üçün %s sahəsini alıb!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s vergi ödəyə bilmədi və %s tərəfindən qovuldu.' msg_couldnt_pay_plot_taxes: '&b%s vergi ödəyə bilmədi və bir sahəsini itirdi.' msg_payed_town_tax: '&bÖdənilmiş şəhər vergisi ' diff --git a/Towny/src/main/resources/lang/bg-BG.yml b/Towny/src/main/resources/lang/bg-BG.yml index 8544fa1f78..3d37035596 100644 --- a/Towny/src/main/resources/lang/bg-BG.yml +++ b/Towny/src/main/resources/lang/bg-BG.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&bЗакупи %d %s за %s.' msg_buy_resident_plot: '&b%s закупи площта на %s за %s!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s не можа да плати данъците и беше изритан от %s.' msg_couldnt_pay_plot_taxes: '&b%s не можа да плати данъците и загуби своя парцел.' msg_payed_town_tax: '&bПлати градски данък от ' diff --git a/Towny/src/main/resources/lang/cs-CZ.yml b/Towny/src/main/resources/lang/cs-CZ.yml index 007d9827dc..6e80c6ac6e 100644 --- a/Towny/src/main/resources/lang/cs-CZ.yml +++ b/Towny/src/main/resources/lang/cs-CZ.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&bZakoupeno %d %s za %s.' msg_buy_resident_plot: '&b%s koupil od %s parcelu za %s!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s neměl/a na zaplacení daní a není už součástí sídla %s.' msg_couldnt_pay_plot_taxes: '&b%s neměl/a na zaplacení daní a již nevlastní parcelu.' msg_payed_town_tax: '&bZaplacena městká daň ' diff --git a/Towny/src/main/resources/lang/da-DK.yml b/Towny/src/main/resources/lang/da-DK.yml index 6eca2209df..e5639ff673 100644 --- a/Towny/src/main/resources/lang/da-DK.yml +++ b/Towny/src/main/resources/lang/da-DK.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&bKøbte %d %s for %s.' msg_buy_resident_plot: '&b%s købte %s''s grund for %s!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s kunne ikke betale skat og blev smidt ud af %s.' msg_couldnt_pay_plot_taxes: '&b%s kunne ikke betale skat og mistede ejerskab af en grund.' msg_payed_town_tax: '&bBetalte byskat på ' diff --git a/Towny/src/main/resources/lang/de-DE.yml b/Towny/src/main/resources/lang/de-DE.yml index 25f7cffff9..694cbce711 100644 --- a/Towny/src/main/resources/lang/de-DE.yml +++ b/Towny/src/main/resources/lang/de-DE.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&bKaufte %d %s für %s.' msg_buy_resident_plot: '&b%s kaufte %s'' Grundstück für %s!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s konnte die Steuern nicht bezahlen und wurde deshalb aus %s rausgeschmissen.' msg_couldnt_pay_plot_taxes: '&b%s konnte die Steuern für die Plots nicht bezahlen und verliert den Anspruch auf ein Grundstück.' msg_payed_town_tax: '&bSteuern wurden bezahlt an ' diff --git a/Towny/src/main/resources/lang/en-GB.yml b/Towny/src/main/resources/lang/en-GB.yml index 4f001c2b46..a252ae9848 100644 --- a/Towny/src/main/resources/lang/en-GB.yml +++ b/Towny/src/main/resources/lang/en-GB.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&bBought %d %s for %s.' msg_buy_resident_plot: '&b%s bought %s''s plot for %s!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s couldn''t pay taxes and was kicked from the %s.' msg_couldnt_pay_plot_taxes: '&b%s couldn''t pay taxes and lost ownership of a plot.' msg_payed_town_tax: '&bPayed town tax of ' diff --git a/Towny/src/main/resources/lang/en-PT.yml b/Towny/src/main/resources/lang/en-PT.yml index f4edcb3ad5..6ff9739453 100644 --- a/Towny/src/main/resources/lang/en-PT.yml +++ b/Towny/src/main/resources/lang/en-PT.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&bBought %d %s for %s.' msg_buy_resident_plot: '&b%s bought %s''s plot for %s!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s couldn''t pay taxes and was kicked from the %s.' msg_couldnt_pay_plot_taxes: '&b%s couldn''t pay taxes and lost ownership of a plot.' msg_payed_town_tax: '&bPayed town tax of ' diff --git a/Towny/src/main/resources/lang/en-UD.yml b/Towny/src/main/resources/lang/en-UD.yml index 39b7d29f68..e6e8a3c549 100644 --- a/Towny/src/main/resources/lang/en-UD.yml +++ b/Towny/src/main/resources/lang/en-UD.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&bBought %d %s for %s.' msg_buy_resident_plot: '&b%s bought %s''s plot for %s!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s couldn''t pay taxes and was kicked from the %s.' msg_couldnt_pay_plot_taxes: '&b%s couldn''t pay taxes and lost ownership of a plot.' msg_payed_town_tax: '&bPayed town tax of ' diff --git a/Towny/src/main/resources/lang/es-AR.yml b/Towny/src/main/resources/lang/es-AR.yml index bd05a5d6cc..60b33c71f4 100644 --- a/Towny/src/main/resources/lang/es-AR.yml +++ b/Towny/src/main/resources/lang/es-AR.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&bCompró %d %s por %s.' msg_buy_resident_plot: '&b%s compró el terreno de %s por %s!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s no pudo pagar los impuestos y fue expulsado de %s.' msg_couldnt_pay_plot_taxes: '&b%s no pudo pagar los impuestos y perdió la propiedad de un terreno.' msg_payed_town_tax: '&bPagaste los impuestos de la ciudad ' diff --git a/Towny/src/main/resources/lang/es-CL.yml b/Towny/src/main/resources/lang/es-CL.yml index 97abbfb7a8..a391c6a8a4 100644 --- a/Towny/src/main/resources/lang/es-CL.yml +++ b/Towny/src/main/resources/lang/es-CL.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&bCompró %d %s por %s.' msg_buy_resident_plot: '&b%s compró el terreno de %s por %s!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s no pudo pagar los impuestos y fue expulsado de %s.' msg_couldnt_pay_plot_taxes: '&b%s no pudo pagar los impuestos y perdió la propiedad de un terreno.' msg_payed_town_tax: '&bPagaste los impuestos de la ciudad ' diff --git a/Towny/src/main/resources/lang/es-EC.yml b/Towny/src/main/resources/lang/es-EC.yml index 4b388c684e..85b2c2036c 100644 --- a/Towny/src/main/resources/lang/es-EC.yml +++ b/Towny/src/main/resources/lang/es-EC.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&bCompró %d %s por %s.' msg_buy_resident_plot: '&b%s compró el terreno de %s por %s!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s no pudo pagar los impuestos y fue expulsado de %s.' msg_couldnt_pay_plot_taxes: '&b%s no pudo pagar los impuestos y perdió la propiedad de un terreno.' msg_payed_town_tax: '&bPagaste los impuestos de la ciudad ' diff --git a/Towny/src/main/resources/lang/es-ES.yml b/Towny/src/main/resources/lang/es-ES.yml index 0bf1b91dc4..346b41852d 100644 --- a/Towny/src/main/resources/lang/es-ES.yml +++ b/Towny/src/main/resources/lang/es-ES.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&bCompró %d %s por %s.' msg_buy_resident_plot: '&b%s le compro parcelas a %s por %s!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s no pudo pagar los impuestos y fue echado de %s.' msg_couldnt_pay_plot_taxes: '&b%s no pudo pagar los impuestos y perdió una parcela.' msg_payed_town_tax: '&bPagó los impuestos de ' diff --git a/Towny/src/main/resources/lang/es-MX.yml b/Towny/src/main/resources/lang/es-MX.yml index c52e30f8ce..0dd0fee25d 100644 --- a/Towny/src/main/resources/lang/es-MX.yml +++ b/Towny/src/main/resources/lang/es-MX.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&bCompró %d %s por %s.' msg_buy_resident_plot: '&b%s compró el terreno de %s por %s!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s no pudo pagar los impuestos y fue expulsado de %s.' msg_couldnt_pay_plot_taxes: '&b%s no pudo pagar los impuestos y perdió la propiedad de un terreno.' msg_payed_town_tax: '&bPagaste los impuestos de la ciudad ' diff --git a/Towny/src/main/resources/lang/es-UY.yml b/Towny/src/main/resources/lang/es-UY.yml index 4b388c684e..85b2c2036c 100644 --- a/Towny/src/main/resources/lang/es-UY.yml +++ b/Towny/src/main/resources/lang/es-UY.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&bCompró %d %s por %s.' msg_buy_resident_plot: '&b%s compró el terreno de %s por %s!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s no pudo pagar los impuestos y fue expulsado de %s.' msg_couldnt_pay_plot_taxes: '&b%s no pudo pagar los impuestos y perdió la propiedad de un terreno.' msg_payed_town_tax: '&bPagaste los impuestos de la ciudad ' diff --git a/Towny/src/main/resources/lang/es-VE.yml b/Towny/src/main/resources/lang/es-VE.yml index 4b388c684e..85b2c2036c 100644 --- a/Towny/src/main/resources/lang/es-VE.yml +++ b/Towny/src/main/resources/lang/es-VE.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&bCompró %d %s por %s.' msg_buy_resident_plot: '&b%s compró el terreno de %s por %s!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s no pudo pagar los impuestos y fue expulsado de %s.' msg_couldnt_pay_plot_taxes: '&b%s no pudo pagar los impuestos y perdió la propiedad de un terreno.' msg_payed_town_tax: '&bPagaste los impuestos de la ciudad ' diff --git a/Towny/src/main/resources/lang/fr-FR.yml b/Towny/src/main/resources/lang/fr-FR.yml index 0ceaaf7b3c..23b992baaa 100644 --- a/Towny/src/main/resources/lang/fr-FR.yml +++ b/Towny/src/main/resources/lang/fr-FR.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&bAchète %d %s pour %s.' msg_buy_resident_plot: '&b%s Achète la parcelle de %s pour %s !' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s ne pouvait pas payer les impôts et a été exclu de la %s.' msg_couldnt_pay_plot_taxes: '&b%s ne pouvait pas payer les impôts et a perdu la propriété d''une parcelle.' msg_payed_town_tax: '&ba payé les impôts de la ville de ' diff --git a/Towny/src/main/resources/lang/he-IL.yml b/Towny/src/main/resources/lang/he-IL.yml index 7d8f52adb0..bbb76b1f3c 100644 --- a/Towny/src/main/resources/lang/he-IL.yml +++ b/Towny/src/main/resources/lang/he-IL.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&b.סך הכל (%2$s) בעבור (%d%1$s) קנה את ' msg_buy_resident_plot: '&b!סך הכל (%3$s) בעבור (%2$s) קנה את החלקה של (%1$s) השחקן' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b.%s-לא עמד בתשלום מיסים וגורש מ s%' msg_couldnt_pay_plot_taxes: '&b%s לא עמד בתשלום מיסים ואיבד בעלות על חלקה.' msg_payed_town_tax: '&b שילם מס לעיר בסכום של ' diff --git a/Towny/src/main/resources/lang/id-ID.yml b/Towny/src/main/resources/lang/id-ID.yml index f0e438d7d7..74afb41c2e 100644 --- a/Towny/src/main/resources/lang/id-ID.yml +++ b/Towny/src/main/resources/lang/id-ID.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&bMembeli %d %s seharga %s.' msg_buy_resident_plot: '&b%s membeli %s lahan seharga %s!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s tidak mampu membayar pajak, dan dikeluarkan dari %s.' msg_couldnt_pay_plot_taxes: '&b%s tidak mampu membayar pajak, dan kepemilikan lahan di hapus.' msg_payed_town_tax: '&bMembayar pajak kota ' diff --git a/Towny/src/main/resources/lang/it-IT.yml b/Towny/src/main/resources/lang/it-IT.yml index adf8eee75f..1e35289ed9 100644 --- a/Towny/src/main/resources/lang/it-IT.yml +++ b/Towny/src/main/resources/lang/it-IT.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&bComprato %d %s per %s.' msg_buy_resident_plot: '&b%s ha comprato il lotto di %s per %s!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s non poteva pagare le tasse ed è stato cacciato da %s.' msg_couldnt_pay_plot_taxes: '&b%s non poteva pagare le tasse e ha perso la proprietà di un lotto.' msg_payed_town_tax: '&bSono state pagate le tasse della città di ' diff --git a/Towny/src/main/resources/lang/ja-JP.yml b/Towny/src/main/resources/lang/ja-JP.yml index 4ab6acc595..a2c0250980 100644 --- a/Towny/src/main/resources/lang/ja-JP.yml +++ b/Towny/src/main/resources/lang/ja-JP.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&b%d %s を %s で購入しました' msg_buy_resident_plot: '&b%s が %s のプロットを %s で購入しました!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s は税金を払うことができなかったため、 %s からキックされました' msg_couldnt_pay_plot_taxes: '&s%s は税金を払うことができなかったため、プロットの所有権を失いました' msg_payed_town_tax: '%b税金を支払いました: ' diff --git a/Towny/src/main/resources/lang/ko-KR.yml b/Towny/src/main/resources/lang/ko-KR.yml index 9fef214591..a881a5beed 100644 --- a/Towny/src/main/resources/lang/ko-KR.yml +++ b/Towny/src/main/resources/lang/ko-KR.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&b%d %s를 %s에 구매하였습니다.' msg_buy_resident_plot: '&b%s는 %ss 만큼의 %s 땅을 구매하였습니다.' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s님은 세금을 미납하여 %s에서 추방되었습니다.' msg_couldnt_pay_plot_taxes: '&b%s님은 세금을 미납하여 땅의 소유권을 잃었습니다.' msg_payed_town_tax: '&b지불한 마을 세금: ' diff --git a/Towny/src/main/resources/lang/lol-US.yml b/Towny/src/main/resources/lang/lol-US.yml index 1487c5972f..af31d7b183 100644 --- a/Towny/src/main/resources/lang/lol-US.yml +++ b/Towny/src/main/resources/lang/lol-US.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&bBought %d %s for %s.' msg_buy_resident_plot: '&b%s bought %s''s plot for %s!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s couldn''t pay taxes and was kicked from the %s.' msg_couldnt_pay_plot_taxes: '&b%s couldn''t pay taxes and lost ownership of a plot.' msg_payed_town_tax: '&bPayed town tax of ' diff --git a/Towny/src/main/resources/lang/lt-LT.yml b/Towny/src/main/resources/lang/lt-LT.yml index d4bc5dc642..2fb71d5f68 100644 --- a/Towny/src/main/resources/lang/lt-LT.yml +++ b/Towny/src/main/resources/lang/lt-LT.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Parduoti sklypus spinduliu.' ############################################################ msg_buy: '&bNusipirkote %d %s už %s.' msg_buy_resident_plot: '&b%s nusipirko %s sklypą už %s!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s negalėjo sumokėti mokesčių ir buvo išmestas iš %s.' msg_couldnt_pay_plot_taxes: '&b%s negalėjo sumokėti mokesčių ir prarado sklypo nuosavybės teises.' msg_payed_town_tax: '&b Sumokėtas miesto mokestis ' diff --git a/Towny/src/main/resources/lang/lzh.yml b/Towny/src/main/resources/lang/lzh.yml index ef0eb5ffeb..655b3db3bb 100644 --- a/Towny/src/main/resources/lang/lzh.yml +++ b/Towny/src/main/resources/lang/lzh.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&b用%s購買了%d%s ' msg_buy_resident_plot: '&b%s花費了%s購買了%s地段!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s因為交不起稅而被%s放逐 ' msg_couldnt_pay_plot_taxes: '&b%s因為交不起稅而失去了他的地段所有權 ' msg_payed_town_tax: '&b繳納市鎮地方稅 ' diff --git a/Towny/src/main/resources/lang/nl-NL.yml b/Towny/src/main/resources/lang/nl-NL.yml index ab55909c59..b71c446d40 100644 --- a/Towny/src/main/resources/lang/nl-NL.yml +++ b/Towny/src/main/resources/lang/nl-NL.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&bHeeft %d %s voor %s gekocht.' msg_buy_resident_plot: '&b%s heeft %s''s plot gekocht voor %s!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s kon geen belastingen betalen en werd uit de %s gezet.' msg_couldnt_pay_plot_taxes: '&b%s kon geen belastingen betalen en heeft het eigendom van een plot verloren.' msg_payed_town_tax: '&bBetaalde stad belasting van ' diff --git a/Towny/src/main/resources/lang/no-NO.yml b/Towny/src/main/resources/lang/no-NO.yml index 3cbdc36d62..0df933a092 100644 --- a/Towny/src/main/resources/lang/no-NO.yml +++ b/Towny/src/main/resources/lang/no-NO.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&bKjøpt %d %s for %s.' msg_buy_resident_plot: '&b%s Kjøpt %s''s tomt for %s!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s Kunne ikke betale skatt og ble fjernet fra %s.' msg_couldnt_pay_plot_taxes: '&b%s Kunne ikke betale skatt og mistet eierskapet av en tomt.' msg_payed_town_tax: '&bBetalte ned skatten ' diff --git a/Towny/src/main/resources/lang/pl-PL.yml b/Towny/src/main/resources/lang/pl-PL.yml index e3d8b5a270..7d4d6704cc 100644 --- a/Towny/src/main/resources/lang/pl-PL.yml +++ b/Towny/src/main/resources/lang/pl-PL.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Wystawia podany promień działek na sprzedaż.' ############################################################ msg_buy: '&bKupiono %s (%d szt.) za %s.' msg_buy_resident_plot: '&b%s kupił działkę od %s za %s!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&bMieszkaniec %s nie mógł zapłacić podatków i został wyrzucony z %s.' msg_couldnt_pay_plot_taxes: '&b%s nie mógł zapłacić podatków i został wysiedlony ze swojej działki.' msg_payed_town_tax: '&bZapłacono podatki miejskie: ' diff --git a/Towny/src/main/resources/lang/pt-BR.yml b/Towny/src/main/resources/lang/pt-BR.yml index 96a676da6e..93307daf34 100644 --- a/Towny/src/main/resources/lang/pt-BR.yml +++ b/Towny/src/main/resources/lang/pt-BR.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&bComprou %d %s por %s.' msg_buy_resident_plot: '&b%s comprou o terreno de %s por %s!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s não conseguiu pagar os impostos e foi expulso de %s.' msg_couldnt_pay_plot_taxes: '&b%s não conseguiu pagar os impostos e perdeu a posse de um terreno.' msg_payed_town_tax: '&bVocê pagou o imposto da cidade de ' diff --git a/Towny/src/main/resources/lang/pt-PT.yml b/Towny/src/main/resources/lang/pt-PT.yml index cb9331b367..462ba6d4c1 100644 --- a/Towny/src/main/resources/lang/pt-PT.yml +++ b/Towny/src/main/resources/lang/pt-PT.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&bComprou %d %s por %s.' msg_buy_resident_plot: '&b%s comprou o terreno de %s por %s!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s não conseguiu pagar os impostos e foi expulso de %s.' msg_couldnt_pay_plot_taxes: '&b%s não conseguiu pagar os impostos e perdeu a posse de um terreno.' msg_payed_town_tax: '&bPagaste os impostos da cidade de ' diff --git a/Towny/src/main/resources/lang/ro-RO.yml b/Towny/src/main/resources/lang/ro-RO.yml index f4cc71a5e1..4b7bca046d 100644 --- a/Towny/src/main/resources/lang/ro-RO.yml +++ b/Towny/src/main/resources/lang/ro-RO.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&bA cumpărat %d %s pentru %s.' msg_buy_resident_plot: '&b%s a cumpărat plotul lui %s pentru %s!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s nu a putut să-şi plătească taxele şi a fost dat afară din %s.' msg_couldnt_pay_plot_taxes: '&b%s nu a putut să-şi plătească taxele şi a pierdut stăpânirea asupra unui plot.' msg_payed_town_tax: '&bA plătit taxa oraşului de ' diff --git a/Towny/src/main/resources/lang/ru-RU.yml b/Towny/src/main/resources/lang/ru-RU.yml index d1d56f5911..0aad25802c 100644 --- a/Towny/src/main/resources/lang/ru-RU.yml +++ b/Towny/src/main/resources/lang/ru-RU.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&bКуплено %d %s за %s.' msg_buy_resident_plot: '&b%s купил участок %s за %s!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s не смог оплатить налоги, и был изгнан из города %s.' msg_couldnt_pay_plot_taxes: '&b%s не смог заплатить налоги и потерял свой участок.' msg_payed_town_tax: '&bЗаплатил налог городу ' diff --git a/Towny/src/main/resources/lang/sq-AL.yml b/Towny/src/main/resources/lang/sq-AL.yml index b5a48be825..02b98c173a 100644 --- a/Towny/src/main/resources/lang/sq-AL.yml +++ b/Towny/src/main/resources/lang/sq-AL.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&bBought %d %s for %s.' msg_buy_resident_plot: '&b%s bought %s''s plot for %s!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s couldn''t pay taxes and was kicked from the %s.' msg_couldnt_pay_plot_taxes: '&b%s couldn''t pay taxes and lost ownership of a plot.' msg_payed_town_tax: '&bPayed town tax of ' diff --git a/Towny/src/main/resources/lang/sr-CS.yml b/Towny/src/main/resources/lang/sr-CS.yml index 44d543f0de..cd849b0b5a 100644 --- a/Towny/src/main/resources/lang/sr-CS.yml +++ b/Towny/src/main/resources/lang/sr-CS.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&bKupili ste %d %s za %s.' msg_buy_resident_plot: '&b%s je kupio/la plot igrača %s za %s!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s je izbačen/a iz %s zbog nemogućnosti da plati poreze.' msg_couldnt_pay_plot_taxes: '&b%s je izgubio/la vlasništvo nad plotom zbog nemogućnosti da plati poreze.' msg_payed_town_tax: '&bIsplaćen gradski porez od ' diff --git a/Towny/src/main/resources/lang/sv-SE.yml b/Towny/src/main/resources/lang/sv-SE.yml index 7fa4af5658..03ada153d5 100644 --- a/Towny/src/main/resources/lang/sv-SE.yml +++ b/Towny/src/main/resources/lang/sv-SE.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&bKöpte %d %s till priset %s.' msg_buy_resident_plot: '&b%s köpte %s mark till priset %s!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s kunde inte betala skatten och blev utslängd från %s.' msg_couldnt_pay_plot_taxes: '&b%s kunde inte betala skatten och förlorade sin mark.' msg_payed_town_tax: '&bBetalade statsskatten ' diff --git a/Towny/src/main/resources/lang/th-TH.yml b/Towny/src/main/resources/lang/th-TH.yml index dec934e944..621daff82f 100644 --- a/Towny/src/main/resources/lang/th-TH.yml +++ b/Towny/src/main/resources/lang/th-TH.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&bซื้อ %d %s สำหรับ %s' msg_buy_resident_plot: '&b%s ซื้อพล็อตของ %s สำหรับ %s!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s ไม่สามารถจ่ายภาษีได้และถูกไล่ออกจาก %s' msg_couldnt_pay_plot_taxes: '&b%s ไม่สามารถจ่ายภาษีได้และเสียความเป็นเจ้าของ plot' msg_payed_town_tax: '&bจ่ายภาษีเมืองของ' diff --git a/Towny/src/main/resources/lang/tl-PH.yml b/Towny/src/main/resources/lang/tl-PH.yml index 3e365358ea..47cf3a5278 100644 --- a/Towny/src/main/resources/lang/tl-PH.yml +++ b/Towny/src/main/resources/lang/tl-PH.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&bBinili %d %s para sa %s.' msg_buy_resident_plot: '&b%s ay binili ang plot ni%s para sa %s!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: 'Si &b%s ay hindi nakapag-bayad nang buwis at ito ay natanggal sa %s.' msg_couldnt_pay_plot_taxes: 'Si &b%s ay hindi makapag-bayad nang buwis at nawala nito ang pag-mamay ari sa lupa.' msg_payed_town_tax: '&bBinayaran ang buwis ng ' diff --git a/Towny/src/main/resources/lang/tr-TR.yml b/Towny/src/main/resources/lang/tr-TR.yml index ddb89da742..261ec831e9 100644 --- a/Towny/src/main/resources/lang/tr-TR.yml +++ b/Towny/src/main/resources/lang/tr-TR.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&b%s için %d %s satın aldı.' msg_buy_resident_plot: '&b%s, %s için %s arsasını satın aldı!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s vergi ödeyemedi ve %s tarafından atıldı.' msg_couldnt_pay_plot_taxes: '&b%s vergi ödeyemedi ve bir arsasını kaybetti.' msg_payed_town_tax: '&bÖdenen şehir vergisi ' diff --git a/Towny/src/main/resources/lang/uk-UA.yml b/Towny/src/main/resources/lang/uk-UA.yml index 0ae7ccd3f7..9bfe7fcf5a 100644 --- a/Towny/src/main/resources/lang/uk-UA.yml +++ b/Towny/src/main/resources/lang/uk-UA.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&bПридбано %d %s за %s.' msg_buy_resident_plot: '&b%s купив ділянку землі %s за %s!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s не зміг сплатити податки, і був вигнаний з міста %s.' msg_couldnt_pay_plot_taxes: '&b%s не зміг сплатити податки й втратив право на власність ділянки.' msg_payed_town_tax: '&bЗаплатив податок місту ' diff --git a/Towny/src/main/resources/lang/vi-VN.yml b/Towny/src/main/resources/lang/vi-VN.yml index d792178f11..dbcf780ab6 100644 --- a/Towny/src/main/resources/lang/vi-VN.yml +++ b/Towny/src/main/resources/lang/vi-VN.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&bĐã mua %d %s với giá %s.' msg_buy_resident_plot: '&b%s đã mua mảnh đất của %s với giá %s!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s không thể nộp thuế và bị đuổi khỏi %s.' msg_couldnt_pay_plot_taxes: '&b%s không thể nộp thuế và mất quyền sở hữu mảnh đất.' msg_payed_town_tax: '&bĐã nộp thuế thị trấn của ' diff --git a/Towny/src/main/resources/lang/zh-CN.yml b/Towny/src/main/resources/lang/zh-CN.yml index 35c3fc091c..71c9e4b09d 100644 --- a/Towny/src/main/resources/lang/zh-CN.yml +++ b/Towny/src/main/resources/lang/zh-CN.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&b用 %s 购买了 %d %s .' msg_buy_resident_plot: '&b%s 花费了 %s 购买了 %s 的土地!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s 因为交不起税而被踢出了 %s.' msg_couldnt_pay_plot_taxes: '&b%s 交不起税而失去了他的土地所有权.' msg_payed_town_tax: '&b缴纳城镇税: ' diff --git a/Towny/src/main/resources/lang/zh-TW.yml b/Towny/src/main/resources/lang/zh-TW.yml index ae400e91ce..d73ee04c22 100644 --- a/Towny/src/main/resources/lang/zh-TW.yml +++ b/Towny/src/main/resources/lang/zh-TW.yml @@ -424,6 +424,7 @@ msg_plot_fs_radius: 'Put up a radius of plots for sale.' ############################################################ msg_buy: '&b用%s購買了%d%s ' msg_buy_resident_plot: '&b%s花費了%s購買了%s地段!' +msg_buy_resident_plot_group: '&b%s bought %s''s plotgroup for %s!' msg_couldnt_pay_taxes: '&b%s因為交不起稅而被%s放逐 ' msg_couldnt_pay_plot_taxes: '&b%s因為交不起稅而失去了他的地段所有權 ' msg_payed_town_tax: '&b繳納市鎮地方稅 ' From e1f25746c162c8a72f66515d20ae4af9c9e30f8b Mon Sep 17 00:00:00 2001 From: LlmDl Date: Thu, 11 Jan 2024 10:34:54 -0600 Subject: [PATCH 58/74] Errant ; --- .../palmergames/bukkit/towny/tasks/HealthRegenTimerTask.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/HealthRegenTimerTask.java b/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/HealthRegenTimerTask.java index 81207c062a..9c30dbce31 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/HealthRegenTimerTask.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/HealthRegenTimerTask.java @@ -57,7 +57,7 @@ public void evaluatePlayer(final Player player) { return; // Heal and saturate if allowed based on Location. - if (playerAllowedToHealHere(town, TownyAPI.getInstance().getTownBlock(player))); + if (playerAllowedToHealHere(town, TownyAPI.getInstance().getTownBlock(player))) evaluateHealth(player); } From 12899c325f2929e6c52e85967d84f2b5bbba3dfd Mon Sep 17 00:00:00 2001 From: LlmDl Date: Fri, 12 Jan 2024 14:01:14 -0600 Subject: [PATCH 59/74] - Fix non-mayors being able to add non-kickable-ranked residents as outlaws, which would have allowed them to be kicked. --- Towny/pom.xml | 2 +- .../com/palmergames/bukkit/towny/command/TownCommand.java | 5 ++++- Towny/src/main/resources/ChangeLog.txt | 4 +++- Towny/src/main/resources/lang/en-US.yml | 6 +++++- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Towny/pom.xml b/Towny/pom.xml index b571efe87a..80b5948420 100644 --- a/Towny/pom.xml +++ b/Towny/pom.xml @@ -13,7 +13,7 @@ towny jar - 0.100.1.1 + 0.100.1.2 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 45315f20bd..a49bc55153 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 @@ -921,7 +921,10 @@ public static void parseTownOutlawCommand(CommandSender sender, String[] split, 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; + throw new TownyException(Translatable.of("msg_err_you_cannot_outlaw_your_mayor")); + + if (!resident.isMayor() && TownySettings.getTownUnkickableRanks().stream().anyMatch(target::hasTownRank)) + throw new TownyException(Translatable.of("msg_err_you_cannot_outlaw_because_of_rank", target.getName())); if (town.hasOutlaw(target)) throw new TownyException(Translatable.of("msg_err_resident_already_an_outlaw")); diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index 4d56f6342a..80fa973f4f 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9445,4 +9445,6 @@ v0.92.0.11: - New Config Option: global_town_settings.saturation_regen.also_prevent_saturation_loss - Default: true - When true players cannot become hungrier when in their own or an allied town. - - Refactor the TownCommand's town kicking method, and decouple the admin version of town kicking. \ No newline at end of file + - Refactor the TownCommand's town kicking method, and decouple the admin version of town kicking. +0.100.1.2: + - Fix non-mayors being able to add non-kickable-ranked residents as outlaws, which would have allowed them to be kicked. \ No newline at end of file diff --git a/Towny/src/main/resources/lang/en-US.yml b/Towny/src/main/resources/lang/en-US.yml index 1fbfa7eac3..4ec67d9105 100644 --- a/Towny/src/main/resources/lang/en-US.yml +++ b/Towny/src/main/resources/lang/en-US.yml @@ -2420,4 +2420,8 @@ msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not a msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' -msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' \ No newline at end of file +msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' + +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." + +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." \ No newline at end of file From 4f08eae0930b373f5651b23c2ad3e3f6d6ef7088 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Fri, 12 Jan 2024 14:21:41 -0600 Subject: [PATCH 60/74] - Refactor MapHUD class. --- .../bukkit/towny/huds/HUDManager.java | 2 +- .../palmergames/bukkit/towny/huds/MapHUD.java | 265 ++++++++++-------- Towny/src/main/resources/ChangeLog.txt | 3 +- 3 files changed, 158 insertions(+), 112 deletions(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/huds/HUDManager.java b/Towny/src/main/java/com/palmergames/bukkit/towny/huds/HUDManager.java index 0c0e1502e4..d2d5b434fa 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/huds/HUDManager.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/huds/HUDManager.java @@ -146,6 +146,6 @@ public static boolean isPermHUDActive(Player player) { } public static boolean isMapHudActive(Player player) { - return player.getScoreboard().getTeam("mapTeam1") != null; + return player.getScoreboard().getTeam(MapHUD.mapHudTestKey()) != null; } } diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/huds/MapHUD.java b/Towny/src/main/java/com/palmergames/bukkit/towny/huds/MapHUD.java index 72b7a31200..b1a81a62fb 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/huds/MapHUD.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/huds/MapHUD.java @@ -9,7 +9,6 @@ import com.palmergames.bukkit.towny.object.Resident; import com.palmergames.bukkit.towny.object.Town; import com.palmergames.bukkit.towny.object.TownBlock; -import com.palmergames.bukkit.towny.object.TownyWorld; import com.palmergames.bukkit.towny.object.Translatable; import com.palmergames.bukkit.towny.object.WorldCoord; import com.palmergames.bukkit.towny.object.map.TownyMapData; @@ -27,28 +26,47 @@ import org.bukkit.scoreboard.Scoreboard; public class MapHUD { + + /* Scoreboards use old-timey colours. */ + private static final ChatColor WHITE = ChatColor.WHITE; + private static final ChatColor GOLD = ChatColor.GOLD; + private static final ChatColor GREEN = ChatColor.GREEN; + private static final ChatColor DARK_GREEN = ChatColor.DARK_GREEN; + + /* Scoreboards use Teams here is our team names.*/ + private static final String HUD_OBJECTIVE = "MAP_HUD_OBJ"; + private static final String TEAM_MAP_PREFIX = "mapTeam"; + private static final String TEAM_OWNER = "ownerTeam"; + private static final String TEAM_TOWN = "townTeam"; + private static int lineWidth = 19, lineHeight = 10; - + private static int halfLineWidth = lineWidth/2; + private static int halfLineHeight = lineHeight/2; + + public static String mapHudTestKey() { + return "mapTeam1"; + } + public static void toggleOn(Player player) { Scoreboard board = Bukkit.getScoreboardManager().getNewScoreboard(); - Objective objective = BukkitTools.objective(board, "MAP_HUD_OBJ", "maphud"); + Objective objective = BukkitTools.objective(board, HUD_OBJECTIVE, "maphud"); objective.setDisplaySlot(DisplaySlot.SIDEBAR); int score = lineHeight + 2; ChatColor[] colors = ChatColor.values(); for (int i = 0; i < lineHeight; i++) { - board.registerNewTeam("mapTeam" + i).addEntry(colors[i].toString()); + board.registerNewTeam(TEAM_MAP_PREFIX + i).addEntry(colors[i].toString()); objective.getScore(colors[i].toString()).setScore(score); score--; } - String townEntry = ChatColor.DARK_GREEN + Translatable.of("town_sing").forLocale(player) + ": "; - String ownerEntry = ChatColor.DARK_GREEN + Translatable.of("owner_status").forLocale(player) + ": "; + String townEntry = DARK_GREEN + Translatable.of("town_sing").forLocale(player) + ": "; + String ownerEntry = DARK_GREEN + Translatable.of("owner_status").forLocale(player) + ": "; - board.registerNewTeam("townTeam").addEntry(townEntry); + board.registerNewTeam(TEAM_TOWN).addEntry(townEntry); objective.getScore(townEntry).setScore(2); - board.registerNewTeam("ownerTeam").addEntry(ownerEntry); + board.registerNewTeam(TEAM_OWNER).addEntry(ownerEntry); objective.getScore(ownerEntry).setScore(1); player.setScoreboard(board); @@ -64,128 +82,155 @@ public static void updateMap(Player player, WorldCoord wc) { if (board == null) { toggleOn(player); return; - } else if (board.getObjective("MAP_HUD_OBJ") == null) { + } else if (board.getObjective(HUD_OBJECTIVE) == null || wc.getTownyWorld() == null || !wc.getTownyWorld().isUsingTowny()) { HUDManager.toggleOff(player); return; } - Objective objective = board.getObjective("MAP_HUD_OBJ"); - objective.setDisplayName(ChatColor.GOLD + "Towny Map " + ChatColor.WHITE + "(" + wc.getX() + ", " + wc.getZ() + ")"); + int wcX = wc.getX(); + int wcZ = wc.getZ(); + // Set the board title. + String boardTitle = String.format("%sTowny Map %s(%s, %s)", GOLD, WHITE, wcX, wcZ); + board.getObjective(HUD_OBJECTIVE).setDisplayName(boardTitle); - TownyWorld world = wc.getTownyWorld(); - World bukkitWorld = player.getWorld(); - if (world == null || !world.isUsingTowny()) { - HUDManager.toggleOff(player); - return; - } - - Resident resident = TownyAPI.getInstance().getResident(player.getName()); - - int halfLineWidth = lineWidth/2; - int halfLineHeight = lineHeight/2; - + // Populate our map into an array. String[][] map = new String[lineWidth][lineHeight]; + fillMapArray(wcX, wcZ, TownyAPI.getInstance().getResident(player.getName()), player.getWorld(), map); + + // Write out the map to the board. + writeMapToBoard(board, map); + + TownBlock tb = wc.getTownBlockOrNull(); + board.getTeam(TEAM_TOWN).setSuffix(GREEN + (tb != null && tb.hasTown() ? tb.getTownOrNull().getName() : Translatable.of("status_no_town").forLocale(player))); + board.getTeam(TEAM_OWNER).setSuffix(GREEN + (tb != null && tb.hasResident() ? tb.getResidentOrNull().getName() : Translatable.of("status_no_town").forLocale(player))); + } + + private static void fillMapArray(int wcX, int wcZ, Resident resident, World bukkitWorld, String[][] map) { int x, y = 0; - for (int tby = wc.getX() + (lineWidth - halfLineWidth - 1); tby >= wc.getX() - halfLineWidth; tby--) { + for (int tby = wcX + (lineWidth - halfLineWidth - 1); tby >= wcX - halfLineWidth; tby--) { x = 0; - for (int tbx = wc.getZ() - halfLineHeight; tbx <= wc.getZ() + (lineHeight - halfLineHeight - 1); tbx++) { - map[y][x] = Colors.White; + for (int tbx = wcZ - halfLineHeight; tbx <= wcZ + (lineHeight - halfLineHeight - 1); tbx++) { final WorldCoord worldCoord = new WorldCoord(bukkitWorld, tby, tbx); - final TownBlock townBlock = worldCoord.getTownBlockOrNull(); - - if (townBlock != null) { - Town town = townBlock.getTownOrNull(); - if (x == halfLineHeight && y == halfLineWidth) - // This is the player's location, colour it special. - map[y][x] = Colors.Gold; - else if (townBlock.hasResident(resident)) - //own plot - map[y][x] = Colors.Yellow; - else if (resident.hasTown()) - if (town.hasResident(resident)) { - // own town - map[y][x] = Colors.LightGreen; - } else if (resident.hasNation()) { - Nation resNation = resident.getNationOrNull(); - if (resNation.hasTown(town)) - // own nation - map[y][x] = Colors.Green; - else if (town.hasNation()) { - Nation townBlockNation = town.getNationOrNull(); - if (resNation.hasAlly(townBlockNation)) - map[y][x] = Colors.Green; - else if (resNation.hasEnemy(townBlockNation)) - map[y][x] = Colors.Red; - } - } - - // If this is not where the player is currently locationed, - // set the colour of the townblocktype if it has one. - if (!(x == halfLineHeight && y == halfLineWidth) && townBlock.getData().hasColour()) - map[y][x] = map[y][x] = Colors.getLegacyFromNamedTextColor(townBlock.getData().getColour()); - - // Registered town block - if (townBlock.getPlotPrice() != -1 || townBlock.hasPlotObjectGroup() && townBlock.getPlotObjectGroup().getPrice() != -1) { - map[y][x] += TownyAsciiMap.forSaleSymbol; - } else if (townBlock.isHomeBlock()) - map[y][x] += TownyAsciiMap.homeSymbol; - else if (townBlock.isOutpost()) - map[y][x] += TownyAsciiMap.outpostSymbol; - else - map[y][x] += townBlock.getType().getAsciiMapKey(); - } else { - // Unregistered town block - - if (x == halfLineHeight && y == halfLineWidth) - map[y][x] = Colors.Gold; - else - map[y][x] = Colors.Gray; - - String symbol; - // Cached TownyMapData is present and not old. - final TownyMapData data = getWildernessMapDataMap().get(worldCoord); - - if (data != null && !data.isOld()) { - TownyMapData mapData = getWildernessMapDataMap().get(worldCoord); - symbol = mapData.getSymbol(); - // Cached TownyMapData is either not present or was considered old. - } else { - WildernessMapEvent wildMapEvent = new WildernessMapEvent(worldCoord); - BukkitTools.fireEvent(wildMapEvent); - symbol = wildMapEvent.getMapSymbol(); - getWildernessMapDataMap().put(worldCoord, new TownyMapData(worldCoord, symbol, wildMapEvent.getHoverText(), wildMapEvent.getClickCommand())); - - Towny.getPlugin().getScheduler().runAsyncLater(() -> { - getWildernessMapDataMap().computeIfPresent(worldCoord, (key, cachedData) -> cachedData.isOld() ? null : cachedData); - }, 20 * 35); - } - - /* - * We are only using symbol here but we have generated hovertext and clickcommands because the same - * TownyMapData cache is used for the ascii map seen in the /towny map commands. We would not want - * to fill only a part of that cache. - */ - map[y][x] += symbol; - } + if (worldCoord.hasTownBlock()) + mapTownBlock(resident, map, x, y, worldCoord.getTownBlockOrNull()); + else + mapWilderness(map, x, y, worldCoord); x++; } y++; } + } + + private static void mapTownBlock(Resident resident, String[][] map, int x, int y, final TownBlock townBlock) { + // Set the townblock colour. + map[y][x] = getTownBlockColour(resident, x, y, townBlock); + + // Set the townblock symbol. + if (isForSale(townBlock)) + map[y][x] += TownyAsciiMap.forSaleSymbol; + else if (townBlock.isHomeBlock()) + map[y][x] += TownyAsciiMap.homeSymbol; + else if (townBlock.isOutpost()) + map[y][x] += TownyAsciiMap.outpostSymbol; + else + map[y][x] += townBlock.getType().getAsciiMapKey(); + } + + private static String getTownBlockColour(Resident resident, int x, int y, final TownBlock townBlock) { + if (playerLocatedAtThisCoord(x, y)) + // This is the player's location, colour it special. + return Colors.Gold; + else if (townBlock.hasResident(resident)) + // Resident's own plot + return Colors.Yellow; + else if (townBlock.getData().hasColour()) + // Set the colour of the townblocktype if it has one. + return Colors.getLegacyFromNamedTextColor(townBlock.getData().getColour()); + else if (resident.hasTown()) + // The townblock could have a variety of colours. + return getTownBlockColour(resident, townBlock.getTownOrNull()); + else + // Default fallback. + return Colors.White; + } + + private static String getTownBlockColour(Resident resident, Town townAtTownBlock) { + // The player is a part of this town. + if (townAtTownBlock.hasResident(resident)) + return Colors.LightGreen; + + if (!resident.hasNation()) + return Colors.White; + + Nation resNation = resident.getNationOrNull(); + // Another town in the player's nation. + if (resNation.hasTown(townAtTownBlock)) + return Colors.Green; + + if (!townAtTownBlock.hasNation()) + return Colors.White; + + Nation townBlockNation = townAtTownBlock.getNationOrNull(); + if (resNation.hasAlly(townBlockNation)) + return Colors.Green; + else if (resNation.hasEnemy(townBlockNation)) + return Colors.Red; + else + return Colors.White; + } + + private static boolean playerLocatedAtThisCoord(int x, int y) { + return x == halfLineHeight && y == halfLineWidth; + } + + private static boolean isForSale(final TownBlock townBlock) { + return townBlock.getPlotPrice() != -1 || townBlock.hasPlotObjectGroup() && townBlock.getPlotObjectGroup().getPrice() != -1; + } + + + private static void mapWilderness(String[][] map, int x, int y, final WorldCoord worldCoord) { + // Colour gold if this is the player loc, otherwise normal gray. + map[y][x] = playerLocatedAtThisCoord(x, y) ? Colors.Gold : Colors.Gray; + + String symbol; + // Cached TownyMapData is present and not old. + final TownyMapData data = getWildernessMapDataMap().get(worldCoord); + if (data != null && !data.isOld()) { + TownyMapData mapData = getWildernessMapDataMap().get(worldCoord); + symbol = mapData.getSymbol(); + // Cached TownyMapData is either not present or was considered old. + } else { + WildernessMapEvent wildMapEvent = new WildernessMapEvent(worldCoord); + BukkitTools.fireEvent(wildMapEvent); + symbol = wildMapEvent.getMapSymbol(); + getWildernessMapDataMap().put(worldCoord, new TownyMapData(worldCoord, symbol, wildMapEvent.getHoverText(), wildMapEvent.getClickCommand())); + + Towny.getPlugin().getScheduler().runAsyncLater(() -> { + getWildernessMapDataMap().computeIfPresent(worldCoord, (key, cachedData) -> cachedData.isOld() ? null : cachedData); + }, 20 * 35); + } + + /* + * We are only using symbol here but we have generated hovertext and clickcommands because the same + * TownyMapData cache is used for the ascii map seen in the /towny map commands. We would not want + * to fill only a part of that cache. + */ + map[y][x] += symbol; + } + + private static Map getWildernessMapDataMap() { + return TownyUniverse.getInstance().getWildernessMapDataMap(); + } + + private static void writeMapToBoard(Scoreboard board, String[][] map) { for (int my = 0; my < lineHeight; my++) { String line = ""; for (int mx = lineWidth - 1; mx >= 0; mx--) line += map[mx][my]; - board.getTeam("mapTeam" + my).setSuffix(line); + board.getTeam(TEAM_MAP_PREFIX + my).setSuffix(line); } - - TownBlock tb = wc.getTownBlockOrNull(); - board.getTeam("townTeam").setSuffix(ChatColor.GREEN + (tb != null && tb.hasTown() ? tb.getTownOrNull().getName() : Translatable.of("status_no_town").forLocale(player))); - board.getTeam("ownerTeam").setSuffix(ChatColor.GREEN + (tb != null && tb.hasResident() ? tb.getResidentOrNull().getName() : Translatable.of("status_no_town").forLocale(player))); } - private static Map getWildernessMapDataMap() { - return TownyUniverse.getInstance().getWildernessMapDataMap(); - } } diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index 80fa973f4f..6543a422d4 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9447,4 +9447,5 @@ v0.92.0.11: - When true players cannot become hungrier when in their own or an allied town. - Refactor the TownCommand's town kicking method, and decouple the admin version of town kicking. 0.100.1.2: - - Fix non-mayors being able to add non-kickable-ranked residents as outlaws, which would have allowed them to be kicked. \ No newline at end of file + - Fix non-mayors being able to add non-kickable-ranked residents as outlaws, which would have allowed them to be kicked. + - Refactor MapHUD class. \ No newline at end of file From d189e93b4519919478e55e65e1ad9a66b971d89c Mon Sep 17 00:00:00 2001 From: LlmDl Date: Fri, 12 Jan 2024 15:11:07 -0600 Subject: [PATCH 61/74] - Refactor onEntityChangeBlockEvent method. --- .../towny/listeners/TownyEntityListener.java | 80 +++++++++---------- Towny/src/main/resources/ChangeLog.txt | 3 +- 2 files changed, 40 insertions(+), 43 deletions(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyEntityListener.java b/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyEntityListener.java index c91c45b79c..9c00cd4f50 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyEntityListener.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyEntityListener.java @@ -470,14 +470,18 @@ public void onEntityInteract(EntityInteractEvent event) { } /** - * Handles: + * Handles: * Enderman thieving protected blocks. * Ravagers breaking protected blocks. * Withers blowing up protected blocks. * Water being used to put out campfires. + * Boats breaking lilypads. * Crop Trampling. * - * @param event - onEntityChangeBlockEvent + * Because we use ignoreCancelled = true we dont need to worry about setting the + * cancelled state to false overriding other plugins. + * + * @param event onEntityChangeBlockEvent */ @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) public void onEntityChangeBlockEvent(EntityChangeBlockEvent event) { @@ -486,59 +490,51 @@ public void onEntityChangeBlockEvent(EntityChangeBlockEvent event) { return; } - TownyWorld townyWorld = TownyAPI.getInstance().getTownyWorld(event.getBlock().getWorld()); - + final Block block = event.getBlock(); + final TownyWorld townyWorld = TownyAPI.getInstance().getTownyWorld(block.getWorld()); if (townyWorld == null || !townyWorld.isUsingTowny()) return; - + final Material blockMat = block.getType(); + final Entity entity = event.getEntity(); + final EntityType entityType = event.getEntityType(); + // Crop trampling protection done here. - if (event.getBlock().getType().equals(Material.FARMLAND)) { - // Handle creature trampling crops if disabled in the world. - if (!event.getEntityType().equals(EntityType.PLAYER) && townyWorld.isDisableCreatureTrample()) { - event.setCancelled(true); - return; - } - // Handle player trampling crops if disabled in the world. - if (event.getEntity() instanceof Player player) { - event.setCancelled(TownySettings.isPlayerCropTramplePrevented() || !TownyActionEventExecutor.canDestroy(player, event.getBlock().getLocation(), Material.FARMLAND)); - return; - } + if (blockMat.equals(Material.FARMLAND)) { + if (entity instanceof Player player) // Handle player trampling crops if disabled in the world. + event.setCancelled(TownySettings.isPlayerCropTramplePrevented() || !TownyActionEventExecutor.canDestroy(player, block)); + else // Handle creature trampling crops if disabled in the world. + event.setCancelled(townyWorld.isDisableCreatureTrample()); + return; } - final EntityType type = event.getEntityType(); - - if (type == EntityType.ENDERMAN) { - if (townyWorld.isEndermanProtect()) - event.setCancelled(true); - } else if (EntityLists.BOATS.contains(type)) { - /* Protect lily pads. */ - if (!event.getBlock().getType().equals(Material.LILY_PAD)) - return; + // Test other instances of Entities altering blocks. + if (entityType == EntityType.ENDERMAN) { + event.setCancelled(townyWorld.isEndermanProtect()); + + } else if (entityType == EntityType.RAVAGER) { + event.setCancelled(townyWorld.isDisableCreatureTrample()); - final List passengers = event.getEntity().getPassengers(); + } else if (entityType == EntityType.WITHER) { + List allowed = TownyActionEventExecutor.filterExplodableBlocks(Collections.singletonList(block), blockMat, entity, event); + event.setCancelled(allowed.isEmpty()); + } else if (EntityLists.BOATS.contains(entityType) && blockMat.equals(Material.LILY_PAD)) { + // Protect lily pads. + final List passengers = entity.getPassengers(); if (!passengers.isEmpty() && passengers.get(0) instanceof Player player) - // Test if the player can break here. - event.setCancelled(!TownyActionEventExecutor.canDestroy(player, event.getBlock())); - else if (!TownyAPI.getInstance().isWilderness(event.getBlock())) + // Test if the player driving the boat can break here. + event.setCancelled(!TownyActionEventExecutor.canDestroy(player, block)); + else // Protect townland from non-player-ridden boats. (Maybe someone is pushing a boat?) - event.setCancelled(true); - } else if (type == EntityType.RAVAGER) { - if (townyWorld.isDisableCreatureTrample()) - event.setCancelled(true); - } else if (type == EntityType.WITHER) { - List allowed = TownyActionEventExecutor.filterExplodableBlocks(Collections.singletonList(event.getBlock()), event.getBlock().getType(), event.getEntity(), event); - event.setCancelled(allowed.isEmpty()); - } else if (event.getEntity() instanceof ThrownPotion potion) { - // Check that the affected block is a campfire and that a water bottle (no effects) was used. - if (event.getBlock().getType() != Material.CAMPFIRE || !potion.getEffects().isEmpty()) - return; + event.setCancelled(!TownyAPI.getInstance().isWilderness(block)); + } else if (entity instanceof ThrownPotion potion && potion.getEffects().isEmpty() && ItemLists.CAMPFIRES.contains(blockMat)) { + // Protect campfires from being extinguished by plain Water Bottles (which are potions with no effects.) if (potion.getShooter() instanceof BlockProjectileSource bps) - event.setCancelled(!BorderUtil.allowedMove(bps.getBlock(), event.getBlock())); + event.setCancelled(!BorderUtil.allowedMove(bps.getBlock(), block)); else if (potion.getShooter() instanceof Player player) - event.setCancelled(!TownyActionEventExecutor.canDestroy(player, event.getBlock().getLocation(), Material.CAMPFIRE)); + event.setCancelled(!TownyActionEventExecutor.canDestroy(player, block)); } } diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index 6543a422d4..83620c48fe 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9448,4 +9448,5 @@ v0.92.0.11: - Refactor the TownCommand's town kicking method, and decouple the admin version of town kicking. 0.100.1.2: - Fix non-mayors being able to add non-kickable-ranked residents as outlaws, which would have allowed them to be kicked. - - Refactor MapHUD class. \ No newline at end of file + - Refactor MapHUD class. + - Refactor onEntityChangeBlockEvent method. \ No newline at end of file From f17b801bc9a97aefbf6043a62b5d8257a1228e1d Mon Sep 17 00:00:00 2001 From: LlmDl Date: Sun, 14 Jan 2024 08:09:43 -0600 Subject: [PATCH 62/74] Increase granularity of the getUUIDPercent() method. --- .../main/java/com/palmergames/bukkit/towny/TownySettings.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/TownySettings.java b/Towny/src/main/java/com/palmergames/bukkit/towny/TownySettings.java index 470676a1ef..7a639e4554 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/TownySettings.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/TownySettings.java @@ -3377,6 +3377,10 @@ public static String getUUIDPercent() { if (fraction == 1.00) return "100%"; + if (fraction > 0.98) + return "99%"; + if (fraction > 0.95) + return "95%+"; if (fraction > 0.89) return "90%+"; if (fraction > 0.79) From 37fb72d64ccc7a8a7cc56987dd3a6d562efdb559 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Mon, 15 Jan 2024 10:08:39 -0600 Subject: [PATCH 63/74] - Fix returning null in the relational placeholder code, returning the no-relation colour instead. --- .../bukkit/towny/hooks/TownyPlaceholderExpansion.java | 4 ++-- Towny/src/main/resources/ChangeLog.txt | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/hooks/TownyPlaceholderExpansion.java b/Towny/src/main/java/com/palmergames/bukkit/towny/hooks/TownyPlaceholderExpansion.java index 99ba37d6cf..0fa64a7c81 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/hooks/TownyPlaceholderExpansion.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/hooks/TownyPlaceholderExpansion.java @@ -123,12 +123,12 @@ public String onPlaceholderRequest(Player player, Player player2, String identif private String getRelationalPlaceholder(Player player, Player player2, String identifier) { if (!identifier.equalsIgnoreCase("color")) - return null; + return TownySettings.getPAPIRelationNone(); Resident res = TownyUniverse.getInstance().getResident(player.getUniqueId()); Resident res2 = TownyUniverse.getInstance().getResident(player2.getUniqueId()); if (res == null || res2 == null) - return null; + return TownySettings.getPAPIRelationNone(); if (!res2.hasTown()) return TownySettings.getPAPIRelationNoTown(); diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index 83620c48fe..f3eb725a02 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9449,4 +9449,5 @@ v0.92.0.11: 0.100.1.2: - Fix non-mayors being able to add non-kickable-ranked residents as outlaws, which would have allowed them to be kicked. - Refactor MapHUD class. - - Refactor onEntityChangeBlockEvent method. \ No newline at end of file + - Refactor onEntityChangeBlockEvent method. + - Fix returning null in the relational placeholder code, returning the no-relation colour instead. \ No newline at end of file From eabbc6e042cf7eba48a67ab5473bd8edac7cf71f Mon Sep 17 00:00:00 2001 From: LlmDl Date: Mon, 15 Jan 2024 11:10:25 -0600 Subject: [PATCH 64/74] - Refactor some of TownyFormatter's methods, mainly moving some component-creation out into their related Util classes. - Add NationUtil. --- .../bukkit/towny/TownyFormatter.java | 144 +++--------------- .../bukkit/towny/utils/MoneyUtil.java | 84 +++++++++- .../bukkit/towny/utils/NationUtil.java | 59 +++++++ .../bukkit/towny/utils/OutpostUtil.java | 22 +++ .../bukkit/towny/utils/TownRuinUtil.java | 13 ++ Towny/src/main/resources/ChangeLog.txt | 4 +- 6 files changed, 200 insertions(+), 126 deletions(-) create mode 100644 Towny/src/main/java/com/palmergames/bukkit/towny/utils/NationUtil.java diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/TownyFormatter.java b/Towny/src/main/java/com/palmergames/bukkit/towny/TownyFormatter.java index 5e4e787eaf..c394fa42ee 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/TownyFormatter.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/TownyFormatter.java @@ -25,6 +25,8 @@ import com.palmergames.bukkit.towny.permissions.TownyPerms; import com.palmergames.bukkit.towny.utils.CombatUtil; import com.palmergames.bukkit.towny.utils.MoneyUtil; +import com.palmergames.bukkit.towny.utils.NationUtil; +import com.palmergames.bukkit.towny.utils.OutpostUtil; import com.palmergames.bukkit.towny.utils.ResidentUtil; import com.palmergames.bukkit.towny.utils.TownRuinUtil; import com.palmergames.bukkit.towny.utils.TownyComponents; @@ -40,8 +42,6 @@ import org.bukkit.command.CommandSender; import org.bukkit.command.ConsoleCommandSender; import org.bukkit.entity.Player; -import java.math.BigDecimal; -import java.math.RoundingMode; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; @@ -300,10 +300,10 @@ public static StatusScreen getStatus(Town town, CommandSender sender) { screen.addComponentOf("townblocks", colourKeyValue(translator.of("status_town_size"), translator.of("status_fractions", town.getTownBlocks().size(), town.getMaxTownBlocksAsAString()))); if (town.isPublic()) { - Component homeComponent = TownyComponents.miniMessage(!town.isPublic() ? "" : (translator.of("status_home_element", (TownySettings.getTownDisplaysXYZ() ? - (town.hasSpawn() ? BukkitTools.convertCoordtoXYZ(town.getSpawnOrNull()) : translator.of("status_no_town")) : - (town.hasHomeBlock() ? town.getHomeBlockOrNull().getCoord().toString() : translator.of("status_no_town")) - )))); + Component homeComponent = TownyComponents.miniMessage(translator.of("status_home_element", TownySettings.getTownDisplaysXYZ() + ? (town.hasSpawn() ? BukkitTools.convertCoordtoXYZ(town.getSpawnOrNull()) : translator.of("status_no_town")) + : (town.hasHomeBlock() ? town.getHomeBlockOrNull().getCoord().toString() : translator.of("status_no_town")) + )); String webUrl = formatWebUrl(town); if (!webUrl.isEmpty()) @@ -313,22 +313,8 @@ public static StatusScreen getStatus(Town town, CommandSender sender) { } // Outposts: 3 - if (TownySettings.isAllowingOutposts()) { - String outpostLine = ""; - if (TownySettings.isOutpostsLimitedByLevels()) { - outpostLine = colourKeyValue(translator.of("status_town_outposts"), translator.of("status_fractions", town.getMaxOutpostSpawn(), town.getOutpostLimit())); - if (town.hasNation()) { - int nationBonus = town.getNationOrNull().getNationLevel().nationBonusOutpostLimit(); - if (nationBonus > 0) - outpostLine += colourBracketElement(translator.of("status_town_size_nationbonus"), String.valueOf(nationBonus)); - } - } else if (town.hasOutpostSpawn()) { - outpostLine = colourKeyValue(translator.of("status_town_outposts"), String.valueOf(town.getMaxOutpostSpawn())); - } - screen.addComponentOf("outposts", outpostLine, - HoverEvent.showText(translator.component("status_hover_click_for_more")), - ClickEvent.runCommand("/towny:town outpost list")); - } + if (TownySettings.isAllowingOutposts()) + OutpostUtil.addOutpostComponent(town, screen, translator); // Permissions: B=rnao D=---- S=rna- I=rnao screen.addComponentOf("perm", colourKeyValue(translator.of("status_perm"), town.getPermissions().getColourString().replace("f", "r"))); @@ -337,18 +323,13 @@ public static StatusScreen getStatus(Town town, CommandSender sender) { screen.addComponentOf("mobspawns", colourKeyValue(translator.of("mobspawns"), (town.hasMobs() || town.isAdminEnabledMobs() || world.isForceTownMobs()) ? translator.of("status_on"): translator.of("status_off"))); if (TownySettings.getTownRuinsEnabled() && town.isRuined()) { - screen.addComponentOf("ruinedTime", colourKey(translator.of("msg_time_remaining_before_full_removal", TownySettings.getTownRuinsMaxDurationHours() - TownRuinUtil.getTimeSinceRuining(town)))); - if (TownySettings.getTownRuinsReclaimEnabled()) { - if (TownRuinUtil.getTimeSinceRuining(town) < TownySettings.getTownRuinsMinDurationHours()) - screen.addComponentOf("reclaim", colourKeyImportant(translator.of("msg_time_until_reclaim_available", TownySettings.getTownRuinsMinDurationHours() - TownRuinUtil.getTimeSinceRuining(town)))); - else - screen.addComponentOf("reclaim", colourKeyImportant(translator.of("msg_reclaim_available"))); - } - // Only display the remaining fields if town is not ruined + TownRuinUtil.addRuinedComponents(town, screen, translator); + + // Only display the remaining fields if town is not ruined } else { // | Bank: 534 coins if (TownyEconomyHandler.isActive()) - addTownMoneyComponents(town, translator, screen); + MoneyUtil.addTownMoneyComponents(town, translator, screen); // Mayor: MrSand if (town.getMayor() != null) { @@ -362,35 +343,11 @@ public static StatusScreen getStatus(Town town, CommandSender sender) { screen.addComponentOf("mayor", colourKeyValue(translator.of("rank_list_mayor"), translator.of("status_no_town"))); // Nation: Azur Empire - if (town.hasNation()) { - // Shown in Hover Text: Towns [44]: James City, Carry Grove, Mason Town - List towns = getFormattedNames(town.getNationOrNull().getTowns()); - if (towns.size() > 10) - shortenOverLengthList(towns, 11, translator); + if (town.hasNation()) + NationUtil.addNationComponenents(town, screen, translator); - Component hover = TownyComponents.miniMessage(Colors.translateColorCodes(String.format(TownySettings.getPAPIFormattingNation(), town.getNationOrNull().getFormattedName()))) - .append(Component.newline()) - .append(TownyComponents.miniMessage(getTownJoinedNationDate(town, translator))) - .append(Component.newline()) - .append(TownyComponents.miniMessage(colourKeyValue(translator.of("status_nation_king"), town.getNationOrNull().getCapital().getMayor().getFormattedName()))) - .append(Component.newline()) - .append(TownyComponents.miniMessage(colourKeyValue(translator.of("town_plu"), StringMgmt.join(towns, ", ")))); - - int nationZoneSize = town.getNationZoneSize(); - if (nationZoneSize > 0) - hover = hover.append(Component.newline().append(TownyComponents.miniMessage(colourKeyValue(translator.of("status_nation_zone_size"), town.isNationZoneEnabled() ? String.valueOf(nationZoneSize) : translator.of("status_off_bad"))))); - - hover = hover.append(Component.newline()) - .append(translator.component("status_hover_click_for_more")); - - screen.addComponentOf("nation", colourKeyValue(translator.of("status_town_nation"), town.getNationOrNull().getName() + formatPopulationBrackets(town.getNationOrNull().getTowns().size())), - hover.asHoverEvent(), - ClickEvent.runCommand("/towny:nation " + town.getNationOrNull().getName()) - ); - } - screen.addComponentOf("newline", Component.newline()); - // Assistants [2]: Sammy, Ginger + // [Rank List] with hover including ranks and their residents. List ranklist = getRanks(town, translator); if (ranklist.size() > 0) screen.addComponentOf("townranks", colourHoverKey(translator.of("status_rank_list")), @@ -399,7 +356,7 @@ public static StatusScreen getStatus(Town town, CommandSender sender) { .append(translator.component("status_hover_click_for_more"))), ClickEvent.runCommand("/towny:town ranklist " + town.getName())); - // Residents [3]: James, Carry, Mason + // [Residents] with hover showing residents names. List residents = getFormattedNames(town.getResidents()); if (residents.size() > 34) shortenOverLengthList(residents, 35, translator); @@ -410,7 +367,7 @@ public static StatusScreen getStatus(Town town, CommandSender sender) { .append(translator.component("status_hover_click_for_more"))), ClickEvent.runCommand("/towny:town reslist "+ town.getName())); - // Plots + // [Plots] with hover. TextComponent text = Component.empty(); Map cache = town.getTownBlockTypeCache().getCache(TownBlockTypeCache.CacheType.ALL); for (TownBlockType type : TownBlockTypeHandler.getTypes().values()) { @@ -462,7 +419,7 @@ public static StatusScreen getStatus(Nation nation, CommandSender sender) { // Bank: 534 coins if (TownyEconomyHandler.isActive()) - addNationMoneyComponentsToScreen(nation, translator, screen); + MoneyUtil.addNationMoneyComponentsToScreen(nation, translator, screen); if (nation.isPublic()) { Component homeComponent = translator.component("status_home_element", (nation.hasSpawn() ? Coord.parseCoord(nation.getSpawnOrNull()).toString() : translator.of("status_no_town"))); @@ -675,11 +632,7 @@ private static String getResidentLastOnline(Resident resident, Translator transl private static String getResidentJoinedTownDate(Resident resident, Translator translator) { return colourKeyValue(translator.of("status_joined_town"), resident.getJoinedTownAt() > 0 ? lastOnlineFormatIncludeYear.format(resident.getJoinedTownAt()) : translator.of("status_unknown")); } - - private static String getTownJoinedNationDate(Town town, Translator translator) { - return colourKeyValue(translator.of("status_joined_nation"), town.getJoinedNationAt() > 0 ? lastOnlineFormatIncludeYear.format(town.getJoinedNationAt()) : translator.of("status_unknown")); - } - + private static boolean sameYear(Resident resident) { Calendar cal = Calendar.getInstance(); cal.setTimeInMillis(resident.getLastOnline()); @@ -755,68 +708,11 @@ private static String[] shortenOverlengthArray(String[] array, int i, Translator return array; } - private static void shortenOverLengthList(List list, int i, Translator translator) { + public static void shortenOverLengthList(List list, int i, Translator translator) { list.subList(Math.min(i, list.size() - 1), list.size() - 1).clear(); list.add(translator.of("status_town_reslist_overlength")); } - /** - * Populates the StatusScreen with the various bank and money components. - * @param town Town of which to generate a bankstring. - * @param translator Translator used in choosing language. - * @param screen StatusScreen to add components to. - */ - private static void addTownMoneyComponents(Town town, Translator translator, StatusScreen screen) { - screen.addComponentOf("moneynewline", Component.newline()); - screen.addComponentOf("bankString", colourKeyValue(translator.of("status_bank"), town.getAccount().getHoldingFormattedBalance())); - if (town.isBankrupt()) { - if (town.getAccount().getDebtCap() == 0) - town.getAccount().setDebtCap(MoneyUtil.getTownDebtCap(town, TownySettings.getTownUpkeepCost(town))); - - screen.addComponentOf("bankrupt", translator.of("status_bank_bankrupt") + " " + colourKeyValue(translator.of("status_debtcap"), "-" + formatMoney(town.getAccount().getDebtCap()))); - } - - if (TownySettings.isTaxingDaily()) { - if (town.hasUpkeep()) - screen.addComponentOf("upkeep", translator.of("status_splitter") + colourKey(translator.of("status_bank_town2")) + " " + colourKeyImportant(formatMoney(BigDecimal.valueOf(TownySettings.getTownUpkeepCost(town)).setScale(2, RoundingMode.HALF_UP).doubleValue()))); - - if (TownySettings.getUpkeepPenalty() > 0 && town.isOverClaimed()) - screen.addComponentOf("upkeepPenalty", translator.of("status_splitter") + colourKey(translator.of("status_bank_town_penalty_upkeep")) + " " + colourKeyImportant(formatMoney(TownySettings.getTownPenaltyUpkeepCost(town)))); - - if (town.isNeutral()) { - double neutralCost = TownySettings.getTownNeutralityCost(town); - if (neutralCost > 0) - screen.addComponentOf("neutralityCost", translator.of("status_splitter") + colourKey(translator.of("status_neutrality_cost") + " " + colourKeyImportant(formatMoney(neutralCost)))); - } - - screen.addComponentOf("towntax", translator.of("status_splitter") + colourKey(translator.of("status_bank_town3")) + " " + colourKeyImportant(town.isTaxPercentage() ? town.getTaxes() + "%" : formatMoney(town.getTaxes()))); - } - } - - /** - * Populates the StatusScreen with the various bank and money components. - * @param nation Nation of which to generate a bankstring. - * @param translator Translator used in choosing language. - * @param screen StatusScreen to add components to. - */ - private static void addNationMoneyComponentsToScreen(Nation nation, Translator translator, StatusScreen screen) { - screen.addComponentOf("moneynewline", Component.newline()); - screen.addComponentOf("bankString", colourKeyValue(translator.of("status_bank"), nation.getAccount().getHoldingFormattedBalance())); - - if (TownySettings.isTaxingDaily()) { - if (TownySettings.getNationUpkeepCost(nation) > 0) - screen.addComponentOf("nationupkeep", translator.of("status_splitter") + colourKey(translator.of("status_bank_town2") + " " + colourKeyImportant(formatMoney(TownySettings.getNationUpkeepCost(nation))))); - if (nation.isNeutral()) { - double neutralCost = TownySettings.getNationNeutralityCost(nation); - if (neutralCost > 0) - screen.addComponentOf("neutralityCost", translator.of("status_splitter") + colourKey(translator.of("status_neutrality_cost") + " " + colourKeyImportant(formatMoney(neutralCost)))); - } - - screen.addComponentOf("nationtax", translator.of("status_splitter") + colourKey(translator.of("status_nation_tax")) + " " + colourKeyImportant(nation.isTaxPercentage() ? nation.getTaxes() + "%" : formatMoney(nation.getTaxes()))); - screen.addComponentOf("nationConqueredTax", translator.of("status_splitter") + colourKey(translator.of("status_nation_conquered_tax")) + " " + colourKeyImportant(formatMoney(nation.getConqueredTax()))); - } - } - private static String formatMoney(double money) { return TownyEconomyHandler.getFormattedBalance(money); } diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/MoneyUtil.java b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/MoneyUtil.java index c26bc4aaa9..ca17d9a8d8 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/MoneyUtil.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/MoneyUtil.java @@ -1,14 +1,19 @@ package com.palmergames.bukkit.towny.utils; import com.palmergames.bukkit.towny.object.Translatable; +import com.palmergames.bukkit.towny.object.Translator; import java.io.File; +import java.math.BigDecimal; +import java.math.RoundingMode; + import org.bukkit.Location; import org.bukkit.entity.Player; import com.palmergames.bukkit.towny.Towny; import com.palmergames.bukkit.towny.TownyAPI; import com.palmergames.bukkit.towny.TownyEconomyHandler; +import com.palmergames.bukkit.towny.TownyFormatter; import com.palmergames.bukkit.towny.TownyMessaging; import com.palmergames.bukkit.towny.TownySettings; import com.palmergames.bukkit.towny.TownyUniverse; @@ -23,10 +28,13 @@ import com.palmergames.bukkit.towny.object.TownBlock; import com.palmergames.bukkit.towny.object.TownBlockType; import com.palmergames.bukkit.towny.object.TownBlockTypeCache.CacheType; +import com.palmergames.bukkit.towny.object.statusscreens.StatusScreen; import com.palmergames.bukkit.towny.object.Transaction; import com.palmergames.bukkit.towny.object.TransactionType; import com.palmergames.bukkit.util.BukkitTools; +import net.kyori.adventure.text.Component; + public class MoneyUtil { public static double getTownDebtCap(Town town, double upkeep) { @@ -194,7 +202,7 @@ private static void commonTests(int amount, Resident resident, Town town, Locati else minAmount = nation ? TownySettings.getNationMinDeposit() : TownySettings.getTownMinDeposit(); if (amount < minAmount) - throw new TownyException(Translatable.of("msg_err_must_be_greater_than_or_equal_to", TownyEconomyHandler.getFormattedBalance(minAmount))); + throw new TownyException(Translatable.of("msg_err_must_be_greater_than_or_equal_to", formatMoney(minAmount))); } @@ -305,4 +313,78 @@ public static double returnPurchasedBlocksCost(int alreadyPurchased, int toPurch final double cost = blockCost * (1 - Math.pow(increaseValue, n)) / (1 - increaseValue); return Math.round(cost); } + + + /** + * Populates the StatusScreen with the various bank and money components. + * @param town Town of which to generate a bankstring. + * @param translator Translator used in choosing language. + * @param screen StatusScreen to add components to. + */ + public static void addTownMoneyComponents(Town town, Translator translator, StatusScreen screen) { + screen.addComponentOf("moneynewline", Component.newline()); + screen.addComponentOf("bankString", TownyFormatter.colourKeyValue(translator.of("status_bank"), town.getAccount().getHoldingFormattedBalance())); + if (town.isBankrupt()) { + if (town.getAccount().getDebtCap() == 0) + town.getAccount().setDebtCap(getTownDebtCap(town, TownySettings.getTownUpkeepCost(town))); + + screen.addComponentOf("bankrupt", translator.of("status_bank_bankrupt") + + " " + TownyFormatter.colourKeyValue(translator.of("status_debtcap"), "-" + formatMoney(town.getAccount().getDebtCap()))); + } + + if (!TownySettings.isTaxingDaily()) + return; + + if (town.hasUpkeep()) + screen.addComponentOf("upkeep", translator.of("status_splitter") + TownyFormatter.colourKey(translator.of("status_bank_town2")) + + " " + TownyFormatter.colourKeyImportant(formatMoney(BigDecimal.valueOf(TownySettings.getTownUpkeepCost(town)).setScale(2, RoundingMode.HALF_UP).doubleValue()))); + + if (TownySettings.getUpkeepPenalty() > 0 && town.isOverClaimed()) + screen.addComponentOf("upkeepPenalty", translator.of("status_splitter") + TownyFormatter.colourKey(translator.of("status_bank_town_penalty_upkeep")) + + " " + TownyFormatter.colourKeyImportant(formatMoney(TownySettings.getTownPenaltyUpkeepCost(town)))); + + if (town.isNeutral()) { + double neutralCost = TownySettings.getTownNeutralityCost(town); + if (neutralCost > 0) + screen.addComponentOf("neutralityCost", translator.of("status_splitter") + TownyFormatter.colourKey(translator.of("status_neutrality_cost") + + " " + TownyFormatter.colourKeyImportant(formatMoney(neutralCost)))); + } + + screen.addComponentOf("towntax", translator.of("status_splitter") + TownyFormatter.colourKey(translator.of("status_bank_town3")) + + " " + TownyFormatter.colourKeyImportant(town.isTaxPercentage() ? town.getTaxes() + "%" : formatMoney(town.getTaxes()))); + } + + /** + * Populates the StatusScreen with the various bank and money components. + * @param nation Nation of which to generate a bankstring. + * @param translator Translator used in choosing language. + * @param screen StatusScreen to add components to. + */ + public static void addNationMoneyComponentsToScreen(Nation nation, Translator translator, StatusScreen screen) { + screen.addComponentOf("moneynewline", Component.newline()); + screen.addComponentOf("bankString", TownyFormatter.colourKeyValue(translator.of("status_bank"), nation.getAccount().getHoldingFormattedBalance())); + + if (!TownySettings.isTaxingDaily()) + return; + + if (TownySettings.getNationUpkeepCost(nation) > 0) + screen.addComponentOf("nationupkeep", translator.of("status_splitter") + TownyFormatter.colourKey(translator.of("status_bank_town2") + + " " + TownyFormatter.colourKeyImportant(formatMoney(TownySettings.getNationUpkeepCost(nation))))); + if (nation.isNeutral()) { + double neutralCost = TownySettings.getNationNeutralityCost(nation); + if (neutralCost > 0) + screen.addComponentOf("neutralityCost", translator.of("status_splitter") + TownyFormatter.colourKey(translator.of("status_neutrality_cost") + + " " + TownyFormatter.colourKeyImportant(formatMoney(neutralCost)))); + } + + screen.addComponentOf("nationtax", translator.of("status_splitter") + TownyFormatter.colourKey(translator.of("status_nation_tax")) + + " " + TownyFormatter.colourKeyImportant(nation.isTaxPercentage() ? nation.getTaxes() + "%" : formatMoney(nation.getTaxes()))); + screen.addComponentOf("nationConqueredTax", translator.of("status_splitter") + TownyFormatter.colourKey(translator.of("status_nation_conquered_tax")) + + " " + TownyFormatter.colourKeyImportant(formatMoney(nation.getConqueredTax()))); + + } + + private static String formatMoney(double money) { + return TownyEconomyHandler.getFormattedBalance(money); + } } diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/NationUtil.java b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/NationUtil.java new file mode 100644 index 0000000000..a17b43b745 --- /dev/null +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/NationUtil.java @@ -0,0 +1,59 @@ +package com.palmergames.bukkit.towny.utils; + +import java.util.List; + +import com.palmergames.bukkit.towny.TownyFormatter; +import com.palmergames.bukkit.towny.TownySettings; +import com.palmergames.bukkit.towny.object.Nation; +import com.palmergames.bukkit.towny.object.Town; +import com.palmergames.bukkit.towny.object.Translator; +import com.palmergames.bukkit.towny.object.statusscreens.StatusScreen; +import com.palmergames.bukkit.util.Colors; +import com.palmergames.util.StringMgmt; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.ClickEvent; + +public class NationUtil { + + public static void addNationComponenents(Town town, StatusScreen screen, Translator translator) { + // Shown in Hover Text: Towns [44]: James City, Carry Grove, Mason Town + Nation nation = town.getNationOrNull(); + if (nation == null) + return; + + List towns = TownyFormatter.getFormattedNames(nation.getTowns()); + if (towns.size() > 10) + TownyFormatter.shortenOverLengthList(towns, 11, translator); + + Component hover = buildNationComponentHover(town, translator, nation, towns); + + screen.addComponentOf("nation", + TownyFormatter.colourKeyValue(translator.of("status_town_nation"), nation.getName() + TownyFormatter.formatPopulationBrackets(nation.getTowns().size())), + hover.asHoverEvent(), + ClickEvent.runCommand("/towny:nation " + nation.getName())); + } + + private static Component buildNationComponentHover(Town town, Translator translator, Nation nation, List towns) { + Component hover = TownyComponents.miniMessage(Colors.translateColorCodes(String.format(TownySettings.getPAPIFormattingNation(), nation.getFormattedName()))) + .append(Component.newline()) + .append(TownyComponents.miniMessage(getTownJoinedNationDate(town, translator))) + .append(Component.newline()) + .append(TownyComponents.miniMessage(TownyFormatter.colourKeyValue(translator.of("status_nation_king"), nation.getCapital().getMayor().getFormattedName()))) + .append(Component.newline()) + .append(TownyComponents.miniMessage(TownyFormatter.colourKeyValue(translator.of("town_plu"), StringMgmt.join(towns, ", ")))); + + int nationZoneSize = town.getNationZoneSize(); + if (nationZoneSize > 0) + hover = hover.append(Component.newline().append(TownyComponents.miniMessage( + TownyFormatter.colourKeyValue(translator.of("status_nation_zone_size"), town.isNationZoneEnabled() ? String.valueOf(nationZoneSize) : translator.of("status_off_bad"))))); + + hover = hover.append(Component.newline()).append(translator.component("status_hover_click_for_more")); + return hover; + } + + private static String getTownJoinedNationDate(Town town, Translator translator) { + return TownyFormatter.colourKeyValue(translator.of("status_joined_nation"), + town.getJoinedNationAt() > 0 ? TownyFormatter.lastOnlineFormatIncludeYear.format(town.getJoinedNationAt()) : translator.of("status_unknown")); + } +} diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/OutpostUtil.java b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/OutpostUtil.java index 9f1d7bb381..76deb82170 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/OutpostUtil.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/OutpostUtil.java @@ -1,6 +1,7 @@ package com.palmergames.bukkit.towny.utils; +import com.palmergames.bukkit.towny.TownyFormatter; import com.palmergames.bukkit.towny.TownySettings; import com.palmergames.bukkit.towny.exceptions.TownyException; import com.palmergames.bukkit.towny.object.Coord; @@ -8,6 +9,11 @@ import com.palmergames.bukkit.towny.object.Town; import com.palmergames.bukkit.towny.object.TownyWorld; import com.palmergames.bukkit.towny.object.Translatable; +import com.palmergames.bukkit.towny.object.Translator; +import com.palmergames.bukkit.towny.object.statusscreens.StatusScreen; + +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.event.HoverEvent; public class OutpostUtil { @@ -68,4 +74,20 @@ public static boolean OutpostTests(Town town, Resident resident, TownyWorld worl return true; } + public static void addOutpostComponent(Town town, StatusScreen screen, Translator translator) { + String outpostLine = ""; + if (TownySettings.isOutpostsLimitedByLevels()) { + outpostLine = TownyFormatter.colourKeyValue(translator.of("status_town_outposts"), translator.of("status_fractions", town.getMaxOutpostSpawn(), town.getOutpostLimit())); + if (town.hasNation()) { + int nationBonus = town.getNationOrNull().getNationLevel().nationBonusOutpostLimit(); + if (nationBonus > 0) + outpostLine += TownyFormatter.colourBracketElement(translator.of("status_town_size_nationbonus"), String.valueOf(nationBonus)); + } + } else if (town.hasOutpostSpawn()) { + outpostLine = TownyFormatter.colourKeyValue(translator.of("status_town_outposts"), String.valueOf(town.getMaxOutpostSpawn())); + } + screen.addComponentOf("outposts", outpostLine, + HoverEvent.showText(translator.component("status_hover_click_for_more")), + ClickEvent.runCommand("/towny:town outpost list")); + } } diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/TownRuinUtil.java b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/TownRuinUtil.java index 5cb5815111..99cdd1d2b7 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/TownRuinUtil.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/TownRuinUtil.java @@ -4,6 +4,7 @@ import com.palmergames.bukkit.towny.Towny; import com.palmergames.bukkit.towny.TownyAPI; import com.palmergames.bukkit.towny.TownyEconomyHandler; +import com.palmergames.bukkit.towny.TownyFormatter; import com.palmergames.bukkit.towny.TownyMessaging; import com.palmergames.bukkit.towny.TownySettings; import com.palmergames.bukkit.towny.TownyUniverse; @@ -21,6 +22,8 @@ import com.palmergames.bukkit.towny.object.TownBlock; import com.palmergames.bukkit.towny.object.TownBlockType; import com.palmergames.bukkit.towny.object.Translatable; +import com.palmergames.bukkit.towny.object.Translator; +import com.palmergames.bukkit.towny.object.statusscreens.StatusScreen; import com.palmergames.bukkit.util.BukkitTools; import com.palmergames.util.TimeTools; @@ -237,4 +240,14 @@ public static void evaluateRuinedTownRemovals() { public static int getTimeSinceRuining(Town town) { return TimeTools.getHours(System.currentTimeMillis() - town.getRuinedTime()); } + + public static void addRuinedComponents(Town town, StatusScreen screen, Translator translator) { + screen.addComponentOf("ruinedTime", TownyFormatter.colourKey(translator.of("msg_time_remaining_before_full_removal", TownySettings.getTownRuinsMaxDurationHours() - getTimeSinceRuining(town)))); + if (TownySettings.getTownRuinsReclaimEnabled()) { + if (TownRuinUtil.getTimeSinceRuining(town) < TownySettings.getTownRuinsMinDurationHours()) + screen.addComponentOf("reclaim", TownyFormatter.colourKeyImportant(translator.of("msg_time_until_reclaim_available", TownySettings.getTownRuinsMinDurationHours() - getTimeSinceRuining(town)))); + else + screen.addComponentOf("reclaim", TownyFormatter.colourKeyImportant(translator.of("msg_reclaim_available"))); + } + } } diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index f3eb725a02..e17b3bf84f 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9450,4 +9450,6 @@ v0.92.0.11: - Fix non-mayors being able to add non-kickable-ranked residents as outlaws, which would have allowed them to be kicked. - Refactor MapHUD class. - Refactor onEntityChangeBlockEvent method. - - Fix returning null in the relational placeholder code, returning the no-relation colour instead. \ No newline at end of file + - Fix returning null in the relational placeholder code, returning the no-relation colour instead. + - Refactor some of TownyFormatter's methods, mainly moving some component-creation out into their related Util classes. + - Add NationUtil. \ No newline at end of file From 16d1727873c27b8cf23c9866c208b5c82694c223 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Mon, 15 Jan 2024 12:59:35 -0600 Subject: [PATCH 65/74] - Move max allies test into NationUtil. --- .../com/palmergames/bukkit/towny/command/NationCommand.java | 2 +- .../main/java/com/palmergames/bukkit/towny/object/Nation.java | 4 ++++ .../java/com/palmergames/bukkit/towny/utils/NationUtil.java | 4 ++++ Towny/src/main/resources/ChangeLog.txt | 3 ++- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/command/NationCommand.java b/Towny/src/main/java/com/palmergames/bukkit/towny/command/NationCommand.java index 03bf4607c3..2096f164c5 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/command/NationCommand.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/command/NationCommand.java @@ -1650,7 +1650,7 @@ private void nationAllyAccept(Player player, Nation nation, String[] split) thro if (toAccept != null) { // Nation has reached the max amount of allies - if (TownySettings.getMaxNationAllies() >= 0 && nation.getAllies().size() >= TownySettings.getMaxNationAllies()) { + if (nation.hasReachedMaximumAllies()) { toAccept.getReceiver().deleteReceivedInvite(toAccept); toAccept.getSender().deleteSentInvite(toAccept); TownyMessaging.sendErrorMsg(player, Translatable.of("msg_err_ally_limit_reached")); diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/object/Nation.java b/Towny/src/main/java/com/palmergames/bukkit/towny/object/Nation.java index cdaf705950..3fa02dee3d 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/object/Nation.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/object/Nation.java @@ -17,6 +17,7 @@ import com.palmergames.bukkit.towny.object.SpawnPoint.SpawnPointType; import com.palmergames.bukkit.towny.object.metadata.CustomDataField; import com.palmergames.bukkit.towny.permissions.TownyPerms; +import com.palmergames.bukkit.towny.utils.NationUtil; import com.palmergames.bukkit.towny.utils.ProximityUtil; import com.palmergames.bukkit.towny.utils.TownyComponents; import com.palmergames.bukkit.util.BukkitTools; @@ -304,6 +305,9 @@ public List getAllies() { return allies; } + public boolean hasReachedMaximumAllies() { + return NationUtil.hasReachedMaximumAllies(this); + } public List getMutualAllies() { List result = new ArrayList<>(); for(Nation ally: getAllies()) { diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/NationUtil.java b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/NationUtil.java index a17b43b745..3030dbd5fa 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/NationUtil.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/NationUtil.java @@ -56,4 +56,8 @@ private static String getTownJoinedNationDate(Town town, Translator translator) return TownyFormatter.colourKeyValue(translator.of("status_joined_nation"), town.getJoinedNationAt() > 0 ? TownyFormatter.lastOnlineFormatIncludeYear.format(town.getJoinedNationAt()) : translator.of("status_unknown")); } + + public static boolean hasReachedMaximumAllies(Nation nation) { + return TownySettings.getMaxNationAllies() >= 0 && nation.getAllies().size() >= TownySettings.getMaxNationAllies(); + } } diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index e17b3bf84f..181ea6a02c 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9452,4 +9452,5 @@ v0.92.0.11: - Refactor onEntityChangeBlockEvent method. - Fix returning null in the relational placeholder code, returning the no-relation colour instead. - Refactor some of TownyFormatter's methods, mainly moving some component-creation out into their related Util classes. - - Add NationUtil. \ No newline at end of file + - Add NationUtil. + - Move max allies test into NationUtil. \ No newline at end of file From 02099afd2ad8075a2d92b15e49929e4152a1beca Mon Sep 17 00:00:00 2001 From: LlmDl Date: Mon, 15 Jan 2024 17:08:19 -0600 Subject: [PATCH 66/74] - Add more nation-joining tests to the NationUtil. - Refactor nation adding towns in the NationCommand class. --- .../bukkit/towny/command/NationCommand.java | 102 +++++++++--------- .../bukkit/towny/object/Nation.java | 14 +++ .../inviteobjects/TownJoinNationInvite.java | 11 +- .../bukkit/towny/utils/NationUtil.java | 18 ++++ Towny/src/main/resources/ChangeLog.txt | 4 +- Towny/src/main/resources/lang/en-US.yml | 2 + 6 files changed, 90 insertions(+), 61 deletions(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/command/NationCommand.java b/Towny/src/main/java/com/palmergames/bukkit/towny/command/NationCommand.java index 2096f164c5..ce9d9074f0 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/command/NationCommand.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/command/NationCommand.java @@ -696,10 +696,10 @@ private void parseNationJoin(Player player, String[] args) { if (!town.hasEnoughResidentsToJoinANation()) throw new TownyException(Translatable.of("msg_err_not_enough_residents_join_nation", town.getName())); - if (!testNationMaxTowns(nation)) + if (nation.hasReachedMaxTowns()) throw new TownyException(Translatable.of("msg_err_nation_over_town_limit", TownySettings.getMaxTownsPerNation())); - if (!testNationMaxResidents(nation, town)) + if (!nation.canAddResidents(town.getNumResidents())) throw new TownyException(Translatable.of("msg_err_cannot_join_nation_over_resident_limit", TownySettings.getMaxResidentsPerNation())); if (TownySettings.getNationProximityToCapital() > 0) @@ -708,9 +708,7 @@ private void parseNationJoin(Player player, String[] args) { // Check if the command is not cancelled BukkitTools.ifCancelledThenThrow(new NationPreAddTownEvent(nation, town)); - List towns = new ArrayList<>(); - towns.add(town); - nationAdd(nation, towns); + nationAdd(nation, town); } catch (TownyException e) { TownyMessaging.sendErrorMsg(player, e.getMessage(player)); @@ -1176,7 +1174,7 @@ public void nationAdd(Player player, String[] names) throws TownyException { Nation nation = getNationFromPlayerOrThrow(player); - if (!testNationMaxTowns(nation)) + if (nation.hasReachedMaxTowns()) throw new TownyException(Translatable.of("msg_err_nation_over_town_limit", TownySettings.getMaxTownsPerNation())); // The list of valid invites. @@ -1214,7 +1212,7 @@ public void nationAdd(Player player, String[] names) throws TownyException { continue; } - if (!testNationMaxResidents(nation, town)) { + if (!nation.canAddResidents(town.getNumResidents())) { // Town has too many residents to join the nation removeinvites.add(townname); TownyMessaging.sendErrorMsg(player, Translatable.of("msg_err_cannot_join_nation_over_resident_limit", TownySettings.getMaxResidentsPerNation(), townname)); @@ -1290,57 +1288,61 @@ public static void nationAdd(Player player, Nation nation, List invited) t /** * Final stage of adding towns to a nation. - * @param nation - Nation being added to. - * @param towns - List of Town(s) being added to Nation. - * @throws AlreadyRegisteredException - Shouldn't happen but could. + * + * @deprecated since 0.100.1.2 use {@link #nationAdd(Nation, Town)} instead. + * @param nation Nation being added to. + * @param towns List of Town(s) being added to Nation. */ - public static void nationAdd(Nation nation, List towns) throws AlreadyRegisteredException { - for (Town town : towns) { - if (!town.hasNation()) { - if (!testNationMaxTowns(nation)) { - // Nation has hit the max-towns limit. - TownyMessaging.sendPrefixedNationMessage(nation, Translatable.of("msg_err_nation_over_town_limit", TownySettings.getMaxTownsPerNation())); - TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_err_cannot_join_nation_over_town_limit", TownySettings.getMaxTownsPerNation())); - continue; - } - - if (!town.hasEnoughResidentsToJoinANation()) { - // Town has dropped below min.-residents-to-join-nation limit. - TownyMessaging.sendPrefixedNationMessage(nation, Translatable.of("msg_err_not_enough_residents_join_nation", town.getName())); - TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_err_not_enough_residents_join_nation", town.getName())); - continue; - } + @Deprecated + public static void nationAdd(Nation nation, List towns) { + for (Town town : towns) + nationAdd(nation, town); + } - if (!testNationMaxResidents(nation, town)) { - // Nation has hit the max-residents limit. - TownyMessaging.sendPrefixedNationMessage(nation, Translatable.of("msg_err_cannot_add_nation_over_resident_limit", TownySettings.getMaxResidentsPerNation(), town.getName())); - TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_err_cannot_join_nation_over_resident_limit", TownySettings.getMaxResidentsPerNation())); - continue; - } + /** + * Final stage of adding a town to a nation, via joining or via accepting an + * invite. We re-test the rules for joining a nation in case the town or + * nation's situation has changed since being sent the invite/join confirmation. + * + * @param nation Nation which would take on a new Town. + * @param town Town which would join the nation. + */ + public static void nationAdd(Nation nation, Town town) { + if (town.hasNation()) { + TownyMessaging.sendPrefixedNationMessage(nation, Translatable.of("msg_err_town_already_belong_nation", town.getName(), town.getNationOrNull().getName())); + TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_err_already_belong_nation")); + return; + } - town.setNation(nation); - town.save(); - TownyMessaging.sendPrefixedNationMessage(nation, Translatable.of("msg_join_nation", StringMgmt.remUnderscore(town.getName()))); - } + if (!town.hasEnoughResidentsToJoinANation()) { + // Town has dropped below min.-residents-to-join-nation limit. + TownyMessaging.sendPrefixedNationMessage(nation, Translatable.of("msg_err_not_enough_residents_join_nation", town.getName())); + TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_err_not_enough_residents_join_nation", town.getName())); + return; + } + if (nation.hasReachedMaxTowns()) { + // Nation has hit the max-towns limit. + TownyMessaging.sendPrefixedNationMessage(nation, Translatable.of("msg_err_nation_over_town_limit", TownySettings.getMaxTownsPerNation())); + TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_err_cannot_join_nation_over_town_limit", TownySettings.getMaxTownsPerNation())); + return; } - plugin.resetCache(); - nation.save(); - } - - private static boolean testNationMaxResidents(Nation nation, Town town) { - int maxResidentPerNation = TownySettings.getMaxResidentsPerNation(); - if (maxResidentPerNation < 1) - return true; - return !(nation.getResidents().size() + town.getResidents().size() > maxResidentPerNation); + if (!nation.canAddResidents(town.getNumResidents())) { + // Nation has hit the max-residents limit. + TownyMessaging.sendPrefixedNationMessage(nation, Translatable.of("msg_err_cannot_add_nation_over_resident_limit", TownySettings.getMaxResidentsPerNation(), town.getName())); + TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_err_cannot_join_nation_over_resident_limit", TownySettings.getMaxResidentsPerNation())); + return; + } - } + try { + town.setNation(nation); + } catch (AlreadyRegisteredException ignored) {} + town.save(); + TownyMessaging.sendPrefixedNationMessage(nation, Translatable.of("msg_join_nation", StringMgmt.remUnderscore(town.getName()))); - private static boolean testNationMaxTowns(Nation nation) { - if (TownySettings.getMaxTownsPerNation() < 1) - return true; - return !(nation.getTowns().size() >= TownySettings.getMaxTownsPerNation()); + // Reset the town's player cache to account for potential new plot permissions. + TownyAPI.getInstance().getOnlinePlayers(town).forEach(p-> plugin.resetCache(p)); } private static void nationRevokeInviteTown(CommandSender sender, Nation nation, List towns) { diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/object/Nation.java b/Towny/src/main/java/com/palmergames/bukkit/towny/object/Nation.java index 3fa02dee3d..bf3d0c32e6 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/object/Nation.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/object/Nation.java @@ -330,6 +330,18 @@ public int getNumResidents() { return numResidents; } + public boolean canAddResidents(int additionalResidents) { + return NationUtil.canAddTownsResidentCount(this, additionalResidents); + } + + public boolean hasReachedMaxResidents() { + return NationUtil.hasReachedMaximumResidents(this); + } + + public boolean hasReachedMaxTowns() { + return NationUtil.hasReachedMaximumTowns(this); + } + /** * Should only be called by Town.removeNation(); * Removes town from {@link #towns} list and will choose a @@ -738,4 +750,6 @@ public void loadSanctionedTowns(String[] tokens) { } } } + + } diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/object/inviteobjects/TownJoinNationInvite.java b/Towny/src/main/java/com/palmergames/bukkit/towny/object/inviteobjects/TownJoinNationInvite.java index 4b07c94988..0f483c3d87 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/object/inviteobjects/TownJoinNationInvite.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/object/inviteobjects/TownJoinNationInvite.java @@ -8,9 +8,6 @@ import com.palmergames.bukkit.towny.object.Translatable; import org.bukkit.command.CommandSender; -import java.util.ArrayList; -import java.util.List; - public class TownJoinNationInvite extends AbstractInvite { public TownJoinNationInvite(CommandSender directSender, Town receiver, Nation sender) { @@ -20,14 +17,8 @@ public TownJoinNationInvite(CommandSender directSender, Town receiver, Nation se @Override public void accept() throws TownyException { Town town = getReceiver(); - List towns = new ArrayList<>(); - towns.add(town); Nation nation = getSender(); - if(!town.hasNation()){ - NationCommand.nationAdd(nation, towns); - } else { - TownyMessaging.sendPrefixedTownMessage(town, Translatable.of("msg_err_already_nation", town.getName())); - } + NationCommand.nationAdd(nation, town); // Message handled in nationAdd() town.deleteReceivedInvite(this); nation.deleteSentInvite(this); diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/NationUtil.java b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/NationUtil.java index 3030dbd5fa..6db66ae18d 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/NationUtil.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/NationUtil.java @@ -60,4 +60,22 @@ private static String getTownJoinedNationDate(Town town, Translator translator) public static boolean hasReachedMaximumAllies(Nation nation) { return TownySettings.getMaxNationAllies() >= 0 && nation.getAllies().size() >= TownySettings.getMaxNationAllies(); } + + public static boolean hasReachedMaximumResidents(Nation nation) { + int maxResidentsPerNation = TownySettings.getMaxResidentsPerNation(); + return maxResidentsPerNation > 0 && nation.getResidents().size() >= maxResidentsPerNation; + } + + public static boolean canAddTownsResidentCount(Nation nation, int additionalResidents) { + if (hasReachedMaximumResidents(nation)) + return false; + int maxResidentPerNation = TownySettings.getMaxResidentsPerNation(); + return maxResidentPerNation > 0 && (nation.getResidents().size() + additionalResidents) >= maxResidentPerNation; + } + + public static boolean hasReachedMaximumTowns(Nation nation) { + int maxTownsPerNation = TownySettings.getMaxTownsPerNation(); + return maxTownsPerNation > 0 && nation.getTowns().size() >= maxTownsPerNation; + } + } diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index 181ea6a02c..8883ce4b2e 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9453,4 +9453,6 @@ v0.92.0.11: - Fix returning null in the relational placeholder code, returning the no-relation colour instead. - Refactor some of TownyFormatter's methods, mainly moving some component-creation out into their related Util classes. - Add NationUtil. - - Move max allies test into NationUtil. \ No newline at end of file + - Move max allies test into NationUtil. + - Add more nation-joining tests to the NationUtil. + - Refactor nation adding towns in the NationCommand class. \ No newline at end of file diff --git a/Towny/src/main/resources/lang/en-US.yml b/Towny/src/main/resources/lang/en-US.yml index 4ec67d9105..95643002f4 100644 --- a/Towny/src/main/resources/lang/en-US.yml +++ b/Towny/src/main/resources/lang/en-US.yml @@ -710,6 +710,8 @@ msg_err_not_in_town_claim: '&cYou must belong to a town in order to claim plots. msg_err_must_belong_town: '&cYou must belong to a town.' msg_err_dont_belong_town: '&cYou don''t belong to a town.' msg_err_dont_belong_nation: '&bYou don''t belong to a nation.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s doesn''t belong to your nation.' msg_err_rect_auto: '&cOnly towns and residents can use auto.' msg_err_invalid_radius: '&cInvalid radius. Use an integer or ''auto''.' From ccfca86d2b7f8904d546056eb0832607c6bac60d Mon Sep 17 00:00:00 2001 From: LlmDl Date: Tue, 16 Jan 2024 09:13:00 -0600 Subject: [PATCH 67/74] Refactor townAdd method to better handle adding and revoking invites. (#7188) Updates a lang string to actually be useful when revoking invites off a group of names. --- .../bukkit/towny/command/TownCommand.java | 212 +++++++----------- .../bukkit/towny/invites/InviteHandler.java | 8 + .../bukkit/towny/utils/ResidentUtil.java | 2 +- Towny/src/main/resources/lang/en-US.yml | 2 +- 4 files changed, 93 insertions(+), 131 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 a49bc55153..2af85063d8 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 @@ -2876,25 +2876,6 @@ private static void townInviteResident(CommandSender sender,Town town, Resident } } - private static void townRevokeInviteResident(CommandSender sender, Town town, List residents) { - - for (Resident invited : residents) { - if (InviteHandler.inviteIsActive(town, invited)) { - for (Invite invite : invited.getReceivedInvites()) { - if (invite.getSender().equals(town)) { - try { - InviteHandler.declineInvite(invite, true); - TownyMessaging.sendMsg(sender, Translatable.of("town_revoke_invite_successful")); - break; - } catch (InvalidObjectException e) { - plugin.getLogger().log(Level.WARNING, "An exception occurred while revoking invites for town " + town.getName(), e); - } - } - } - } - } - } - /** * Transforms a list of names into a list of residents to be kicked. * Command: /town kick [resident] .. [resident] @@ -3013,117 +2994,106 @@ private static void parseTownJoin(Player player, String[] args) throws TownyExce } /** - * Confirm player is a mayor or assistant, then get list of filter names - * with online players and invite them to town. Command: /town add - * [resident] .. [resident] + * Checks if the player is allowed to handle adding invites, then checks through + * a list of names to be invited, or to have their invites revoked. Will + * dispatch invites and/or revoke invites from names beginning with -. * - * @param sender - Sender. - * @param specifiedTown - Town to add to if not null. - * @param names - Names to add. - * @throws TownyException - General Exception, or if Town's spawn has not been set + * @param sender Sender. + * @param specifiedTown Town to add to if not null. + * @param names Names to add. + * @throws TownyException Thrown when an the invites are not allowed because of + * lack of permissions, ruined/bankruptcy, or the town + * having no spawn set. */ public static void townAdd(CommandSender sender, Town specifiedTown, String[] names) throws TownyException { - String name; - boolean console = false; - if (sender instanceof Player player) { - name = player.getName(); + Player player = null; + if (sender instanceof Player p) { + player = p; checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_TOWN_INVITE_ADD.getNode()); catchRuinedTown(player); - } else { - name = "Console"; - console = true; - } - - Resident resident; - Town town; - try { - if (console) { - town = specifiedTown; - } else { - resident = getResidentOrThrow(name); - if (specifiedTown == null) - town = resident.getTown(); - else - town = specifiedTown; - } - - } catch (TownyException x) { - TownyMessaging.sendErrorMsg(sender, x.getMessage(sender)); - return; } + // The /ta command can specify a town, the /t command cannot. + Town town = specifiedTown != null ? specifiedTown : getTownFromPlayerOrThrow(player); if (town.isBankrupt()) throw new TownyException(Translatable.of("msg_err_bankrupt_town_cannot_invite")); - if (TownySettings.getMaxDistanceFromTownSpawnForInvite() > 0) { + List nameList = new ArrayList<>(Arrays.asList(names)); + if (TownySettings.getMaxDistanceFromTownSpawnForInvite() > 0) + nameList = gatherNearbyPlayerNames(sender, nameList, town); - if (!town.hasSpawn()) - throw new TownyException(Translatable.of("msg_err_townspawn_has_not_been_set")); - - Location spawnLoc = town.getSpawn(); - ArrayList newNames = new ArrayList<>(); - int maxDistance = TownySettings.getMaxDistanceFromTownSpawnForInvite(); - - for (String nameForDistanceTest : names) { - Player player = BukkitTools.getPlayerExact(nameForDistanceTest); - if (player == null) - continue; - - Location playerLoc = player.getLocation(); - - double distance; - try { - distance = spawnLoc.distance(playerLoc); - } catch (Exception e) { - // Can throw an exception if the player is in another world - TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_err_player_too_far_from_town_spawn", nameForDistanceTest, maxDistance)); - continue; - } + // Get a list of valid names to invite. + List toInviteList = nameList.stream() + .filter(name -> !name.startsWith("-") && !town.hasResident(name)) + .collect(Collectors.toList()); - if (distance <= maxDistance) - newNames.add(nameForDistanceTest); - else { - TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_err_player_too_far_from_town_spawn", nameForDistanceTest, maxDistance)); - } - } - names = newNames.toArray(new String[0]); - } - List resList = new ArrayList<>(Arrays.asList(names)); - // Our Arraylist is above - List newResList = new ArrayList<>(); - // The list of valid invites is above, there are currently none - List removeInvites = new ArrayList<>(); - // List of invites to be removed; - for (String resName : resList) { - if (resName.startsWith("-")) { - removeInvites.add(resName.substring(1)); - // Add to removing them, remove the "-" - } else { - if (!town.hasResident(resName)) - newResList.add(resName);// add to adding them, - else - removeInvites.add(resName); - } - } - - if (newResList.size() + removeInvites.size() > 1) + // Get a list of negated names to revoke an invite from. + // (Legacy code also included anyone that is already a resident of the town for some reason.) + List toRevokeInviteList = nameList.stream() + .filter(name -> name.startsWith("-") || town.hasResident(name)) + .map(name -> name.startsWith("-") ? name.substring(1) : name) + .collect(Collectors.toList()); + + // There's a special permission node to prevent invite spam. + if (toInviteList.size() + toRevokeInviteList.size() > 1) checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWN_INVITE_ADD_MULTIPLE.getNode()); - - names = newResList.toArray(new String[0]); - String[] namesToRemove = removeInvites.toArray(new String[0]); - if (namesToRemove.length != 0) { - List toRevoke = getValidatedResidentsForInviteRevoke(sender, namesToRemove, town); - if (!toRevoke.isEmpty()) - townRevokeInviteResident(sender, town, toRevoke); + + // Begin process of sending invites. + if (!toInviteList.isEmpty()) + townAddResidents(sender, town, ResidentUtil.getValidatedResidents(sender, toInviteList)); + + // Pare down revoke list to names that have received invites, then revoke the invite. + if (!toRevokeInviteList.isEmpty()) { + townRevokeResidentInvites(sender, town, + ResidentUtil.getValidatedResidents(sender, town.getSentInvites().stream() // Take the towns sent invites. + .filter(invite -> toRevokeInviteList.contains(invite.getReceiver().getName())) // Find an invite which matches one of our names. + .map(invite -> invite.getReceiver().getName()) // Get the name of that person who was invited. + .collect(Collectors.toList()))); } + } + + private static List gatherNearbyPlayerNames(CommandSender sender, List names, Town town) throws TownyException { + if (!town.hasSpawn()) + throw new TownyException(Translatable.of("msg_err_townspawn_has_not_been_set")); + + Location spawnLoc = town.getSpawn(); + int maxDistance = TownySettings.getMaxDistanceFromTownSpawnForInvite(); + return names.stream() + .filter(name -> playerIsNearEnoughToTownSpawn(sender, name, spawnLoc, maxDistance)) + .collect(Collectors.toList()); + } + + private static boolean playerIsNearEnoughToTownSpawn(CommandSender sender, String name, Location spawnLoc, int maxDistance) { + try { + Player player = BukkitTools.getPlayerExact(name); + if (player == null) + return false; + + Location playerLoc = player.getLocation(); + if (!playerLoc.getWorld().equals(spawnLoc.getWorld())) + throw new TownyException(Translatable.of("msg_err_player_too_far_from_town_spawn", name, maxDistance)); - if (names.length != 0) { - townAddResidents(sender, town, ResidentUtil.getValidatedResidents(sender, names)); + double distance = spawnLoc.distance(playerLoc); + if (distance > maxDistance) + throw new TownyException(Translatable.of("msg_err_player_too_far_from_town_spawn", name, maxDistance)); + + return true; + } catch (TownyException e) { + TownyMessaging.sendErrorMsg(sender, e.getMessage(sender)); + return false; } + } - // Reset this players cached permissions - if (!console) - plugin.resetCache(BukkitTools.getPlayerExact(name)); + private static void townRevokeResidentInvites(CommandSender sender, Town town, List residents) { + residents.forEach((resident) -> + InviteHandler.getActiveInvitesFor(town, resident).forEach(invite -> { + try { + InviteHandler.declineInvite(invite, true); + TownyMessaging.sendMsg(sender, Translatable.of("town_revoke_invite_successful", resident.getName())); + } catch (InvalidObjectException e) { + plugin.getLogger().log(Level.WARNING, "An exception occurred while revoking invite for resident " + resident.getName() + " from town " + town.getName(), e); + } + })); } // wrapper function for non friend setting of perms @@ -3861,22 +3831,6 @@ public static boolean isEdgeBlock(TownBlockOwner owner, WorldCoord worldCoord, L return false; } - public static List getValidatedResidentsForInviteRevoke(Object sender, String[] names, Town town) { - List toRevoke = new ArrayList<>(); - for (Invite invite : town.getSentInvites()) { - for (String name : names) { - if (invite.getReceiver().getName().equalsIgnoreCase(name)) { - Resident revokeRes = TownyUniverse.getInstance().getResident(name); - if (revokeRes != null) { - toRevoke.add(revokeRes); - } - } - } - - } - return toRevoke; - } - private static void townTransaction(Player player, String[] args, boolean withdraw) { try { if (args.length == 0) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/invites/InviteHandler.java b/Towny/src/main/java/com/palmergames/bukkit/towny/invites/InviteHandler.java index 5d8ceea497..cd895c136d 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/invites/InviteHandler.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/invites/InviteHandler.java @@ -11,8 +11,10 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; /** * @author - Articdive @@ -98,6 +100,12 @@ public static boolean inviteIsActive(InviteSender sender, InviteReceiver receive return false; } + public static List getActiveInvitesFor(InviteSender sender, InviteReceiver receiver) { + return ACTIVE_INVITES.keySet().stream() + .filter(activeInvite -> activeInvite.getReceiver().equals(receiver) && activeInvite.getSender().equals(sender)) + .collect(Collectors.toList()); + } + public static int getSentAllyRequestsMaxAmount(Nation sender) { int amount = 0; if (sender != null) { diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/ResidentUtil.java b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/ResidentUtil.java index 64ef657e1f..bbc7aefc2a 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/ResidentUtil.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/ResidentUtil.java @@ -70,7 +70,7 @@ public static List getOnlineResidentsViewable(Player viewer, ResidentL * @param names - Names to be converted. * @return - List of residents to be used later. */ - public static List getValidatedResidents(CommandSender sender, String[] names) { + public static List getValidatedResidents(CommandSender sender, List names) { List residents = new ArrayList<>(); for (String name : names) { List matches = BukkitTools.matchPlayer(name); diff --git a/Towny/src/main/resources/lang/en-US.yml b/Towny/src/main/resources/lang/en-US.yml index 95643002f4..eb76677656 100644 --- a/Towny/src/main/resources/lang/en-US.yml +++ b/Towny/src/main/resources/lang/en-US.yml @@ -912,7 +912,7 @@ msg_err_nation_sent_too_many_requests: '&bNation has sent too many requests, rev msg_err_nation_has_too_many_requests: '&bNation %s has too many requests, ask them to decline some, before requesting again.' player_received_invites: '&bYou have received %a/%m invites.' town_revoke_invite: '&bTown %s, revoked your invite to join them.' -town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bTown has received %a/%m invites.' town_sent_invites: '&bTown has sent %a/%m invites.' nation_revoke_invite: '&bNation %s, revoked your invite to join them.' From 5916aabbe535aa82c97d7acc23e4614887f95bfd Mon Sep 17 00:00:00 2001 From: LlmDl Date: Tue, 16 Jan 2024 11:06:52 -0600 Subject: [PATCH 68/74] - Refactor townAdd method to better handle adding and revoking invites. - Fix not being able to add towns to nations when the residents-per-nation setting is 0. --- Towny/pom.xml | 2 +- .../java/com/palmergames/bukkit/towny/utils/NationUtil.java | 2 +- Towny/src/main/resources/ChangeLog.txt | 5 ++++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Towny/pom.xml b/Towny/pom.xml index 80b5948420..2a202b6c25 100644 --- a/Towny/pom.xml +++ b/Towny/pom.xml @@ -13,7 +13,7 @@ towny jar - 0.100.1.2 + 0.100.1.3 diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/NationUtil.java b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/NationUtil.java index 6db66ae18d..7f93f4738e 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/NationUtil.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/NationUtil.java @@ -70,7 +70,7 @@ public static boolean canAddTownsResidentCount(Nation nation, int additionalResi if (hasReachedMaximumResidents(nation)) return false; int maxResidentPerNation = TownySettings.getMaxResidentsPerNation(); - return maxResidentPerNation > 0 && (nation.getResidents().size() + additionalResidents) >= maxResidentPerNation; + return maxResidentPerNation == 0 || (nation.getResidents().size() + additionalResidents) < maxResidentPerNation; } public static boolean hasReachedMaximumTowns(Nation nation) { diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index 8883ce4b2e..f2fc49afdf 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9455,4 +9455,7 @@ v0.92.0.11: - Add NationUtil. - Move max allies test into NationUtil. - Add more nation-joining tests to the NationUtil. - - Refactor nation adding towns in the NationCommand class. \ No newline at end of file + - Refactor nation adding towns in the NationCommand class. +0.100.1.3: + - Refactor townAdd method to better handle adding and revoking invites. + - Fix not being able to add towns to nations when the residents-per-nation setting is 0. \ No newline at end of file From 0d14db803c5f1ccc3cb288b5cfaa4dcd6878e3ee Mon Sep 17 00:00:00 2001 From: LlmDl Date: Tue, 16 Jan 2024 11:07:21 -0600 Subject: [PATCH 69/74] Add a configurable amount of bonus townblocks given to new towns. (#7196) Closes #7195. Takes care of a loophole that would let merging towns farm bonus townblocks. --- .../com/palmergames/bukkit/config/ConfigNodes.java | 6 ++++++ .../com/palmergames/bukkit/towny/TownySettings.java | 4 ++++ .../bukkit/towny/command/TownCommand.java | 12 ++++++++++-- .../bukkit/towny/db/TownyDatabaseHandler.java | 7 ++++++- .../bukkit/towny/listeners/TownyCustomListener.java | 5 +++++ 5 files changed, 31 insertions(+), 3 deletions(-) diff --git a/Towny/src/main/java/com/palmergames/bukkit/config/ConfigNodes.java b/Towny/src/main/java/com/palmergames/bukkit/config/ConfigNodes.java index 672c5385ef..6dcdbc4f41 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/config/ConfigNodes.java +++ b/Towny/src/main/java/com/palmergames/bukkit/config/ConfigNodes.java @@ -990,6 +990,12 @@ public enum ConfigNodes { "# The maximum townblocks available to a town is (numResidents * ratio).", "# Setting this value to 0 will instead use the level based jump values determined in the town level config.", "# Setting this to -1 will result in every town having unlimited claims."), + CLAIMING_DEF_BONUS_CLAIMS( + "claiming.new_town_bonus_claims", + "0", + "", + "# An amount of additional townblocks that a town will receive when it is first created, in addition to any amount given via the town_block_ratio or town_levels.", + "# As an example: This can be used to add 10 townblocks to a town when it is made so the borders can be grown a bit more before the mayor has to seek out residents."), CLAIMING_TOWN_BLOCK_LIMIT( "claiming.town_block_limit", "0", diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/TownySettings.java b/Towny/src/main/java/com/palmergames/bukkit/towny/TownySettings.java index 7a639e4554..3c37faee26 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/TownySettings.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/TownySettings.java @@ -1338,6 +1338,10 @@ public static int getTownBlockRatio() { return getInt(ConfigNodes.CLAIMING_TOWN_BLOCK_RATIO); } + public static int getNewTownBonusBlocks() { + return getInt(ConfigNodes.CLAIMING_DEF_BONUS_CLAIMS); + } + public static int getTownBlockSize() { return getInt(ConfigNodes.CLAIMING_TOWN_BLOCK_SIZE); 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 2af85063d8..17ec2c3f5d 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 @@ -3707,8 +3707,7 @@ private static void vetTownsForMergeAndThrow(Town remainingTown, Town succumbing newResidentsAmount > TownySettings.getMaxResidentsForTown(remainingTown)) throw new TownyException(Translatable.of("msg_town_merge_err_too_many_residents", TownySettings.getMaxResidentsForTown(remainingTown))); - if (!remainingTown.hasUnlimitedClaims() && - (remainingTown.getNumTownBlocks() + succumbingTown.getNumTownBlocks()) > TownySettings.getMaxTownBlocks(remainingTown, newResidentsAmount)) + if (!remainingTown.hasUnlimitedClaims() && townWouldHaveTooManyTownBlocks(remainingTown, succumbingTown, newResidentsAmount)) throw new TownyException(Translatable.of("msg_town_merge_err_too_many_townblocks", TownySettings.getMaxTownBlocks(remainingTown, newResidentsAmount))); if ((remainingTown.getPurchasedBlocks() + succumbingTown.getPurchasedBlocks()) > TownySettings.getMaxPurchasedBlocks(remainingTown, newResidentsAmount)) @@ -3731,6 +3730,15 @@ private static void vetTownsForMergeAndThrow(Town remainingTown, Town succumbing throw new TownyException(Translatable.of("msg_town_merge_other_offline", succumbingTown.getName(), succumbingTown.getMayor().getName())); } + private static boolean townWouldHaveTooManyTownBlocks(Town remainingTown, Town succumbingTown, int newResidentsAmount) { + int newTownBonus = TownySettings.getNewTownBonusBlocks(); + int succumbingTownTBAmount = succumbingTown.getNumTownBlocks(); + if (newTownBonus > 0 && succumbingTown.getBonusBlocks() >= newTownBonus) + succumbingTownTBAmount = succumbingTownTBAmount - newTownBonus; + + return (remainingTown.getNumTownBlocks() + succumbingTownTBAmount) > TownySettings.getMaxTownBlocks(remainingTown, newResidentsAmount); + } + 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. diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/db/TownyDatabaseHandler.java b/Towny/src/main/java/com/palmergames/bukkit/towny/db/TownyDatabaseHandler.java index dba222b55a..b0c7c8e9e1 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/db/TownyDatabaseHandler.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/db/TownyDatabaseHandler.java @@ -1145,7 +1145,12 @@ public void mergeTown(Town mergeInto, Town mergeFrom) { List outposts = new ArrayList(mergeFrom.getAllOutpostSpawns()); mergeInto.addPurchasedBlocks(mergeFrom.getPurchasedBlocks()); - mergeInto.addBonusBlocks(mergeFrom.getBonusBlocks()); + + int mergeFromBonus = mergeFrom.getBonusBlocks(); + int newTownBonus = TownySettings.getNewTownBonusBlocks(); + if (newTownBonus > 0 && mergeFromBonus >= newTownBonus) + mergeFromBonus = mergeFromBonus - newTownBonus; + mergeInto.addBonusBlocks(mergeFromBonus); for (TownBlock tb : mergeFrom.getTownBlocks()) { tb.setTown(mergeInto); diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyCustomListener.java b/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyCustomListener.java index c48ec640c6..6169ed3861 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyCustomListener.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyCustomListener.java @@ -115,6 +115,11 @@ public void onPlayerCreateTown(NewTownEvent event) { } }, 200L); + // Award new town with any potential bonus blocks. + int bonus = TownySettings.getNewTownBonusBlocks(); + if (bonus > 0) + town.setBonusBlocks(town.getBonusBlocks() + bonus); + //TODO: at some point it might be nice to have a written_book given to mayors // which could contain the above advice about depositing money, or containing // links to the commands page on the wiki. From a1043c70b069f7a4b51f11d400c0d8bb9f399cab Mon Sep 17 00:00:00 2001 From: LlmDl Date: Tue, 16 Jan 2024 11:07:57 -0600 Subject: [PATCH 70/74] New Crowdin updates (#7189) * New translations en-us.yml (Chinese Simplified) * New translations en-us.yml (German) * New translations en-us.yml (Romanian) * New translations en-us.yml (French) * New translations en-us.yml (Spanish) * New translations en-us.yml (Bulgarian) * New translations en-us.yml (Czech) * New translations en-us.yml (Danish) * New translations en-us.yml (Hebrew) * New translations en-us.yml (Italian) * New translations en-us.yml (Japanese) * New translations en-us.yml (Korean) * New translations en-us.yml (Lithuanian) * New translations en-us.yml (Dutch) * New translations en-us.yml (Norwegian) * New translations en-us.yml (Polish) * New translations en-us.yml (Portuguese) * New translations en-us.yml (Russian) * New translations en-us.yml (Albanian) * New translations en-us.yml (Swedish) * New translations en-us.yml (Turkish) * New translations en-us.yml (Ukrainian) * New translations en-us.yml (Chinese Traditional) * New translations en-us.yml (Vietnamese) * New translations en-us.yml (Portuguese, Brazilian) * New translations en-us.yml (Indonesian) * New translations en-us.yml (Spanish, Argentina) * New translations en-us.yml (Spanish, Chile) * New translations en-us.yml (Spanish, Mexico) * New translations en-us.yml (Spanish, Uruguay) * New translations en-us.yml (Spanish, Venezuela) * New translations en-us.yml (Spanish, Ecuador) * New translations en-us.yml (Thai) * New translations en-us.yml (Azerbaijani) * New translations en-us.yml (English, United Kingdom) * New translations en-us.yml (Tagalog) * New translations en-us.yml (Pirate English) * New translations en-us.yml (Serbian (Latin)) * New translations en-us.yml (English (upside down)) * New translations en-us.yml (LOLCAT) * New translations en-us.yml (Classical Chinese) * Update source file en-US.yml * New translations en-us.yml (Korean) * New translations en-us.yml (Romanian) * New translations en-us.yml (French) * New translations en-us.yml (Spanish) * New translations en-us.yml (Bulgarian) * New translations en-us.yml (Czech) * New translations en-us.yml (Danish) * New translations en-us.yml (Chinese Simplified) * New translations en-us.yml (German) * New translations en-us.yml (Hebrew) * New translations en-us.yml (Italian) * New translations en-us.yml (Japanese) * New translations en-us.yml (Korean) * New translations en-us.yml (Lithuanian) * New translations en-us.yml (Dutch) * New translations en-us.yml (Norwegian) * New translations en-us.yml (Polish) * New translations en-us.yml (Portuguese) * New translations en-us.yml (Russian) * New translations en-us.yml (Albanian) * New translations en-us.yml (Swedish) * New translations en-us.yml (Turkish) * New translations en-us.yml (Ukrainian) * New translations en-us.yml (Chinese Traditional) * New translations en-us.yml (Vietnamese) * New translations en-us.yml (Portuguese, Brazilian) * New translations en-us.yml (Indonesian) * New translations en-us.yml (Spanish, Argentina) * New translations en-us.yml (Spanish, Chile) * New translations en-us.yml (Spanish, Mexico) * New translations en-us.yml (Spanish, Uruguay) * New translations en-us.yml (Spanish, Venezuela) * New translations en-us.yml (Spanish, Ecuador) * New translations en-us.yml (Thai) * New translations en-us.yml (Azerbaijani) * New translations en-us.yml (English, United Kingdom) * New translations en-us.yml (Tagalog) * New translations en-us.yml (Pirate English) * New translations en-us.yml (Serbian (Latin)) * New translations en-us.yml (English (upside down)) * New translations en-us.yml (LOLCAT) * New translations en-us.yml (Classical Chinese) * Update source file en-US.yml * New translations en-us.yml (Chinese Simplified) * New translations en-us.yml (German) * New translations en-us.yml (Romanian) * New translations en-us.yml (French) * New translations en-us.yml (Spanish) * New translations en-us.yml (Bulgarian) * New translations en-us.yml (Czech) * New translations en-us.yml (Danish) * New translations en-us.yml (Hebrew) * New translations en-us.yml (Italian) * New translations en-us.yml (Japanese) * New translations en-us.yml (Korean) * New translations en-us.yml (Lithuanian) * New translations en-us.yml (Dutch) * New translations en-us.yml (Norwegian) * New translations en-us.yml (Polish) * New translations en-us.yml (Portuguese) * New translations en-us.yml (Russian) * New translations en-us.yml (Albanian) * New translations en-us.yml (Swedish) * New translations en-us.yml (Turkish) * New translations en-us.yml (Ukrainian) * New translations en-us.yml (Chinese Traditional) * New translations en-us.yml (Vietnamese) * New translations en-us.yml (Portuguese, Brazilian) * New translations en-us.yml (Indonesian) * New translations en-us.yml (Spanish, Argentina) * New translations en-us.yml (Spanish, Chile) * New translations en-us.yml (Spanish, Mexico) * New translations en-us.yml (Spanish, Uruguay) * New translations en-us.yml (Spanish, Venezuela) * New translations en-us.yml (Spanish, Ecuador) * New translations en-us.yml (Thai) * New translations en-us.yml (Azerbaijani) * New translations en-us.yml (English, United Kingdom) * New translations en-us.yml (Tagalog) * New translations en-us.yml (Pirate English) * New translations en-us.yml (Serbian (Latin)) * New translations en-us.yml (English (upside down)) * New translations en-us.yml (LOLCAT) * New translations en-us.yml (Classical Chinese) --- Towny/src/main/resources/lang/az-AZ.yml | 6 +++++- Towny/src/main/resources/lang/bg-BG.yml | 6 +++++- Towny/src/main/resources/lang/cs-CZ.yml | 6 +++++- Towny/src/main/resources/lang/da-DK.yml | 6 +++++- Towny/src/main/resources/lang/de-DE.yml | 6 +++++- Towny/src/main/resources/lang/en-GB.yml | 6 +++++- Towny/src/main/resources/lang/en-PT.yml | 6 +++++- Towny/src/main/resources/lang/en-UD.yml | 6 +++++- Towny/src/main/resources/lang/es-AR.yml | 6 +++++- Towny/src/main/resources/lang/es-CL.yml | 6 +++++- Towny/src/main/resources/lang/es-EC.yml | 6 +++++- Towny/src/main/resources/lang/es-ES.yml | 6 +++++- Towny/src/main/resources/lang/es-MX.yml | 6 +++++- Towny/src/main/resources/lang/es-UY.yml | 6 +++++- Towny/src/main/resources/lang/es-VE.yml | 6 +++++- Towny/src/main/resources/lang/fr-FR.yml | 6 +++++- Towny/src/main/resources/lang/he-IL.yml | 6 +++++- Towny/src/main/resources/lang/id-ID.yml | 6 +++++- Towny/src/main/resources/lang/it-IT.yml | 6 +++++- Towny/src/main/resources/lang/ja-JP.yml | 6 +++++- Towny/src/main/resources/lang/ko-KR.yml | 8 ++++++-- Towny/src/main/resources/lang/lol-US.yml | 6 +++++- Towny/src/main/resources/lang/lt-LT.yml | 6 +++++- Towny/src/main/resources/lang/lzh.yml | 6 +++++- Towny/src/main/resources/lang/nl-NL.yml | 6 +++++- Towny/src/main/resources/lang/no-NO.yml | 6 +++++- Towny/src/main/resources/lang/pl-PL.yml | 6 +++++- Towny/src/main/resources/lang/pt-BR.yml | 6 +++++- Towny/src/main/resources/lang/pt-PT.yml | 6 +++++- Towny/src/main/resources/lang/ro-RO.yml | 6 +++++- Towny/src/main/resources/lang/ru-RU.yml | 6 +++++- Towny/src/main/resources/lang/sq-AL.yml | 6 +++++- Towny/src/main/resources/lang/sr-CS.yml | 6 +++++- Towny/src/main/resources/lang/sv-SE.yml | 6 +++++- Towny/src/main/resources/lang/th-TH.yml | 6 +++++- Towny/src/main/resources/lang/tl-PH.yml | 6 +++++- Towny/src/main/resources/lang/tr-TR.yml | 6 +++++- Towny/src/main/resources/lang/uk-UA.yml | 6 +++++- Towny/src/main/resources/lang/vi-VN.yml | 6 +++++- Towny/src/main/resources/lang/zh-CN.yml | 6 +++++- Towny/src/main/resources/lang/zh-TW.yml | 6 +++++- 41 files changed, 206 insertions(+), 42 deletions(-) diff --git a/Towny/src/main/resources/lang/az-AZ.yml b/Towny/src/main/resources/lang/az-AZ.yml index 02ee7bbe42..b8dbd444c2 100644 --- a/Towny/src/main/resources/lang/az-AZ.yml +++ b/Towny/src/main/resources/lang/az-AZ.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cSən şəhərə mənsub olmalısan ki, topraq təl msg_err_must_belong_town: '&cSiz gərək ki, hansısa şəhərə mənsub olasınız.' msg_err_dont_belong_town: '&cBir şəhərə ait deyilsən.' msg_err_dont_belong_nation: '&bBir millətə aid deyilsən.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s millətinizə aid deyil.' msg_err_rect_auto: '&cAvtomobili yalnız şəhərlər və sakinlər işlədə bilər.' msg_err_invalid_radius: '&cYolverilməz radius. Tam və ya "avtomatik" istifadə edin.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&bNation has sent too many requests, rev msg_err_nation_has_too_many_requests: '&bNation %s has too many requests, ask them to decline some, before requesting again.' player_received_invites: '&bYou have received %a/%m invites.' town_revoke_invite: '&bTown %s, revoked your invite to join them.' -town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bTown has received %a/%m invites.' town_sent_invites: '&bTown has sent %a/%m invites.' nation_revoke_invite: '&bNation %s, revoked your invite to join them.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/bg-BG.yml b/Towny/src/main/resources/lang/bg-BG.yml index 3d37035596..225a1a7b23 100644 --- a/Towny/src/main/resources/lang/bg-BG.yml +++ b/Towny/src/main/resources/lang/bg-BG.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cYou must belong to a town in order to claim plots. msg_err_must_belong_town: '&cYou must belong to a town.' msg_err_dont_belong_town: '&cYou don''t belong to a town.' msg_err_dont_belong_nation: '&bYou don''t belong to a nation.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s doesn''t belong to your nation.' msg_err_rect_auto: '&cOnly towns and residents can use auto.' msg_err_invalid_radius: '&cInvalid radius. Use an integer or ''auto''.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&bNation has sent too many requests, rev msg_err_nation_has_too_many_requests: '&bNation %s has too many requests, ask them to decline some, before requesting again.' player_received_invites: '&bYou have received %a/%m invites.' town_revoke_invite: '&bTown %s, revoked your invite to join them.' -town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bTown has received %a/%m invites.' town_sent_invites: '&bTown has sent %a/%m invites.' nation_revoke_invite: '&bNation %s, revoked your invite to join them.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/cs-CZ.yml b/Towny/src/main/resources/lang/cs-CZ.yml index 6e80c6ac6e..7773311061 100644 --- a/Towny/src/main/resources/lang/cs-CZ.yml +++ b/Towny/src/main/resources/lang/cs-CZ.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cAbys mohl/a zabírat parcely, musíš patřit do m msg_err_must_belong_town: '&cMusíš patřit do města.' msg_err_dont_belong_town: '&cNepatříš do města.' msg_err_dont_belong_nation: '&bNepatříš do národa.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s nepatří do tvého národa.' msg_err_rect_auto: '&cPouze obyvatelé mohou požívat Auto.' msg_err_invalid_radius: '&cNeplatný radius. Požij celé číslo nebo auto.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&bNárod odeslal příliš mnoho žádos msg_err_nation_has_too_many_requests: '&bFrakce %s má příliš mnoho pozvánek, požádejte je, aby některé odmítli, než zkusíte znovu.' player_received_invites: '&bObdrželi jste %a/%m pozvání.' town_revoke_invite: '&bMěsto %s zrušilo tvoji pozvánku o připojení se k nim.' -town_revoke_invite_successful: '&bÚspěšně jsi zrušil pozvánku o připojení k tvému městu.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bMěsto obdrželo %a/%m pozvání.' town_sent_invites: '&bMěsto odeslalo %a/%m pozvánek.' nation_revoke_invite: '&bNárod%s zrušil tvoji pozvánku o připojení se k nim.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/da-DK.yml b/Towny/src/main/resources/lang/da-DK.yml index e5639ff673..ac9fdbd553 100644 --- a/Towny/src/main/resources/lang/da-DK.yml +++ b/Towny/src/main/resources/lang/da-DK.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cDu skal tilhøre en by for at gøre krav på grund msg_err_must_belong_town: '&cDu skal tilhøre en by.' msg_err_dont_belong_town: '&cDu tilhører ikke nogen by.' msg_err_dont_belong_nation: '&cDu tilhører ikke en nation.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s tilhører ikke din nation.' msg_err_rect_auto: '&cKun byer og indbyggere kan bruge auto.' msg_err_invalid_radius: '&cInvalid radius. Brug et heltal eller ''auto''.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&bNationen har sendt for mange anmodning msg_err_nation_has_too_many_requests: '&bNationen %s har for mange anmodninger. Bed dem om at afvise nogle, før du anmoder igen.' player_received_invites: '&bDu har modtaget %a/%m invitationer.' town_revoke_invite: '&bByen %s tilbagekaldte din invitation om at tilslutte dem.' -town_revoke_invite_successful: '&bDu har succesfuldt tilbagekaldt en invitation om at tilslutte sig din by.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bByen har modtaget %a/%m invitationer.' town_sent_invites: '&bByen har sendt %a/%m invitationer.' nation_revoke_invite: '&Nationen %s tilbagekaldte din invitation om at tilslutte dem.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/de-DE.yml b/Towny/src/main/resources/lang/de-DE.yml index 694cbce711..f1eba4c75d 100644 --- a/Towny/src/main/resources/lang/de-DE.yml +++ b/Towny/src/main/resources/lang/de-DE.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cSolange du in keiner Stadt bist, kannst du keine B msg_err_must_belong_town: '&cDu musst einer Stadt angehören.' msg_err_dont_belong_town: '&cDu gehörst zu keiner Stadt.' msg_err_dont_belong_nation: '&bDu gehörst zu keiner Nation.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s gehört nicht zu deiner Nation.' msg_err_rect_auto: '&cNur Städte oder Bürger können ''auto'' benutzen.' msg_err_invalid_radius: '&cUngültiger Radius. Benutze eine ganze Zahl oder ''auto''.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&bDie Nation hat zu viele Anfragen verse msg_err_nation_has_too_many_requests: '&bNation %s hat zu viele Anfragen. Sie muss zuerst einige ablehnen, bevor sie wieder Anfragen senden kann.' player_received_invites: '&bDu hast %a/%m Einladungen empfangen.' town_revoke_invite: '&Stadt %s, iht ihre Einladung zurückgezogen ihnen beizutreten.' -town_revoke_invite_successful: '&bDu hast eine Einladung zum Beitritt der Stadt erfolgreich widerrufen.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bDie Stadt hat %a/%m Einladungen empfangen.' town_sent_invites: '&bDie Stadt hat %a/%m Einladungen gesendet.' nation_revoke_invite: '&bNation %s, hat ihre Einladung zurückgezogen ihnen beizutreten.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/en-GB.yml b/Towny/src/main/resources/lang/en-GB.yml index a252ae9848..75c4d90540 100644 --- a/Towny/src/main/resources/lang/en-GB.yml +++ b/Towny/src/main/resources/lang/en-GB.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cYou must belong to a town in order to claim plots. msg_err_must_belong_town: '&cYou must belong to a town.' msg_err_dont_belong_town: '&cYou don''t belong to a town.' msg_err_dont_belong_nation: '&bYou don''t belong to a nation.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s doesn''t belong to your nation.' msg_err_rect_auto: '&cOnly towns and residents can use auto.' msg_err_invalid_radius: '&cInvalid radius. Use an integer or ''auto''.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&bNation has sent too many requests, rev msg_err_nation_has_too_many_requests: '&bNation %s has too many requests, ask them to decline some, before requesting again.' player_received_invites: '&bYou have received %a/%m invites.' town_revoke_invite: '&bTown %s, revoked your invite to join them.' -town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bTown has received %a/%m invites.' town_sent_invites: '&bTown has sent %a/%m invites.' nation_revoke_invite: '&bNation %s, revoked your invite to join them.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/en-PT.yml b/Towny/src/main/resources/lang/en-PT.yml index 6ff9739453..296aa3bb69 100644 --- a/Towny/src/main/resources/lang/en-PT.yml +++ b/Towny/src/main/resources/lang/en-PT.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cYou must belong to a town in order to claim plots. msg_err_must_belong_town: '&cYou must belong to a town.' msg_err_dont_belong_town: '&cYou don''t belong to a town.' msg_err_dont_belong_nation: '&bYou don''t belong to a nation.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s doesn''t belong to your nation.' msg_err_rect_auto: '&cOnly towns and residents can use auto.' msg_err_invalid_radius: '&cInvalid radius. Use an integer or ''auto''.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&bNation has sent too many requests, rev msg_err_nation_has_too_many_requests: '&bNation %s has too many requests, ask them to decline some, before requesting again.' player_received_invites: '&bYou have received %a/%m invites.' town_revoke_invite: '&bTown %s, revoked your invite to join them.' -town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bTown has received %a/%m invites.' town_sent_invites: '&bTown has sent %a/%m invites.' nation_revoke_invite: '&bNation %s, revoked your invite to join them.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/en-UD.yml b/Towny/src/main/resources/lang/en-UD.yml index e6e8a3c549..7de0f341dd 100644 --- a/Towny/src/main/resources/lang/en-UD.yml +++ b/Towny/src/main/resources/lang/en-UD.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cYou must belong to a town in order to claim plots. msg_err_must_belong_town: '&cYou must belong to a town.' msg_err_dont_belong_town: '&cYou don''t belong to a town.' msg_err_dont_belong_nation: '&bYou don''t belong to a nation.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s doesn''t belong to your nation.' msg_err_rect_auto: '&cOnly towns and residents can use auto.' msg_err_invalid_radius: '&cInvalid radius. Use an integer or ''auto''.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&bNation has sent too many requests, rev msg_err_nation_has_too_many_requests: '&bNation %s has too many requests, ask them to decline some, before requesting again.' player_received_invites: '&bYou have received %a/%m invites.' town_revoke_invite: '&bTown %s, revoked your invite to join them.' -town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bTown has received %a/%m invites.' town_sent_invites: '&bTown has sent %a/%m invites.' nation_revoke_invite: '&bNation %s, revoked your invite to join them.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/es-AR.yml b/Towny/src/main/resources/lang/es-AR.yml index 60b33c71f4..b679ed46ab 100644 --- a/Towny/src/main/resources/lang/es-AR.yml +++ b/Towny/src/main/resources/lang/es-AR.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cDebes pertenecer a una ciudad para poder reclamar msg_err_must_belong_town: '&cDebes pertenecer a una ciudad.' msg_err_dont_belong_town: '&cNo perteneces a una ciudad.' msg_err_dont_belong_nation: '&bNo perteneces a una nación.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s no pertenece a tu nación.' msg_err_rect_auto: '&cSolo las ciudades y habitantes pueden usar auto.' msg_err_invalid_radius: '&cRadio inválido. Usa un número entero o ''auto''.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&b¡La nación ha emitido demasiadas sol msg_err_nation_has_too_many_requests: '&b¡La nación de %s tiene demasiadas solicitudes! Pidele al rey que responda algunas y intentalo denuevo.' player_received_invites: '&bHas recibido %a/%m invitaciones.' town_revoke_invite: '&bLa ciudad de %s anuló tu invitación.' -town_revoke_invite_successful: '&bAnulaste una invitación para unirse a tu ciudad.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bLa ciudad ha recibido %a/%m invitaciones.' town_sent_invites: '&bLa ciudad ha enviado %a/%m invitaciones.' nation_revoke_invite: '&bLa nación de %s anuló tu invitación.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/es-CL.yml b/Towny/src/main/resources/lang/es-CL.yml index a391c6a8a4..f4094ad01c 100644 --- a/Towny/src/main/resources/lang/es-CL.yml +++ b/Towny/src/main/resources/lang/es-CL.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cDebes pertenecer a una ciudad para poder reclamar msg_err_must_belong_town: '&cDebes pertenecer a una ciudad.' msg_err_dont_belong_town: '&cNo perteneces a una ciudad.' msg_err_dont_belong_nation: '&bNo perteneces a una nación.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s no pertenece a tu nación.' msg_err_rect_auto: '&cSolo las ciudades y residentes pueden usar auto.' msg_err_invalid_radius: '&cRadio inválido. Usa un número entero o ''auto''.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&b¡La nación ha emitido demasiadas sol msg_err_nation_has_too_many_requests: '&b¡La nación de %s tiene demasiadas solicitudes! Pidele al rey que responda algunas y intentalo denuevo.' player_received_invites: '&bHas recibido %a/%m invitaciones.' town_revoke_invite: '&bLa ciudad de %s anuló tu invitación.' -town_revoke_invite_successful: '&bAnulaste una invitación para unirse a tu ciudad.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bLa ciudad ha recibido %a/%m invitaciones.' town_sent_invites: '&bLa ciudad ha enviado %a/%m invitaciones.' nation_revoke_invite: '&bLa nación de %s anuló tu invitación.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/es-EC.yml b/Towny/src/main/resources/lang/es-EC.yml index 85b2c2036c..2482c60154 100644 --- a/Towny/src/main/resources/lang/es-EC.yml +++ b/Towny/src/main/resources/lang/es-EC.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cDebes pertenecer a una ciudad para poder reclamar msg_err_must_belong_town: '&cDebes pertenecer a una ciudad.' msg_err_dont_belong_town: '&cNo perteneces a una ciudad.' msg_err_dont_belong_nation: '&bNo perteneces a una nación.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s no pertenece a tu nación.' msg_err_rect_auto: '&cSolo las ciudades y habitantes pueden usar auto.' msg_err_invalid_radius: '&cRadio inválido. Usa un número entero o ''auto''.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&b¡La nación ha emitido demasiadas sol msg_err_nation_has_too_many_requests: '&b¡La nación de %s tiene demasiadas solicitudes! Pidele al rey que responda algunas y intentalo denuevo.' player_received_invites: '&bHas recibido %a/%m invitaciones.' town_revoke_invite: '&bLa ciudad de %s anuló tu invitación.' -town_revoke_invite_successful: '&bAnulaste una invitación para unirse a tu ciudad.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bLa ciudad ha recibido %a/%m invitaciones.' town_sent_invites: '&bLa ciudad ha enviado %a/%m invitaciones.' nation_revoke_invite: '&bLa nación de %s anuló tu invitación.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/es-ES.yml b/Towny/src/main/resources/lang/es-ES.yml index 346b41852d..c2db5b5c8a 100644 --- a/Towny/src/main/resources/lang/es-ES.yml +++ b/Towny/src/main/resources/lang/es-ES.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cDebes pertenecer a una ciudad para claimear parcel msg_err_must_belong_town: '&cDebes pertenecer a una ciudad.' msg_err_dont_belong_town: '&cNo perteneces a una ciudad.' msg_err_dont_belong_nation: '&bNo perteneces a un país.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s no pertenece a tu pais' msg_err_rect_auto: '&cSolo las ciudades y los habitantes pueden usar ''auto''.' msg_err_invalid_radius: '&cRadio inválido. Use un número entero o ''auto''.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&bLa nación ha enviado demasiadas solic msg_err_nation_has_too_many_requests: '&bLa nación %s tiene demasiadas solicitudes, pide que rechacen algunas, antes de volver a intentarlo.' player_received_invites: '&bHas recibido %a/%m invitaciones.' town_revoke_invite: '&b%s, rechazó tu invitación de unión.' -town_revoke_invite_successful: '&bHas rechazado una invitación de unión a tu ciudad.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bLa ciudad ha recibido %a/%m invitaciones.' town_sent_invites: '&bLa ciudad ha enviado %a/%m invitaciones.' nation_revoke_invite: '&bLa nación %s, rechazó tu invitación de unión.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/es-MX.yml b/Towny/src/main/resources/lang/es-MX.yml index 0dd0fee25d..dfa11dab74 100644 --- a/Towny/src/main/resources/lang/es-MX.yml +++ b/Towny/src/main/resources/lang/es-MX.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cDebes pertenecer a una ciudad para poder reclamar msg_err_must_belong_town: '&cDebes pertenecer a una ciudad.' msg_err_dont_belong_town: '&cNo perteneces a una ciudad.' msg_err_dont_belong_nation: '&bNo perteneces a una nación.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s no pertenece a tu nación.' msg_err_rect_auto: '&cSolo las ciudades y habitantes pueden usar auto.' msg_err_invalid_radius: '&cRadio inválido. Usa un número entero o ''auto''.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&b¡La nación ha emitido demasiadas sol msg_err_nation_has_too_many_requests: '&b¡La nación de %s tiene demasiadas solicitudes! Pidele al rey que responda algunas y intentalo denuevo.' player_received_invites: '&bHas recibido %a/%m invitaciones.' town_revoke_invite: '&bLa ciudad de %s anuló tu invitación.' -town_revoke_invite_successful: '&bAnulaste una invitación para unirse a tu ciudad.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bLa ciudad ha recibido %a/%m invitaciones.' town_sent_invites: '&bLa ciudad ha enviado %a/%m invitaciones.' nation_revoke_invite: '&bLa nación de %s anuló tu invitación.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/es-UY.yml b/Towny/src/main/resources/lang/es-UY.yml index 85b2c2036c..2482c60154 100644 --- a/Towny/src/main/resources/lang/es-UY.yml +++ b/Towny/src/main/resources/lang/es-UY.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cDebes pertenecer a una ciudad para poder reclamar msg_err_must_belong_town: '&cDebes pertenecer a una ciudad.' msg_err_dont_belong_town: '&cNo perteneces a una ciudad.' msg_err_dont_belong_nation: '&bNo perteneces a una nación.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s no pertenece a tu nación.' msg_err_rect_auto: '&cSolo las ciudades y habitantes pueden usar auto.' msg_err_invalid_radius: '&cRadio inválido. Usa un número entero o ''auto''.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&b¡La nación ha emitido demasiadas sol msg_err_nation_has_too_many_requests: '&b¡La nación de %s tiene demasiadas solicitudes! Pidele al rey que responda algunas y intentalo denuevo.' player_received_invites: '&bHas recibido %a/%m invitaciones.' town_revoke_invite: '&bLa ciudad de %s anuló tu invitación.' -town_revoke_invite_successful: '&bAnulaste una invitación para unirse a tu ciudad.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bLa ciudad ha recibido %a/%m invitaciones.' town_sent_invites: '&bLa ciudad ha enviado %a/%m invitaciones.' nation_revoke_invite: '&bLa nación de %s anuló tu invitación.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/es-VE.yml b/Towny/src/main/resources/lang/es-VE.yml index 85b2c2036c..2482c60154 100644 --- a/Towny/src/main/resources/lang/es-VE.yml +++ b/Towny/src/main/resources/lang/es-VE.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cDebes pertenecer a una ciudad para poder reclamar msg_err_must_belong_town: '&cDebes pertenecer a una ciudad.' msg_err_dont_belong_town: '&cNo perteneces a una ciudad.' msg_err_dont_belong_nation: '&bNo perteneces a una nación.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s no pertenece a tu nación.' msg_err_rect_auto: '&cSolo las ciudades y habitantes pueden usar auto.' msg_err_invalid_radius: '&cRadio inválido. Usa un número entero o ''auto''.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&b¡La nación ha emitido demasiadas sol msg_err_nation_has_too_many_requests: '&b¡La nación de %s tiene demasiadas solicitudes! Pidele al rey que responda algunas y intentalo denuevo.' player_received_invites: '&bHas recibido %a/%m invitaciones.' town_revoke_invite: '&bLa ciudad de %s anuló tu invitación.' -town_revoke_invite_successful: '&bAnulaste una invitación para unirse a tu ciudad.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bLa ciudad ha recibido %a/%m invitaciones.' town_sent_invites: '&bLa ciudad ha enviado %a/%m invitaciones.' nation_revoke_invite: '&bLa nación de %s anuló tu invitación.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/fr-FR.yml b/Towny/src/main/resources/lang/fr-FR.yml index 23b992baaa..e324d8cc0c 100644 --- a/Towny/src/main/resources/lang/fr-FR.yml +++ b/Towny/src/main/resources/lang/fr-FR.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cVous devez appartenir à une ville afin d''annexer msg_err_must_belong_town: '&cVous devez appartenir à une ville.' msg_err_dont_belong_town: '&cVous n''appartenez pas à une ville.' msg_err_dont_belong_nation: '&bVous n''appartenez pas à une nation.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s n''appartient pas à votre nation.' msg_err_rect_auto: '&cUniquement les villes et les résidents peuvent utiliser ''auto''.' msg_err_invalid_radius: '&cRayon invalide. Utilisez un entier ou ''auto''.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&bLa nation a envoyé trop de demandes, msg_err_nation_has_too_many_requests: '&bLa nation %s a trop de demandes, demandez d''en refuser, avant d''inviter à nouveau.' player_received_invites: '&bVous avez reçu %a/%m invitations.' town_revoke_invite: '&bLa ville %s, a annulé votre invitation pour les rejoindre.' -town_revoke_invite_successful: '&bVous avez annulé avec succès une invitation à rejoindre votre ville.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bLa ville a reçu %a/%m invitations.' town_sent_invites: '&bLa ville a envoyé %a/%m invitations.' nation_revoke_invite: '&bLa nation %s, a annulé votre invitation pour les rejoindre.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/he-IL.yml b/Towny/src/main/resources/lang/he-IL.yml index bbb76b1f3c..1e60af5883 100644 --- a/Towny/src/main/resources/lang/he-IL.yml +++ b/Towny/src/main/resources/lang/he-IL.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cYou must belong to a town in order to claim plots. msg_err_must_belong_town: '&cYou must belong to a town.' msg_err_dont_belong_town: '&cYou don''t belong to a town.' msg_err_dont_belong_nation: '&bYou don''t belong to a nation.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s doesn''t belong to your nation.' msg_err_rect_auto: '&cOnly towns and residents can use auto.' msg_err_invalid_radius: '&cInvalid radius. Use an integer or ''auto''.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&bNation has sent too many requests, rev msg_err_nation_has_too_many_requests: '&bNation %s has too many requests, ask them to decline some, before requesting again.' player_received_invites: '&bYou have received %a/%m invites.' town_revoke_invite: '&bTown %s, revoked your invite to join them.' -town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bTown has received %a/%m invites.' town_sent_invites: '&bTown has sent %a/%m invites.' nation_revoke_invite: '&bNation %s, revoked your invite to join them.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/id-ID.yml b/Towny/src/main/resources/lang/id-ID.yml index 74afb41c2e..2eb7381200 100644 --- a/Towny/src/main/resources/lang/id-ID.yml +++ b/Towny/src/main/resources/lang/id-ID.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cKamu harus memiliki kota terlebih dahulu sebelum m msg_err_must_belong_town: '&cKamu harus memiliki kota terlebih dahulu.' msg_err_dont_belong_town: '&cKamu tidak memiliki kota.' msg_err_dont_belong_nation: '&bKamu tidak termasuk di negara manapun.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s Ini bukan milik negara mu.' msg_err_rect_auto: '&cHanya kota dan penduduk yang dapat menggunakan auto.' msg_err_invalid_radius: '&cRadius tidak benar. Gunakan bilangan bulat atau ''auto''.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&bNegara terlalu banyak mengirim permint msg_err_nation_has_too_many_requests: '&bNegara %s telalu banyak memiliki permintaan, tanyakan mereka untuk menolak beberapa, sebelum mencoba kembali.' player_received_invites: '&bKamu telah menerima %a/%m undangan.' town_revoke_invite: '&bKota %s, telah mencaut undangan yang di kirim ke kamu.' -town_revoke_invite_successful: '&bBerhasil mencabut undangan untuk bergabung ke kota.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bKota mendapatkan %a/%m undangan.' town_sent_invites: '&bKota telah mengirimkan %a/%m undangan.' nation_revoke_invite: '&bNegara %s, mencabut undangan yang mereka kirim ke kota mu.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/it-IT.yml b/Towny/src/main/resources/lang/it-IT.yml index 1e35289ed9..733fa97174 100644 --- a/Towny/src/main/resources/lang/it-IT.yml +++ b/Towny/src/main/resources/lang/it-IT.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cDevi appartenere a una città per poter claimare l msg_err_must_belong_town: '&cDevi appartenere a una città.' msg_err_dont_belong_town: '&cNon appartieni a una città.' msg_err_dont_belong_nation: '&bNon appartieni a una nazione.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s non appartiene alla tua nazione.' msg_err_rect_auto: '&cSolo le città e i residenti possono usare auto.' msg_err_invalid_radius: '&cRaggio non valido. Usa un numero intero o ''auto''.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&bLa Nazione ha inviato troppe richieste msg_err_nation_has_too_many_requests: '&bLa Nazione %s ha ricevuto troppe richieste, chiedi di annullarne qualcuna, prima di invitarli di nuovo.' player_received_invites: '&bHai ricevuto %a/%m inviti.' town_revoke_invite: '&bLa Città %s, ha annullato il loro invito ad entrare da loro.' -town_revoke_invite_successful: '&bHai annullato un invito ad entrare nella tua Città.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bLa Città ha ricevuto %a/%m inviti.' town_sent_invites: '&bLa Città ha inviato %a/%m inviti.' nation_revoke_invite: '&bLa Nazione %s, ha annullato il loro invito ad entrare da loro.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/ja-JP.yml b/Towny/src/main/resources/lang/ja-JP.yml index a2c0250980..04aa85ae6b 100644 --- a/Towny/src/main/resources/lang/ja-JP.yml +++ b/Towny/src/main/resources/lang/ja-JP.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&c土地を請求するためには、町に所属 msg_err_must_belong_town: '&cあなたは町に所属している必要があります。' msg_err_dont_belong_town: '&cあなたは町に所属していません。' msg_err_dont_belong_nation: '&bあなたは国に属していません。' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s はあなたの国に属していません。' msg_err_rect_auto: '&cautoは町や住民のみ利用できます。' msg_err_invalid_radius: '&cは無効な半径です。整数または ''auto'' を使用してください。' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&b送信した招待が多すぎます msg_err_nation_has_too_many_requests: '&b%sは招待が多すぎるため、しばらくしてから再度、送信してください。' player_received_invites: '&b%a/%mの招待を受け取りました。' town_revoke_invite: '&b%sは、あなたの招待を削除しました。' -town_revoke_invite_successful: '&bあなたの町への招待を削除しました。' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&b%a/%mの招待を受け取りました。' town_sent_invites: '&b%a/%mの招待を受け取りました。' nation_revoke_invite: '&b%sは、あなたの招待を削除しました。' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/ko-KR.yml b/Towny/src/main/resources/lang/ko-KR.yml index a881a5beed..463d8c232a 100644 --- a/Towny/src/main/resources/lang/ko-KR.yml +++ b/Towny/src/main/resources/lang/ko-KR.yml @@ -45,7 +45,7 @@ help_0: '타우니 도움말' help_1: '다음 명령어를 사용해보며 타우니에 대해 배워보세요.' help_2: '도시 내 채팅' help_3: '국가 내 채팅' -help_4: 'Resident command help.' +help_4: '' help_5: 'Town command help.' help_6: 'Nation command help.' help_7: 'Plot command help.' @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&c귀하는 개인 토지를 점유하기 위해 마 msg_err_must_belong_town: '&c마을에 속해 있어야 합니다.' msg_err_dont_belong_town: '&c마을에 속해 있지 않습니다.' msg_err_dont_belong_nation: '&b국가에 속해 있지 않습니다.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s은(는) 귀하의 국가에 속해 있지 않습니다.' msg_err_rect_auto: '&c오직 마을과 주민만 "자동"을 사용 할 수 있습니다.' msg_err_invalid_radius: '&c잘못된 거리입니다. 정수를 입력하거나 자동을 사용하세요.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&b국가가 너무 많은 요청을 전 msg_err_nation_has_too_many_requests: '&b국가 %s에는 너무 많은 요청이 있습니다. 다시 요청하기 전에 몇몇 요청을 취소하도록 요청하세요.' player_received_invites: '&b귀하는 %a/%m 초대를 수신하였습니다.' town_revoke_invite: '&b마을 %s이(가) 초대를 취소하였습니다.' -town_revoke_invite_successful: '&b마을 초대를 성공적으로 취소하였습니다.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&b마을이 %a/%m 초대를 수신하였습니다.' town_sent_invites: '&b마을에서 %a/%m 초대를 전송하였습니다.' nation_revoke_invite: '&b국가 %s이(가) 초대를 취소하였습니다.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/lol-US.yml b/Towny/src/main/resources/lang/lol-US.yml index af31d7b183..76ae7baa10 100644 --- a/Towny/src/main/resources/lang/lol-US.yml +++ b/Towny/src/main/resources/lang/lol-US.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cYou must belong to a town in order to claim plots. msg_err_must_belong_town: '&cYou must belong to a town.' msg_err_dont_belong_town: '&cYou don''t belong to a town.' msg_err_dont_belong_nation: '&bYou don''t belong to a nation.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s doesn''t belong to your nation.' msg_err_rect_auto: '&cOnly towns and residents can use auto.' msg_err_invalid_radius: '&cInvalid radius. Use an integer or ''auto''.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&bNation has sent too many requests, rev msg_err_nation_has_too_many_requests: '&bNation %s has too many requests, ask them to decline some, before requesting again.' player_received_invites: '&bYou have received %a/%m invites.' town_revoke_invite: '&bTown %s, revoked your invite to join them.' -town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bTown has received %a/%m invites.' town_sent_invites: '&bTown has sent %a/%m invites.' nation_revoke_invite: '&bNation %s, revoked your invite to join them.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/lt-LT.yml b/Towny/src/main/resources/lang/lt-LT.yml index 2fb71d5f68..b5711c5111 100644 --- a/Towny/src/main/resources/lang/lt-LT.yml +++ b/Towny/src/main/resources/lang/lt-LT.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cJūs turite priklausyti miestui, kad galėtumėte msg_err_must_belong_town: '&cJūs turite priklausyti miestui.' msg_err_dont_belong_town: '&cJūs nepriklausote miestui.' msg_err_dont_belong_nation: '&bJūs nepriklausote valstybei.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s nepriklauso Jūsų valstybei.' msg_err_rect_auto: '&cAutomatiniu užėmimu gali naudotis tik miestai ir jų gyventojai.' msg_err_invalid_radius: '&cNetinkamas spindulys. Naudokite sveikąjį skaičių arba „auto“.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&bValstybė turi per daug prašymų, at msg_err_nation_has_too_many_requests: '&bValstybė %s turi per daug prašymų, paprašykite jų atmesti keletą prieš Jums išsiunčiant prašymą iš naujo.' player_received_invites: '&bJūs gavote %a/%m pakvietimų.' town_revoke_invite: '&bMiestas %s atšaukė Jūsų pakvietimą prie jų prisijungti.' -town_revoke_invite_successful: '&bJūs sėkmingai atšaukėte pakvietimą prisijungti prie Jūsų miesto.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bMiestas gavo %a/%m pakvietimų.' town_sent_invites: '&bMiestas išsiuntė %a/%m pakvietimų.' nation_revoke_invite: '&bValstybė %s atšaukė Jūsų pakvietimą prie jų prisijungti.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/lzh.yml b/Towny/src/main/resources/lang/lzh.yml index 655b3db3bb..5d35ed6258 100644 --- a/Towny/src/main/resources/lang/lzh.yml +++ b/Towny/src/main/resources/lang/lzh.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&你必須加入市鎮才能取得這個地段 ' msg_err_must_belong_town: '&c你必須是一個市鎮居民 ' msg_err_dont_belong_town: '&c你不屬於一個市鎮 ' msg_err_dont_belong_nation: '&b你不屬於一個城邦的臣民 ' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s不屬於你的城邦 ' msg_err_rect_auto: '&c只有市鎮及其居民才能使用 auto ' msg_err_invalid_radius: '&c無效半徑 輸入整數或 auto ' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&b城邦已經發出了太多的要求 msg_err_nation_has_too_many_requests: '&b城邦%s有太多的邀請,需要他們拒絕一些請求,然後再進行邀請 ' player_received_invites: '&b你已經收到%a/%m 邀請 ' town_revoke_invite: '&b市鎮%s,撤銷了你的加入邀請 ' -town_revoke_invite_successful: '&b你已成功撤銷邀請你加入的市鎮' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&b市鎮已收到%a/%m 邀請 ' town_sent_invites: '&b市鎮已發送%a/%m 邀請 ' nation_revoke_invite: '&b城邦%s,撤銷了你的邀請以加入 ' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/nl-NL.yml b/Towny/src/main/resources/lang/nl-NL.yml index b71c446d40..5e7eace0c2 100644 --- a/Towny/src/main/resources/lang/nl-NL.yml +++ b/Towny/src/main/resources/lang/nl-NL.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cJe moet tot een stad behoren om plots te claimen.' msg_err_must_belong_town: '&cJe moet tot een stad behoren.' msg_err_dont_belong_town: '&cJe behoort niet tot een stad.' msg_err_dont_belong_nation: '&bJe behoort niet tot een natie.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s behoort niet tot jouw natie.' msg_err_rect_auto: '&cAlleen steden in inwoners kunnen auto gebruiken.' msg_err_invalid_radius: '&cOngeldige radius. Gebruik een geheel getal of ''auto''.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&bNation has sent too many requests, rev msg_err_nation_has_too_many_requests: '&bNation %s has too many requests, ask them to decline some, before requesting again.' player_received_invites: '&bYou have received %a/%m invites.' town_revoke_invite: '&bTown %s, revoked your invite to join them.' -town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bTown has received %a/%m invites.' town_sent_invites: '&bTown has sent %a/%m invites.' nation_revoke_invite: '&bNation %s, revoked your invite to join them.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/no-NO.yml b/Towny/src/main/resources/lang/no-NO.yml index 0df933a092..c3755986fd 100644 --- a/Towny/src/main/resources/lang/no-NO.yml +++ b/Towny/src/main/resources/lang/no-NO.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cDu må tilhøre en by for å kreve tomter.' msg_err_must_belong_town: '&cDu må høre til en by.' msg_err_dont_belong_town: '&cDu tilhører ikke en by.' msg_err_dont_belong_nation: '&bDu tilhører ikke en nasjon.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s tilhører ikke din nasjon.' msg_err_rect_auto: '&cBare byer og innbyggere kan bruke auto.' msg_err_invalid_radius: '&cUgyldig radius. Bruk et heltall eller ''auto''.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&bNasjon har sendt for mange forespørsl msg_err_nation_has_too_many_requests: '&bNation %s has too many requests, ask them to decline some, before inviting again.' player_received_invites: '&bDu har mottatt %a/%m invitasjoner.' town_revoke_invite: '&bTown %s, revoked your invite to join them' -town_revoke_invite_successful: '&bDu har opphevet en invitasjon til å bli med i byen din.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bBy har mottatt %a/%m invitasjoner.' town_sent_invites: '&bByen har sendt %a/%m invitasjoner.' nation_revoke_invite: '&bNasjon %s, opphevet invitasjonen din til å bli med dem.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/pl-PL.yml b/Towny/src/main/resources/lang/pl-PL.yml index 7d4d6704cc..769b4e662d 100644 --- a/Towny/src/main/resources/lang/pl-PL.yml +++ b/Towny/src/main/resources/lang/pl-PL.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cMusisz należeć do miasta, aby móc pozyskiwać d msg_err_must_belong_town: '&cMusisz należeć do miasta.' msg_err_dont_belong_town: '&cNie należysz do żadnego miasta.' msg_err_dont_belong_nation: '&bNie należysz do nacji.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s nie należy do twojej nacji.' msg_err_rect_auto: '&cTylko miasta i mieszkańcy mogą z tego skorzystać.' msg_err_invalid_radius: '&cNieprawidłowy promień. Użyj liczby całkowitej lub trybu "auto".' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&bNacja wysłała zbyt dużo zaproszeń, msg_err_nation_has_too_many_requests: '&bNacja %s ma zbyt dużo zaproszeń. Poproś ją o odrzucenie paru.' player_received_invites: '&bOtrzymałeś %a/%m zaproszeń.' town_revoke_invite: '&bMiasto %s odrzuciło twoją prośbę o dołączenie.' -town_revoke_invite_successful: '&bUnieważniłeś zaproszenie do dołączenia do twojego miasta.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bMiasto otrzymało %a/%m zaproszeń.' town_sent_invites: '&bMiasto wysłało %a/%m zaproszeń.' nation_revoke_invite: '&bNacja %s odrzuciła Twoje propozycję dołączenie do nich.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/pt-BR.yml b/Towny/src/main/resources/lang/pt-BR.yml index 93307daf34..02ebdbf9b4 100644 --- a/Towny/src/main/resources/lang/pt-BR.yml +++ b/Towny/src/main/resources/lang/pt-BR.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cVocê deve pertencer a uma cidade para reivindicar msg_err_must_belong_town: '&cVocê deve pertencer a uma cidade.' msg_err_dont_belong_town: '&cVocê não pertence a nenhuma cidade.' msg_err_dont_belong_nation: '&bVocê não pertence a nenhuma nação.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s não pertence à sua nação.' msg_err_rect_auto: '&cApenas cidades e residentes podem usar auto.' msg_err_invalid_radius: '&cRaio. Use um número inteiro ou ''auto''.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&A nação já enviou demasiados pedidos msg_err_nation_has_too_many_requests: '&bA nação %s tem demasiados pedidos de aliança, pergunte-lhes para recusar alguns antes de convidar outra vez.' player_received_invites: '&bVocê recebeu %a/%m convites.' town_revoke_invite: '&bA cidade %s cancelou o convite para você entrar.' -town_revoke_invite_successful: '&bVocê cancelou um convite para entrarem na sua cidade com sucesso.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bA cidade recebeu %a/%m convites.' town_sent_invites: '&bA cidade recebeu %a/%m convites.' nation_revoke_invite: '&bA nação %s cancelou o convite para você entrar.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/pt-PT.yml b/Towny/src/main/resources/lang/pt-PT.yml index 462ba6d4c1..a3870171d4 100644 --- a/Towny/src/main/resources/lang/pt-PT.yml +++ b/Towny/src/main/resources/lang/pt-PT.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cTens de pertencer a uma cidade para reivindicar te msg_err_must_belong_town: '&cTens de pertencer a uma cidade.' msg_err_dont_belong_town: '&cNão pertences a nenhuma cidade.' msg_err_dont_belong_nation: '&bNão pertences a nenhuma nação.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s não pertence à tua nação.' msg_err_rect_auto: '&cApenas cidades e habitantes podem usar "auto".' msg_err_invalid_radius: '&cRaio inválido. Usa um número inteiro ou "auto".' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&A nação já enviou demasiados pedidos msg_err_nation_has_too_many_requests: '&bA nação %s tem demasiados pedidos de aliança, pede-lhes para recusar alguns antes de enviares outra vez.' player_received_invites: '&bRecebeste %a/%m convites.' town_revoke_invite: '&bA cidade %s cancelou o convite para te juntares a eles.' -town_revoke_invite_successful: '&bCancelaste o convite para entrarem na tua cidade com êxito.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bA cidade recebeu %a/%m convites.' town_sent_invites: '&bA cidade enviou %a/%m convites.' nation_revoke_invite: '&bA nação %s cancelou o convite para te juntares a eles.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/ro-RO.yml b/Towny/src/main/resources/lang/ro-RO.yml index 4b7bca046d..c24966de02 100644 --- a/Towny/src/main/resources/lang/ro-RO.yml +++ b/Towny/src/main/resources/lang/ro-RO.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cYou must belong to a town in order to claim plots. msg_err_must_belong_town: '&cYou must belong to a town.' msg_err_dont_belong_town: '&cYou don''t belong to a town.' msg_err_dont_belong_nation: '&bYou don''t belong to a nation.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s doesn''t belong to your nation.' msg_err_rect_auto: '&cOnly towns and residents can use auto.' msg_err_invalid_radius: '&cInvalid radius. Use an integer or ''auto''.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&bNation has sent too many requests, rev msg_err_nation_has_too_many_requests: '&bNation %s has too many requests, ask them to decline some, before requesting again.' player_received_invites: '&bYou have received %a/%m invites.' town_revoke_invite: '&bTown %s, revoked your invite to join them.' -town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bTown has received %a/%m invites.' town_sent_invites: '&bTown has sent %a/%m invites.' nation_revoke_invite: '&bNation %s, revoked your invite to join them.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/ru-RU.yml b/Towny/src/main/resources/lang/ru-RU.yml index 0aad25802c..aa78513f4c 100644 --- a/Towny/src/main/resources/lang/ru-RU.yml +++ b/Towny/src/main/resources/lang/ru-RU.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cВы должны быть в городе, что msg_err_must_belong_town: '&cВы должны быть жителем города.' msg_err_dont_belong_town: '&cУ вас нет родного города.' msg_err_dont_belong_nation: '&bУ вас нет нации.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s не принадлежит к нации' msg_err_rect_auto: '&cТолько города и горожане могут использовать авто режим.' msg_err_invalid_radius: '&cНеверный радиус. Используйте целое число или ''auto''.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&bНация отправила слиш msg_err_nation_has_too_many_requests: '&bНация %s имеет слишком много запросов. Попросите её отказаться от некоторых, прежде чем снова приглашать.' player_received_invites: '&bВы получили %a/%m приглашений.' town_revoke_invite: '&bГород %s, отозвал ваше приглашение присоединиться к ним' -town_revoke_invite_successful: '&bВы успешно отозвали приглашение присоединиться к вашему городу.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bГород получил %a/%m приглашений.' town_sent_invites: '&bГород отправил %a/%m приглашений.' nation_revoke_invite: '&bНация %s, отозвала ваше приглашение присоединиться к ним.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/sq-AL.yml b/Towny/src/main/resources/lang/sq-AL.yml index 02b98c173a..d0fc92d817 100644 --- a/Towny/src/main/resources/lang/sq-AL.yml +++ b/Towny/src/main/resources/lang/sq-AL.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cYou must belong to a town in order to claim plots. msg_err_must_belong_town: '&cYou must belong to a town.' msg_err_dont_belong_town: '&cYou don''t belong to a town.' msg_err_dont_belong_nation: '&bYou don''t belong to a nation.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s doesn''t belong to your nation.' msg_err_rect_auto: '&cOnly towns and residents can use auto.' msg_err_invalid_radius: '&cInvalid radius. Use an integer or ''auto''.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&bNation has sent too many requests, rev msg_err_nation_has_too_many_requests: '&bNation %s has too many requests, ask them to decline some, before requesting again.' player_received_invites: '&bYou have received %a/%m invites.' town_revoke_invite: '&bTown %s, revoked your invite to join them.' -town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bTown has received %a/%m invites.' town_sent_invites: '&bTown has sent %a/%m invites.' nation_revoke_invite: '&bNation %s, revoked your invite to join them.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/sr-CS.yml b/Towny/src/main/resources/lang/sr-CS.yml index cd849b0b5a..4371aa7800 100644 --- a/Towny/src/main/resources/lang/sr-CS.yml +++ b/Towny/src/main/resources/lang/sr-CS.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cMorate pripadati nekom gradu kako biste claim-oval msg_err_must_belong_town: '&cMorate pripadati nekom gradu.' msg_err_dont_belong_town: '&cNe pripadate nijednom gradu.' msg_err_dont_belong_nation: '&bNe pripadate nijednoj naciji.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s ne pripada Vašoj naciji.' msg_err_rect_auto: '&cSamo gradovi i stanovnici mogu da koriste ''auto''.' msg_err_invalid_radius: '&cNevažeći poluprečnik. Koristite celi broj ili ''auto''.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&bNacija je poslala previše zahteva, po msg_err_nation_has_too_many_requests: '&bNacija %s ima previše zahteva, pitajte ih da odbiju neke pre nego što ponovo zatražite.' player_received_invites: '&bPrimili ste %a/%m poziva.' town_revoke_invite: '&bGrad %s je povukao poziv da mu se pridružite.' -town_revoke_invite_successful: '&bUspešno ste povukli poziv za ulazak u Vaš grad.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bGrad je primio %a/%m poziva.' town_sent_invites: '&bGrad je poslao %a/%m poziva.' nation_revoke_invite: '&bNacija %s je povukla poziv da im se pridružite.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/sv-SE.yml b/Towny/src/main/resources/lang/sv-SE.yml index 03ada153d5..302d9e67de 100644 --- a/Towny/src/main/resources/lang/sv-SE.yml +++ b/Towny/src/main/resources/lang/sv-SE.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cDu måste tillhöra en stad för att kunna köpa m msg_err_must_belong_town: '&cDu måste tillhöra en stad.' msg_err_dont_belong_town: '&cDu tillhör inte en stad.' msg_err_dont_belong_nation: '&bDu tillhör inte en nation.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s tillhör inte din nation.' msg_err_rect_auto: '&cEndast städer och invånare kan använda auto.' msg_err_invalid_radius: '&cOgiltig radie. Använd ett heltal eller ''auto''.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&bNationen har skickat för många förf msg_err_nation_has_too_many_requests: '&bNationen %s har för många förfrågningar, be dem att avböja några, innan du begär igen.' player_received_invites: '&bDu har fått %a/%m inbjudningar.' town_revoke_invite: '&bStaden %s, återkallade din inbjudan att gå med i den.' -town_revoke_invite_successful: '&bDu har framgångsrikt återkallat en inbjudan att gå med i din stad.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bStaden har fått %a/%m inbjudningar.' town_sent_invites: '&bStaden har skickat %a/%m inbjudningar.' nation_revoke_invite: '&bNationen %s, återkallade din inbjudan om att ansluta till dem.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/th-TH.yml b/Towny/src/main/resources/lang/th-TH.yml index 621daff82f..4c2fa91c66 100644 --- a/Towny/src/main/resources/lang/th-TH.yml +++ b/Towny/src/main/resources/lang/th-TH.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: 'คุณต้องอยู่ใน Town เพ msg_err_must_belong_town: 'คุณต้องอยู่ใน Town.' msg_err_dont_belong_town: '&cคุณไม่ได้อยู่ใน Town.' msg_err_dont_belong_nation: '&bคุณไม่ได้เป็นของ Nation.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s ไม่ได้เป็นของ Nation ของคุณ.' msg_err_rect_auto: '&cเฉพาะ Town และ Residents เท่านั้นที่สามารถใช้อัตโนมัติได้.' msg_err_invalid_radius: '&cรัศมีไม่ถูกต้อง ใช้จำนวนเต็มหรืออัตโนมัติ.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&bNation ส่งคำขอมาก msg_err_nation_has_too_many_requests: '&bNation %s มีคำขอมากเกินไป ขอให้พวกเขาปฏิเสธบางคำขอ ก่อนที่คุณจะขออีกครั้ง.' player_received_invites: '&bคุณได้รับ %a/%m คำเชิญ.' town_revoke_invite: '&bTown %s, ยกเลิกคำขอให้เข้าร่วมของคุณ.' -town_revoke_invite_successful: '&bคุณได้ยกเลิกคำเชิญเข้าร่วม Town ของคุณสำเร็จแล้ว.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bTown ได้รับ %a/%m คำเชิญ.' town_sent_invites: '&bTown ได้ส่ง %a/%m คำเชิญ.' nation_revoke_invite: '&bNation %s, ยกเลิกคำเชิญเข้าร่วมของคุณ.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/tl-PH.yml b/Towny/src/main/resources/lang/tl-PH.yml index 47cf3a5278..4a530d611a 100644 --- a/Towny/src/main/resources/lang/tl-PH.yml +++ b/Towny/src/main/resources/lang/tl-PH.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cIkaw ay dapat kasapi sa isang bayan para makapagku msg_err_must_belong_town: '&cIkaw ay dapat kasapi sa isang bayan.' msg_err_dont_belong_town: '&cHindi ka kasapi nang anumang bayan.' msg_err_dont_belong_nation: '&bIkaw hindi kasapi nang anumang nasyon.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s ay hindi kasapi sa iyong nasyon.' msg_err_rect_auto: '&cMga bayan at mga residente lamang ang pwede gumamit nito.' msg_err_invalid_radius: '&cHindi wasto ang radius. Gumamit nang integer o kaya nang ''auto''.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&bNagpadala ang bansa ng napakaraming ka msg_err_nation_has_too_many_requests: 'Masyadong maraming kahilingan ang Bansa %s, hilingin sa kanila na tanggihan ang ilan, bago humiling muli.' player_received_invites: '&bNakatanggap ka ng %a/%m imbitasyon.' town_revoke_invite: '&bBinawi ng Bayan ng %s ang iyong imbitasyon na sumali sa kanila.' -town_revoke_invite_successful: '&bMatagumpay mong binawi ang isang imbitasyon na sumali sa iyong bayan.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bNakatanggap ang bayan ng %a/%m imbitasyon.' town_sent_invites: '&bNagpadala ang bayan ng %a/%m imbitasyon.' nation_revoke_invite: '&bBinawi ang Bansang %s ang iyong imbitasyon na sumali sa kanila.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/tr-TR.yml b/Towny/src/main/resources/lang/tr-TR.yml index 261ec831e9..4fadf1a44b 100644 --- a/Towny/src/main/resources/lang/tr-TR.yml +++ b/Towny/src/main/resources/lang/tr-TR.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cArsa talep etmek için bir şehire ait olmalısın msg_err_must_belong_town: '&cBir şehire ait olmalısın.' msg_err_dont_belong_town: '&cBir şehire ait değilsin.' msg_err_dont_belong_nation: '&bBir ulusa ait değilsin.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s ulusunuza ait değil.' msg_err_rect_auto: '&cOtomobili yalnızca şehirler ve sakinler kullanabilir.' msg_err_invalid_radius: '&cGeçersiz yarıçap. Bir tam sayı veya "otomatik" kullanın.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&bÜlke çok fazla istek gönderdi, tekr msg_err_nation_has_too_many_requests: '&b%s ülkesinin çok fazla isteği var, tekrar istemeden önce bazılarını reddetmelerini isteyin.' player_received_invites: '&b%a/%m davet aldınız.' town_revoke_invite: '&bKasaba %s, onlara katılma davetinizi iptal etti.' -town_revoke_invite_successful: '&bKasabanıza katılma davetini başarıyla geri aldınız.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bKasaba %a/%m davet aldı.' town_sent_invites: '&bKasaba% a/%m davet gönderdi.' nation_revoke_invite: '&b%s ülkesi, onlara katılma davetinizi iptal etti.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/uk-UA.yml b/Towny/src/main/resources/lang/uk-UA.yml index 9bfe7fcf5a..c369b24f88 100644 --- a/Towny/src/main/resources/lang/uk-UA.yml +++ b/Towny/src/main/resources/lang/uk-UA.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cВи повинні бути в місті, щоб msg_err_must_belong_town: '&cВи маєте бути жителем міста.' msg_err_dont_belong_town: '&cВи не належите до міста.' msg_err_dont_belong_nation: '&bВи не належите до нації.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s не належить до нації.' msg_err_rect_auto: '&cТільки міста та городяни можуть використовувати авто режим.' msg_err_invalid_radius: '&cПомилковий радіус. Вкажіть ціле число або ''auto''.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&bНація надіслала зана msg_err_nation_has_too_many_requests: '&bНація %s має занадто багато запрошень, попросіть відхилити деякі з них, перед тим як спробувати знову.' player_received_invites: '&bВи отримали %a/%m повідомлень.' town_revoke_invite: '&bМісто %s відхилило ваше запрошення приєднатися до них.' -town_revoke_invite_successful: '&bВи успішно відкликали запрошення приєднатися до вашого міста.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bМісто отримало %a/%m запрошень.' town_sent_invites: '&bМісто відправило %a/%m запрошень.' nation_revoke_invite: '&bНація %s- відкликала ваше запрошення приєднатися до них.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/vi-VN.yml b/Towny/src/main/resources/lang/vi-VN.yml index dbcf780ab6..4dea0c2867 100644 --- a/Towny/src/main/resources/lang/vi-VN.yml +++ b/Towny/src/main/resources/lang/vi-VN.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&cYou must belong to a town in order to claim plots. msg_err_must_belong_town: '&cYou must belong to a town.' msg_err_dont_belong_town: '&cYou don''t belong to a town.' msg_err_dont_belong_nation: '&bYou don''t belong to a nation.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s doesn''t belong to your nation.' msg_err_rect_auto: '&cOnly towns and residents can use auto.' msg_err_invalid_radius: '&cInvalid radius. Use an integer or ''auto''.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&bNation has sent too many requests, rev msg_err_nation_has_too_many_requests: '&bNation %s has too many requests, ask them to decline some, before requesting again.' player_received_invites: '&bYou have received %a/%m invites.' town_revoke_invite: '&bTown %s, revoked your invite to join them.' -town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town.' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&bTown has received %a/%m invites.' town_sent_invites: '&bTown has sent %a/%m invites.' nation_revoke_invite: '&bNation %s, revoked your invite to join them.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/zh-CN.yml b/Towny/src/main/resources/lang/zh-CN.yml index 71c9e4b09d..8fd633cb79 100644 --- a/Towny/src/main/resources/lang/zh-CN.yml +++ b/Towny/src/main/resources/lang/zh-CN.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&你必须加入城镇才能声明这块土地.' msg_err_must_belong_town: '&c你必须是一个城镇居民.' msg_err_dont_belong_town: '&c你不属于一个城镇.' msg_err_dont_belong_nation: '&b你不属于一个国家的臣民.' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s不属于你的国家.' msg_err_rect_auto: '&c只有城镇及其居民才能使用 auto.' msg_err_invalid_radius: '&c无效半径. 输入整数或 auto.' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&b国家已经发出了太多的要求 msg_err_nation_has_too_many_requests: '&b国家 %s 有太多的邀请, 需要他们拒绝一些请求, 然后再进行邀请.' player_received_invites: '&b你已经收到 %a/%m 邀请.' town_revoke_invite: '&b城镇 %s, 撤销了你的邀请加入.' -town_revoke_invite_successful: '&b你已成功撤销邀请你加入的城镇' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&b城镇已收到 %a/%m 邀请.' town_sent_invites: '&b城镇已发送 %a/%m 邀请.' nation_revoke_invite: '&b国家 %s, 撤销了您的邀请以加入.' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." diff --git a/Towny/src/main/resources/lang/zh-TW.yml b/Towny/src/main/resources/lang/zh-TW.yml index d73ee04c22..9248007130 100644 --- a/Towny/src/main/resources/lang/zh-TW.yml +++ b/Towny/src/main/resources/lang/zh-TW.yml @@ -622,6 +622,8 @@ msg_err_not_in_town_claim: '&你必須加入市鎮才能取得這個地段 ' msg_err_must_belong_town: '&c你必須是一個市鎮居民 ' msg_err_dont_belong_town: '&c你不屬於一個市鎮 ' msg_err_dont_belong_nation: '&b你不屬於一個城邦的臣民 ' +msg_err_already_belong_nation: '&bYou already belong to a nation.' +msg_err_town_already_belong_nation: '&b%s already belongs to a nation: %s.' msg_err_not_same_nation: '&b%s不屬於你的城邦 ' msg_err_rect_auto: '&c只有市鎮及其居民才能使用 auto ' msg_err_invalid_radius: '&c無效半徑 輸入整數或 auto ' @@ -797,7 +799,7 @@ msg_err_nation_sent_too_many_requests: '&b城邦已經發出了太多的要求 msg_err_nation_has_too_many_requests: '&b城邦%s有太多的邀請,需要他們拒絕一些請求,然後再進行邀請 ' player_received_invites: '&b你已經收到%a/%m 邀請 ' town_revoke_invite: '&b市鎮%s,撤銷了你的加入邀請 ' -town_revoke_invite_successful: '&b你已成功撤銷邀請你加入的市鎮' +town_revoke_invite_successful: '&bYou have successfully revoked an invite to join your town sent to %s.' town_received_invites: '&b市鎮已收到%a/%m 邀請 ' town_sent_invites: '&b市鎮已發送%a/%m 邀請 ' nation_revoke_invite: '&b城邦%s,撤銷了你的邀請以加入 ' @@ -2092,3 +2094,5 @@ msg_err_cannot_begin_town_in_this_biome: "You cannot start a town in this biome. msg_err_cannot_overclaim_this_town_because_they_arent_your_enemy: "You are not able to overclaim this town because your nation does not consider their nation an enemy." msg_err_unable_to_command_outside_of_town: 'You cannot use that command outside of your town.' msg_err_unable_to_use_bank_outside_bank_plot_no_homeblock: 'You cannot use that command outside of a bank plot.' +msg_err_you_cannot_outlaw_your_mayor: "You cannot outlaw your town's mayor." +msg_err_you_cannot_outlaw_because_of_rank: "You cannot outlaw %s because of a town rank they hold." From 0aca4f1def9704959777624c8d86892e3654d029 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Tue, 16 Jan 2024 11:08:14 -0600 Subject: [PATCH 71/74] - New Config Option: claiming.new_town_bonus_claims - Default: 0 - An amount of additional townblocks that a town will receive when it is first created, in addition to any amount given via the town_block_ratio or town_levels. - As an example: This can be used to add 10 townblocks to a town when it is made so the borders can be grown a bit more before the mayor has to seek out residents. --- Towny/src/main/resources/ChangeLog.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index f2fc49afdf..41adb7a063 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9458,4 +9458,10 @@ v0.92.0.11: - Refactor nation adding towns in the NationCommand class. 0.100.1.3: - Refactor townAdd method to better handle adding and revoking invites. - - Fix not being able to add towns to nations when the residents-per-nation setting is 0. \ No newline at end of file + - Fix not being able to add towns to nations when the residents-per-nation setting is 0. + - Add a configurable amount of bonus townblocks given to new towns. + - Closes #7195. + - New Config Option: claiming.new_town_bonus_claims + - Default: 0 + - An amount of additional townblocks that a town will receive when it is first created, in addition to any amount given via the town_block_ratio or town_levels. + - As an example: This can be used to add 10 townblocks to a town when it is made so the borders can be grown a bit more before the mayor has to seek out residents. \ No newline at end of file From 18ce06b388ef3341a4db609f3421a5ddbbe517f4 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Thu, 18 Jan 2024 09:31:27 -0600 Subject: [PATCH 72/74] Refactor max residents per town code into TownUtil accessed via a new Town method. (#7197) * Refactor max residents per town code into TownUtil accessed via a new Town method. Also catches some uses of nations max residents. Will be ready after some test classes are written! * Add PopulationTests.java, bump MockBukkit and Spigot. Tests would not run because MockBukkit knows about short_grass or w/e its called. TownyPlayerListener had a test change from being done on the non-existant GRASS changed to DIRT which will hopefully remain named DIRT until forever. * Maybe fix the test on GH's side. * Clean up and change town method name to be better. --- Towny/pom.xml | 4 +- .../bukkit/towny/TownySettings.java | 4 +- .../bukkit/towny/command/InviteCommand.java | 2 +- .../bukkit/towny/command/NationCommand.java | 18 +- .../bukkit/towny/command/PlotCommand.java | 7 +- .../bukkit/towny/command/TownCommand.java | 17 +- .../towny/listeners/TownyPlayerListener.java | 2 +- .../palmergames/bukkit/towny/object/Town.java | 23 ++- .../bukkit/towny/utils/NationUtil.java | 2 +- .../bukkit/towny/utils/TownUtil.java | 8 + .../bukkit/towny/test/PopulationTests.java | 195 ++++++++++++++++++ 11 files changed, 250 insertions(+), 32 deletions(-) create mode 100644 Towny/src/test/java/com/palmergames/bukkit/towny/test/PopulationTests.java diff --git a/Towny/pom.xml b/Towny/pom.xml index 2a202b6c25..5d62d8138f 100644 --- a/Towny/pom.xml +++ b/Towny/pom.xml @@ -84,7 +84,7 @@ org.spigotmc spigot-api - 1.20.2-R0.1-SNAPSHOT + 1.20.4-R0.1-SNAPSHOT provided @@ -256,7 +256,7 @@ com.github.seeseemelk MockBukkit-v1.20 - 3.60.0 + 3.65.0 test diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/TownySettings.java b/Towny/src/main/java/com/palmergames/bukkit/towny/TownySettings.java index 3c37faee26..a57e00ddbc 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/TownySettings.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/TownySettings.java @@ -2514,7 +2514,9 @@ public static int getMaxResidentsForTown(Town town) { if (town.isCapital()) return getMaxResidentsPerTownCapitalOverride(); else - return getMaxResidentsPerTown(); + return !town.hasNation() && getMaxNumResidentsWithoutNation() > 0 + ? getMaxNumResidentsWithoutNation() + : getMaxResidentsPerTown(); } public static boolean isTownyUpdating(String currentVersion) { diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/command/InviteCommand.java b/Towny/src/main/java/com/palmergames/bukkit/towny/command/InviteCommand.java index 19defbfb09..f826388a6a 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/command/InviteCommand.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/command/InviteCommand.java @@ -257,7 +257,7 @@ public static void parseAccept(Player player, String[] args) { if (toAccept != null) { try { - if (TownySettings.getMaxResidentsPerTown() > 0 && town.getResidents().size() >= TownySettings.getMaxResidentsForTown(town)) { + if (!town.isAllowedThisAmountOfResidents(town.getNumResidents() + 1, town.isCapital())) { TownyMessaging.sendMsg(player, Translatable.of("msg_err_max_residents_per_town_reached", TownySettings.getMaxResidentsForTown(town))); } else if (town.getNationOrNull() != null && TownySettings.getMaxResidentsPerNation() > 0 && town.getNationOrNull().getResidents().size() >= TownySettings.getMaxResidentsPerNation()) { TownyMessaging.sendMsg(player, Translatable.of("msg_err_cannot_join_nation_over_resident_limit", TownySettings.getMaxResidentsPerNation())); diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/command/NationCommand.java b/Towny/src/main/java/com/palmergames/bukkit/towny/command/NationCommand.java index ce9d9074f0..7c66c69e4c 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/command/NationCommand.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/command/NationCommand.java @@ -1089,10 +1089,12 @@ public void nationLeave(Player player) throws TownyException { boolean tooManyResidents = false; if (town.isCapital()) { // Check that the capital wont have too many residents after deletion. - tooManyResidents = TownySettings.getMaxResidentsPerTown() > 0 && TownySettings.getMaxResidentsPerTownCapitalOverride() > 0 && town.getNumResidents() > TownySettings.getMaxResidentsPerTown(); + tooManyResidents = town.isAllowedThisAmountOfResidents(town.getNumResidents(), false); // Show a message preceding the confirmation message if they will lose residents. - if (tooManyResidents) - TownyMessaging.sendMsg(player, Translatable.of("msg_deleting_nation_will_result_in_losing_residents", TownySettings.getMaxResidentsPerTown(), town.getNumResidents() - TownySettings.getMaxResidentsPerTown())); + if (tooManyResidents) { + int maxResidentsPerTown = TownySettings.getMaxResidentsPerTown(); + TownyMessaging.sendMsg(player, Translatable.of("msg_deleting_nation_will_result_in_losing_residents", maxResidentsPerTown, town.getNumResidents() - maxResidentsPerTown)); + } } final boolean finalTooManyResidents = tooManyResidents; Confirmation.runOnAccept(() -> { @@ -1120,10 +1122,12 @@ public void nationDelete(Player player, String[] split) { Town town = getTownFromResidentOrThrow(resident); Nation nation = getNationFromResidentOrThrow(resident); // Check that the capital wont have too many residents after deletion. - boolean tooManyResidents = TownySettings.getMaxResidentsPerTown() > 0 && TownySettings.getMaxResidentsPerTownCapitalOverride() > 0 && town.getNumResidents() > TownySettings.getMaxResidentsPerTown(); + boolean tooManyResidents = !town.isAllowedThisAmountOfResidents(town.getNumResidents(), false); // Show a message preceding the confirmation message if they will lose residents. - if (tooManyResidents) - TownyMessaging.sendMsg(player, Translatable.of("msg_deleting_nation_will_result_in_losing_residents", TownySettings.getMaxResidentsPerTown(), town.getNumResidents() - TownySettings.getMaxResidentsPerTown())); + if (tooManyResidents) { + int maxResidentsPerTown = TownySettings.getMaxResidentsPerTown(); + TownyMessaging.sendMsg(player, Translatable.of("msg_deleting_nation_will_result_in_losing_residents", maxResidentsPerTown, town.getNumResidents() - maxResidentsPerTown)); + } Confirmation.runOnAccept(() -> { TownyMessaging.sendGlobalMessage(Translatable.of("msg_del_nation", nation.getName())); @@ -2321,7 +2325,7 @@ private static void changeNationOwnership(CommandSender sender, final Nation nat return; } - boolean capitalTooManyResidents = TownySettings.getMaxResidentsPerTown() > 0 && nation.getCapital().getNumResidents() > TownySettings.getMaxResidentsPerTown(); + boolean capitalTooManyResidents = !existingCapital.isAllowedThisAmountOfResidents(existingCapital.getNumResidents(), false); if (capitalTooManyResidents && !admin) { TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_err_nation_capital_too_many_residents", newCapital.getName())); return; diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/command/PlotCommand.java b/Towny/src/main/java/com/palmergames/bukkit/towny/command/PlotCommand.java index 8e6fa86829..f19d8fbda3 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/command/PlotCommand.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/command/PlotCommand.java @@ -382,16 +382,11 @@ private boolean playerIsAbleToJoinViaPlotClaim(Resident resident, TownBlock town return !resident.hasTown() && town.isOpen() && !townBlock.getType().equals(TownBlockType.EMBASSY) && - !townNotPermittedAnotherResident(town) && + !town.isAllowedThisAmountOfResidents(town.getNumResidents() + 1, town.isCapital()) && !town.hasOutlaw(resident) && resident.hasPermissionNode(PermissionNodes.TOWNY_COMMAND_TOWN_JOIN.getNode()); } - private boolean townNotPermittedAnotherResident(Town town) { - return (TownySettings.getMaxNumResidentsWithoutNation() > 0 && !town.hasNation() && town.getResidents().size() >= TownySettings.getMaxNumResidentsWithoutNation()) || - (TownySettings.getMaxResidentsPerTown() > 0 && town.getResidents().size() >= TownySettings.getMaxResidentsForTown(town)); - } - public void parsePlotClear(Resident resident, TownBlock townBlock) throws TownyException { checkPermOrThrow(resident.getPlayer(), PermissionNodes.TOWNY_COMMAND_PLOT_CLEAR.getNode()); 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 17ec2c3f5d..a627de8145 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 @@ -2816,18 +2816,15 @@ private static boolean inviteResidentToTownOrThrow(CommandSender sender, Residen if (!newMember.hasPermissionNode(PermissionNodes.TOWNY_TOWN_RESIDENT.getNode())) throw new TownyException(Translatable.of("msg_not_allowed_join", newMember.getName())); - if (TownySettings.getMaxResidentsPerTown() > 0 && town.getResidents().size() >= TownySettings.getMaxResidentsForTown(town)) + if (!town.isAllowedThisAmountOfResidents(town.getNumResidents() + 1, town.isCapital())) throw new TownyException(Translatable.of("msg_err_max_residents_per_town_reached", TownySettings.getMaxResidentsForTown(town))); - if (town.hasNation() && TownySettings.getMaxResidentsPerNation() > 0 && town.getNationOrNull().getResidents().size() >= TownySettings.getMaxResidentsPerNation()) + if (town.hasNation() && !town.getNationOrNull().canAddResidents(1)) throw new TownyException(Translatable.of("msg_err_cannot_add_nation_over_resident_limit", TownySettings.getMaxResidentsPerNation(), newMember.getName())); if (!admin && TownySettings.getTownInviteCooldown() > 0 && (System.currentTimeMillis()/1000 - newMember.getRegistered()/1000) < TownySettings.getTownInviteCooldown()) throw new TownyException(Translatable.of("msg_err_resident_doesnt_meet_invite_cooldown", newMember)); - if (TownySettings.getMaxNumResidentsWithoutNation() > 0 && !town.hasNation() && town.getResidents().size() >= TownySettings.getMaxNumResidentsWithoutNation()) - throw new TownyException(Translatable.of("msg_err_unable_to_add_more_residents_without_nation", TownySettings.getMaxNumResidentsWithoutNation())); - // Throws when the player has a town or is in this town already. town.addResidentCheck(newMember); @@ -2974,15 +2971,12 @@ private static void parseTownJoin(Player player, String[] args) throws TownyExce if (!town.isOpen()) throw new TownyException(Translatable.of("msg_err_not_open", town.getFormattedName())); - if (town.hasNation() && TownySettings.getMaxResidentsPerNation() > 0 && town.getNationOrNull().getResidents().size() >= TownySettings.getMaxResidentsPerNation()) + if (town.hasNation() && !town.getNationOrNull().canAddResidents(1)) throw new TownyException(Translatable.of("msg_err_cannot_join_nation_over_resident_limit", TownySettings.getMaxResidentsPerNation())); - if (TownySettings.getMaxResidentsPerTown() > 0 && town.getResidents().size() >= TownySettings.getMaxResidentsForTown(town)) + if (!town.isAllowedThisAmountOfResidents(town.getNumResidents() + 1, town.isCapital())) throw new TownyException(Translatable.of("msg_err_max_residents_per_town_reached", TownySettings.getMaxResidentsForTown(town))); - if (TownySettings.getMaxNumResidentsWithoutNation() > 0 && !town.hasNation() && town.getResidents().size() >= TownySettings.getMaxNumResidentsWithoutNation()) - throw new TownyException(Translatable.of("msg_err_unable_to_add_more_residents_without_nation", TownySettings.getMaxNumResidentsWithoutNation())); - if (town.hasOutlaw(resident)) throw new TownyException(Translatable.of("msg_err_outlaw_in_open_town")); @@ -3703,8 +3697,7 @@ private static void vetTownsForMergeAndThrow(Town remainingTown, Town succumbing int newResidentsAmount = remainingTown.getNumResidents() + succumbingTown.getNumResidents(); - if (TownySettings.getMaxResidentsPerTown() > 0 && - newResidentsAmount > TownySettings.getMaxResidentsForTown(remainingTown)) + if (!remainingTown.isAllowedThisAmountOfResidents(newResidentsAmount, remainingTown.isCapital())) throw new TownyException(Translatable.of("msg_town_merge_err_too_many_residents", TownySettings.getMaxResidentsForTown(remainingTown))); if (!remainingTown.hasUnlimitedClaims() && townWouldHaveTooManyTownBlocks(remainingTown, succumbingTown, newResidentsAmount)) diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyPlayerListener.java b/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyPlayerListener.java index 6f32abdd5e..9190bd8f3f 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyPlayerListener.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyPlayerListener.java @@ -878,7 +878,7 @@ public void onPlayerFishEvent(PlayerFishEvent event) { // Non-player catches are tested for destroy permissions. } else { //Make decision on whether this is allowed using the PlayerCache and then a cancellable event. - test = TownyActionEventExecutor.canDestroy(player, caught.getLocation(), Material.GRASS); + test = TownyActionEventExecutor.canDestroy(player, caught.getLocation(), Material.DIRT); } if (!test) { event.setCancelled(true); diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/object/Town.java b/Towny/src/main/java/com/palmergames/bukkit/towny/object/Town.java index ef84a4bc71..46eb4e7566 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/object/Town.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/object/Town.java @@ -47,6 +47,7 @@ import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.Arrays; @@ -390,7 +391,14 @@ public boolean hasResidentWithRank(Resident resident, String rank) { return hasResident(resident) && resident.hasTownRank(rank); } - void addResident(Resident resident) { + /** + * DO NOT USE THIS. This is visiable for testing only! + * Use {@link Resident#setTown(Town)} instead. + * + * @param resident Resident that gets added to the town. + */ + @VisibleForTesting + public void addResident(Resident resident) { residents.add(resident); } @@ -1922,4 +1930,17 @@ public boolean hasEnoughResidentsToJoinANation() { public boolean hasEnoughResidentsToBeANationCapital() { return TownUtil.townHasEnoughResidentsToBeANationCapital(this); } + + /** + * Is this town allowed to have the given number of residents? + * + * @param residentCount Number of residents to test with. + * @param isCapital When false, a capital city will be tested as though it + * were not a non-Capital city. + * @return true if the town can support the number of residents based on the + * rules configured on the server. + */ + public boolean isAllowedThisAmountOfResidents(int residentCount, boolean isCapital) { + return TownUtil.townCanHaveThisAmountOfResidents(this, residentCount, isCapital); + } } diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/NationUtil.java b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/NationUtil.java index 7f93f4738e..1a429506b0 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/NationUtil.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/NationUtil.java @@ -70,7 +70,7 @@ public static boolean canAddTownsResidentCount(Nation nation, int additionalResi if (hasReachedMaximumResidents(nation)) return false; int maxResidentPerNation = TownySettings.getMaxResidentsPerNation(); - return maxResidentPerNation == 0 || (nation.getResidents().size() + additionalResidents) < maxResidentPerNation; + return maxResidentPerNation == 0 || (nation.getResidents().size() + additionalResidents) <= maxResidentPerNation; } public static boolean hasReachedMaximumTowns(Nation nation) { diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/TownUtil.java b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/TownUtil.java index 591980568a..92fbe3cbff 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/TownUtil.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/TownUtil.java @@ -93,4 +93,12 @@ public static boolean townHasEnoughResidentsToJoinANation(Town town) { return true; return town.getNumResidents() >= TownySettings.getNumResidentsJoinNation(); } + + public static boolean townCanHaveThisAmountOfResidents(Town town, int residentCount, boolean isCapital) { + int maxResidents = !isCapital + ? !town.hasNation() && TownySettings.getMaxNumResidentsWithoutNation() > 0 ? TownySettings.getMaxNumResidentsWithoutNation() : TownySettings.getMaxResidentsPerTown() + : TownySettings.getMaxResidentsPerTownCapitalOverride(); + + return maxResidents == 0 || residentCount <= maxResidents; + } } diff --git a/Towny/src/test/java/com/palmergames/bukkit/towny/test/PopulationTests.java b/Towny/src/test/java/com/palmergames/bukkit/towny/test/PopulationTests.java new file mode 100644 index 0000000000..949c31305a --- /dev/null +++ b/Towny/src/test/java/com/palmergames/bukkit/towny/test/PopulationTests.java @@ -0,0 +1,195 @@ +package com.palmergames.bukkit.towny.test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import com.palmergames.bukkit.config.ConfigNodes; +import com.palmergames.bukkit.towny.TownySettings; +import com.palmergames.bukkit.towny.object.Nation; +import com.palmergames.bukkit.towny.object.Resident; +import com.palmergames.bukkit.towny.object.Town; + +import be.seeseemelk.mockbukkit.MockBukkit; + +public class PopulationTests { + + static Town town; + static Nation nation; + + @BeforeAll + static void init() { + MockBukkit.getOrCreateMock(); + TownySettings.loadDefaultConfig(); + nation = new Nation("testNation"); + town = new Town("testTown"); + Resident res1 = new Resident("leonardo"); + Resident res2 = new Resident("donatello"); + Resident res3 = new Resident("raphael"); + Resident res4 = new Resident("michelangelo"); + Resident res5 = new Resident("splinter"); + town.addResident(res1); + town.addResident(res2); + town.addResident(res3); + town.addResident(res4); + town.addResident(res5); + } + + @BeforeEach + void reset() { + town.removeNation(); + TownySettings.getConfig().set(ConfigNodes.GTOWN_MAX_RESIDENTS_PER_TOWN.getRoot(), 0); + TownySettings.getConfig().set(ConfigNodes.GTOWN_MAX_RESIDENTS_CAPITAL_OVERRIDE.getRoot(), 0); + TownySettings.getConfig().set(ConfigNodes.GTOWN_SETTINGS_MAX_NUMBER_RESIDENTS_WITHOUT_NATION.getRoot(), 0); + TownySettings.getConfig().set(ConfigNodes.GTOWN_SETTINGS_REQUIRED_NUMBER_RESIDENTS_CREATE_NATION.getRoot(), 0); + TownySettings.getConfig().set(ConfigNodes.GTOWN_SETTINGS_REQUIRED_NUMBER_RESIDENTS_JOIN_NATION.getRoot(), 0); + TownySettings.getConfig().set(ConfigNodes.GNATION_SETTINGS_MAX_RESIDENTS_PER_NATION.getRoot(), 0); + } + + /* + * Basic population test where no restrictions apply. + */ + + @Test + void testSuccessAddResidentNoRestrictionsWithoutCapital() { + assertEquals(town.isAllowedThisAmountOfResidents(10, false), true); + } + + @Test + void testSuccessAddResidentNoRestrictionsWithCapital() { + assertEquals(town.isAllowedThisAmountOfResidents(10, true), true); + } + + /* + * Test restricted town population without capital. + */ + + @Test + void testSuccessAllowTownPopulationWithRestrictionsWithoutCapital() { + TownySettings.getConfig().set(ConfigNodes.GTOWN_MAX_RESIDENTS_PER_TOWN.getRoot(), 5); + TownySettings.getConfig().set(ConfigNodes.GTOWN_MAX_RESIDENTS_CAPITAL_OVERRIDE.getRoot(), 10); + assertEquals(town.isAllowedThisAmountOfResidents(5, false), true); + } + + @Test + void testFailAllowTownPopulationWithRestrictionsWithoutCapital() { + TownySettings.getConfig().set(ConfigNodes.GTOWN_MAX_RESIDENTS_PER_TOWN.getRoot(), 5); + TownySettings.getConfig().set(ConfigNodes.GTOWN_MAX_RESIDENTS_CAPITAL_OVERRIDE.getRoot(), 10); + assertEquals(town.isAllowedThisAmountOfResidents(10, false), false); + } + + /* + * Test restricted town population with capital. + */ + + @Test + void testSuccessAllowTownPopulationWithRestrictionsWithCapital() { + TownySettings.getConfig().set(ConfigNodes.GTOWN_MAX_RESIDENTS_PER_TOWN.getRoot(), 5); + TownySettings.getConfig().set(ConfigNodes.GTOWN_MAX_RESIDENTS_CAPITAL_OVERRIDE.getRoot(), 10); + assertEquals(town.isAllowedThisAmountOfResidents(10, true), true); + } + + @Test + void testFailureAllowTownPopulationWithRestrictionsWithCapital() { + TownySettings.getConfig().set(ConfigNodes.GTOWN_MAX_RESIDENTS_PER_TOWN.getRoot(), 5); + TownySettings.getConfig().set(ConfigNodes.GTOWN_MAX_RESIDENTS_CAPITAL_OVERRIDE.getRoot(), 10); + assertEquals(town.isAllowedThisAmountOfResidents(11, true), false); + } + + /* + * Test nationless towns' population restriction. + */ + + @Test + void testSuccessAllowNationlessTownPopulationWithFeatureDisabled() { + TownySettings.getConfig().set(ConfigNodes.GTOWN_MAX_RESIDENTS_PER_TOWN.getRoot(), 10); + TownySettings.getConfig().set(ConfigNodes.GTOWN_SETTINGS_MAX_NUMBER_RESIDENTS_WITHOUT_NATION.getRoot(), 0); + assertEquals(town.isAllowedThisAmountOfResidents(5, false), true); + } + + @Test + void testSuccessAllowNationlessTownPopulation() { + TownySettings.getConfig().set(ConfigNodes.GTOWN_MAX_RESIDENTS_PER_TOWN.getRoot(), 10); + TownySettings.getConfig().set(ConfigNodes.GTOWN_SETTINGS_MAX_NUMBER_RESIDENTS_WITHOUT_NATION.getRoot(), 5); + assertEquals(town.isAllowedThisAmountOfResidents(5, false), true); + } + + @Test + void testFailureAllowNationlessTownPopulation() { + TownySettings.getConfig().set(ConfigNodes.GTOWN_MAX_RESIDENTS_PER_TOWN.getRoot(), 10); + TownySettings.getConfig().set(ConfigNodes.GTOWN_SETTINGS_MAX_NUMBER_RESIDENTS_WITHOUT_NATION.getRoot(), 5); + assertEquals(town.isAllowedThisAmountOfResidents(6, false), false); + } + + /* + * Test capital population requirements. + */ + + @Test + void testSuccessTownMakingNationWithFeatureDisabled() { + TownySettings.getConfig().set(ConfigNodes.GTOWN_SETTINGS_REQUIRED_NUMBER_RESIDENTS_CREATE_NATION.getRoot(), 0); + assertEquals(town.hasEnoughResidentsToBeANationCapital(), true); + } + + @Test + void testSucceedTownPopAllowsBeingCapital() { + TownySettings.getConfig().set(ConfigNodes.GTOWN_SETTINGS_REQUIRED_NUMBER_RESIDENTS_CREATE_NATION.getRoot(), 5); + assertEquals(town.hasEnoughResidentsToBeANationCapital(), true); + } + + @Test + void testFailTownPopAllowsBeingCapital() { + TownySettings.getConfig().set(ConfigNodes.GTOWN_SETTINGS_REQUIRED_NUMBER_RESIDENTS_CREATE_NATION.getRoot(), 6); + assertEquals(town.hasEnoughResidentsToBeANationCapital(), false); + } + + /* + * Test nation-joining population requirements. + */ + + @Test + void testSuccessTownJoiningNationWithFeatureDisabled() { + TownySettings.getConfig().set(ConfigNodes.GTOWN_SETTINGS_REQUIRED_NUMBER_RESIDENTS_JOIN_NATION.getRoot(), 0); + assertEquals(town.hasEnoughResidentsToBeANationCapital(), true); + } + + @Test + void testSucceedTownPopAllowsJoiningNation() { + TownySettings.getConfig().set(ConfigNodes.GTOWN_SETTINGS_REQUIRED_NUMBER_RESIDENTS_JOIN_NATION.getRoot(), 5); + assertEquals(town.hasEnoughResidentsToJoinANation(), true); + } + + @Test + void testFailTownPopAllowsJoiningNation() { + TownySettings.getConfig().set(ConfigNodes.GTOWN_SETTINGS_REQUIRED_NUMBER_RESIDENTS_JOIN_NATION.getRoot(), 6); + assertEquals(town.hasEnoughResidentsToJoinANation(), false); + } + + /* + * Test max residents per nation. + */ + + @Test + void testSuccessNationAddingResidentsWithFeatureDisabled() { + TownySettings.getConfig().set(ConfigNodes.GNATION_SETTINGS_MAX_RESIDENTS_PER_NATION.getRoot(), 0); + nation.addTown(town); + assertEquals(nation.canAddResidents(1), true); + } + + @Test + void testSuccessNationAddingResidents() { + TownySettings.getConfig().set(ConfigNodes.GNATION_SETTINGS_MAX_RESIDENTS_PER_NATION.getRoot(), 7); + nation.addTown(town); + assertEquals(nation.canAddResidents(1), true); + } + + @Test + void testFailureNationAddingResidents() { + TownySettings.getConfig().set(ConfigNodes.GNATION_SETTINGS_MAX_RESIDENTS_PER_NATION.getRoot(), 5); + nation.addTown(town); + assertEquals(nation.canAddResidents(1), false); + } +} + From 838339fca3da86ded851929a7317259ef0826f88 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Jan 2024 09:34:47 -0600 Subject: [PATCH 73/74] Bump org.apache.maven.plugins:maven-surefire-plugin from 3.2.3 to 3.2.5 (#7194) Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.2.3 to 3.2.5. - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.2.3...surefire-3.2.5) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-surefire-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Towny/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Towny/pom.xml b/Towny/pom.xml index 5d62d8138f..5675cedf79 100644 --- a/Towny/pom.xml +++ b/Towny/pom.xml @@ -472,7 +472,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.2.3 + 3.2.5 ${skipTests} From a002e077bf928ff2178c947cd05245e32201d361 Mon Sep 17 00:00:00 2001 From: LlmDl Date: Thu, 18 Jan 2024 13:19:20 -0600 Subject: [PATCH 74/74] - Refactor max residents per town code into TownUtil accessed via a new Town method. - Bump Spigot 1.20.2 to 1.20.4. - Bump com.github.seeseemelk:MockBukkit-v1.20 from 3.60.0 to 3.65.0. - Bump org.apache.maven.plugins:maven-surefire-plugin from 3.2.3 to 3.2.5. --- Towny/pom.xml | 2 +- .../bukkit/towny/listeners/TownyEntityListener.java | 11 ++++++++--- Towny/src/main/resources/ChangeLog.txt | 7 ++++++- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Towny/pom.xml b/Towny/pom.xml index 5675cedf79..04c0f5a7d7 100644 --- a/Towny/pom.xml +++ b/Towny/pom.xml @@ -13,7 +13,7 @@ towny jar - 0.100.1.3 + 0.100.1.4 diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyEntityListener.java b/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyEntityListener.java index 9c00cd4f50..d9c79136d2 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyEntityListener.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/listeners/TownyEntityListener.java @@ -305,9 +305,12 @@ public void onPotionSplashEvent(PotionSplashEvent event) { /* * Check to see if any of the potion effects are protected. + * TODO: Make up a wrapper of some kind in order to support older versions while + * using the new methods when possible. */ - - if (detrimentalPotions.contains(effect.getType().getName())) { + @SuppressWarnings("deprecation") + String name = effect.getType().getName(); + if (detrimentalPotions.contains(name)) { detrimental = true; break; } @@ -939,7 +942,9 @@ private boolean hasDetrimentalEffects(Collection effects) { final List detrimentalPotions = TownySettings.getPotionTypes().stream().map(type -> type.toLowerCase(Locale.ROOT)).collect(Collectors.toList()); for (final PotionEffect effect : effects) { - // This should use getKey when 1.18 becomes the minimum supported version. + // TODO: Make up a wrapper of some kind in order to support older versions while + // using the new methods when possible. + @SuppressWarnings("deprecation") final String name = effect.getType().getName().toLowerCase(Locale.ROOT); /* diff --git a/Towny/src/main/resources/ChangeLog.txt b/Towny/src/main/resources/ChangeLog.txt index 41adb7a063..b49d0b2040 100644 --- a/Towny/src/main/resources/ChangeLog.txt +++ b/Towny/src/main/resources/ChangeLog.txt @@ -9464,4 +9464,9 @@ v0.92.0.11: - New Config Option: claiming.new_town_bonus_claims - Default: 0 - An amount of additional townblocks that a town will receive when it is first created, in addition to any amount given via the town_block_ratio or town_levels. - - As an example: This can be used to add 10 townblocks to a town when it is made so the borders can be grown a bit more before the mayor has to seek out residents. \ No newline at end of file + - As an example: This can be used to add 10 townblocks to a town when it is made so the borders can be grown a bit more before the mayor has to seek out residents. +0.100.1.4: + - Refactor max residents per town code into TownUtil accessed via a new Town method. + - Bump Spigot 1.20.2 to 1.20.4. + - Bump com.github.seeseemelk:MockBukkit-v1.20 from 3.60.0 to 3.65.0. + - Bump org.apache.maven.plugins:maven-surefire-plugin from 3.2.3 to 3.2.5. \ No newline at end of file
Minecraft VersionTowny Version
MC 1.20.* Use 0.100.0.0 or the the Latest Pre-Release.
MC 1.20.* Use 0.100.1.0 or the the Latest Pre-Release.
MC 1.19.*
MC 1.18.*
MC 1.17.*