Skip to content

Commit

Permalink
Make Towny more resiliant to errors which come from having no Economy…
Browse files Browse the repository at this point in the history
… present on the server. (#7127)

* Make Towny more resiliant to errors which come from having no Economy
present on the server.

Alter ConfirmationTransaction to no longer take in an Account in the
constructor, instead it takes in a TownyObject, which will resolve an
account. This prevents errors when non-Economy-enabled servers attempt
to create a Confirmation with a cost set on it.

Make TownyEconomyHandler#getFormattedBalance able to handle returning a
formatted balance when the Economy is not active.

Add prettyMoney method to BaseCommand, use it throughout the command
classes to make things look cleaner.

* Swap TownyObject for EconomyHandler
  • Loading branch information
LlmDl authored Dec 21, 2023
1 parent a279271 commit 6773c7c
Show file tree
Hide file tree
Showing 10 changed files with 138 additions and 103 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,8 @@ public static boolean setBalance(String accountName, double amount, World world)
* @return string containing the formatted balance
*/
public static String getFormattedBalance(double balance) {
if (!isActive())
return String.valueOf(balance);

String formattedBalance = economy.getFormattedBalance(balance);
if (formattedBalance != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.palmergames.bukkit.towny.command;

import com.palmergames.bukkit.towny.TownyAPI;
import com.palmergames.bukkit.towny.TownyEconomyHandler;
import com.palmergames.bukkit.towny.TownyUniverse;
import com.palmergames.bukkit.towny.exceptions.NoPermissionException;
import com.palmergames.bukkit.towny.exceptions.ResidentNPCException;
Expand Down Expand Up @@ -390,4 +391,8 @@ public static void catchNPCResident(Resident resident) throws ResidentNPCExcepti
if (resident.isNPC())
throw new ResidentNPCException();
}

public static String prettyMoney(double cost) {
return TownyEconomyHandler.getFormattedBalance(cost);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -945,8 +945,9 @@ public static void newNation(CommandSender sender, String name, Town capitalTown
// If it isn't free to make a nation, send a confirmation.
if (!noCharge && TownyEconomyHandler.isActive()) {
// Test if they can pay.
if (!capitalTown.getAccount().canPayFromHoldings(TownySettings.getNewNationPrice()))
throw new TownyException(Translatable.of("msg_no_funds_new_nation2", TownySettings.getNewNationPrice()));
double cost = TownySettings.getNewNationPrice();
if (!capitalTown.getAccount().canPayFromHoldings(cost))
throw new TownyException(Translatable.of("msg_no_funds_new_nation2", cost));

final String finalName = filteredName;
Confirmation.runOnAccept(() -> {
Expand All @@ -959,9 +960,9 @@ public static void newNation(CommandSender sender, String name, Town capitalTown
TownyMessaging.sendGlobalMessage(Translatable.of("msg_new_nation", sender.getName(), StringMgmt.remUnderscore(finalName)));

})
.setCost(new ConfirmationTransaction(TownySettings::getNewNationPrice, capitalTown.getAccount(), "New Nation Cost",
Translatable.of("msg_no_funds_new_nation2", TownySettings.getNewNationPrice())))
.setTitle(Translatable.of("msg_confirm_purchase", TownyEconomyHandler.getFormattedBalance(TownySettings.getNewNationPrice())))
.setCost(new ConfirmationTransaction(TownySettings::getNewNationPrice, capitalTown, "New Nation Cost",
Translatable.of("msg_no_funds_new_nation2", cost)))
.setTitle(Translatable.of("msg_confirm_purchase", prettyMoney(cost)))
.sendTo(sender);

// Or, it is free, so just make the nation.
Expand Down Expand Up @@ -1973,11 +1974,12 @@ private static void nationSetMapColor(CommandSender sender, Nation nation, Strin
if (!TownySettings.getNationColorsMap().containsKey(color))
throw new TownyException(Translatable.of("msg_err_invalid_nation_map_color", TownySettings.getNationColorsMap().keySet().toString()));

if (TownySettings.getNationSetMapColourCost() > 0)
double cost = TownySettings.getNationSetMapColourCost();
if (cost > 0)
Confirmation
.runOnAccept(() -> setNationMapColor(nation, color, admin, sender))
.setTitle(Translatable.of("msg_confirm_purchase", TownySettings.getNationSetMapColourCost()))
.setCost(new ConfirmationTransaction(()-> TownySettings.getNationSetMapColourCost(), nation.getAccount(), "Cost of setting nation map color."))
.setTitle(Translatable.of("msg_confirm_purchase", prettyMoney(cost)))
.setCost(new ConfirmationTransaction(() -> cost, nation, "Cost of setting nation map color."))
.sendTo(sender);
else
setNationMapColor(nation, color, admin, sender);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -588,12 +588,12 @@ private void tryPlotSetType(Player player, Resident resident, TownBlock townBloc

// Test if we can pay first to throw an exception.
if (cost > 0 && TownyEconomyHandler.isActive() && !resident.getAccount().canPayFromHoldings(cost))
throw new TownyException(Translatable.of("msg_err_cannot_afford_plot_set_type_cost", townBlockType, TownyEconomyHandler.getFormattedBalance(cost)));
throw new TownyException(Translatable.of("msg_err_cannot_afford_plot_set_type_cost", townBlockType, prettyMoney(cost)));

// Handle payment via a confirmation to avoid suprise costs.
if (cost > 0 && TownyEconomyHandler.isActive()) {
Confirmation.runOnAccept(() -> {
TownyMessaging.sendMsg(resident, Translatable.of("msg_plot_set_cost", TownyEconomyHandler.getFormattedBalance(cost), townBlockType));
TownyMessaging.sendMsg(resident, Translatable.of("msg_plot_set_cost", prettyMoney(cost), townBlockType));

try {
townBlock.setType(townBlockType, resident);
Expand All @@ -604,9 +604,9 @@ private void tryPlotSetType(Player player, Resident resident, TownBlock townBloc
BukkitTools.fireEvent(new PlayerChangePlotTypeEvent(townBlockType, oldType, townBlock, player));
TownyMessaging.sendMsg(player, Translatable.of("msg_plot_set_type", townBlockType));
})
.setCost(new ConfirmationTransaction(() -> cost, resident.getAccount(), String.format("Plot set to %s", townBlockType),
Translatable.of("msg_err_cannot_afford_plot_set_type_cost", townBlockType, TownyEconomyHandler.getFormattedBalance(cost))))
.setTitle(Translatable.of("msg_confirm_purchase", TownyEconomyHandler.getFormattedBalance(cost)))
.setCost(new ConfirmationTransaction(() -> cost, resident, String.format("Plot set to %s", townBlockType),
Translatable.of("msg_err_cannot_afford_plot_set_type_cost", townBlockType, prettyMoney(cost))))
.setTitle(Translatable.of("msg_confirm_purchase", prettyMoney(cost)))
.sendTo(BukkitTools.getPlayerExact(resident.getName()));

// No cost or economy so no confirmation.
Expand Down Expand Up @@ -648,20 +648,20 @@ public void parsePlotSetOutpost(Player player, Resident resident, TownBlock town
// Throws a TownyException with message if outpost should not be set.
OutpostUtil.OutpostTests(town, resident, townyWorld, key, resident.isAdmin(), true);

if (TownyEconomyHandler.isActive() && TownySettings.getOutpostCost() > 0) {
if (TownySettings.getOutpostCost() > 0) {
// Create a confirmation for setting outpost.
Confirmation.runOnAccept(() -> {
// Set the outpost spawn and display feedback.
town.addOutpostSpawn(player.getLocation());
TownyMessaging.sendMsg(player, Translatable.of("msg_plot_set_cost", TownyEconomyHandler.getFormattedBalance(TownySettings.getOutpostCost()), Translatable.of("outpost")));
TownyMessaging.sendMsg(player, Translatable.of("msg_plot_set_cost", prettyMoney(TownySettings.getOutpostCost()), Translatable.of("outpost")));
})
.setCost(new ConfirmationTransaction(() -> TownySettings.getOutpostCost(), town.getAccount(), "PlotSetOutpost", Translatable.of("msg_err_cannot_afford_to_set_outpost")))
.setTitle(Translatable.of("msg_confirm_purchase", TownyEconomyHandler.getFormattedBalance(TownySettings.getOutpostCost())))
.setCost(new ConfirmationTransaction(() -> TownySettings.getOutpostCost(), town, "PlotSetOutpost", Translatable.of("msg_err_cannot_afford_to_set_outpost")))
.setTitle(Translatable.of("msg_confirm_purchase", prettyMoney(TownySettings.getOutpostCost())))
.sendTo(player);
} else {
// Set the outpost spawn and display feedback with no cost confirmation.
town.addOutpostSpawn(player.getLocation());
TownyMessaging.sendMsg(player, Translatable.of("msg_plot_set_cost", TownyEconomyHandler.getFormattedBalance(TownySettings.getOutpostCost()), Translatable.of("outpost")));
TownyMessaging.sendMsg(player, Translatable.of("msg_plot_set_cost", prettyMoney(TownySettings.getOutpostCost()), Translatable.of("outpost")));
}
}

Expand Down Expand Up @@ -994,7 +994,7 @@ public void setPlotForSale(Resident resident, WorldCoord worldCoord, double forS

if (forSale != -1) {
Translatable message = TownyEconomyHandler.isActive()
? Translatable.of("msg_plot_for_sale_amount", resident.getName(), worldCoord.toString(), TownyEconomyHandler.getFormattedBalance(townBlock.getPlotPrice()))
? Translatable.of("msg_plot_for_sale_amount", resident.getName(), worldCoord.toString(), prettyMoney(townBlock.getPlotPrice()))
: Translatable.of("msg_plot_for_sale", resident.getName(), worldCoord.toString());

TownyMessaging.sendPrefixedTownMessage(townBlock.getTownOrNull(), message);
Expand Down Expand Up @@ -1342,7 +1342,7 @@ public void parsePlotGroupForSale(String[] split, Resident resident, TownBlock t
group.save();

Translatable message = TownyEconomyHandler.isActive()
? Translatable.of("msg_player_put_group_up_for_sale_amount", player.getName(), group.getName(), TownyEconomyHandler.getFormattedBalance(group.getPrice()))
? Translatable.of("msg_player_put_group_up_for_sale_amount", player.getName(), group.getName(), prettyMoney(group.getPrice()))
: Translatable.of("msg_player_put_group_up_for_sale", player.getName(), group.getName());

TownyMessaging.sendPrefixedTownMessage(town, message);
Expand Down Expand Up @@ -1576,15 +1576,15 @@ public void parsePlotGroupSetTownBlockType(String[] split, Resident resident, To
double cost = type.getCost() * plotGroupTownBlocks.size();
// Test if we can pay first to throw an exception.
if (cost > 0 && TownyEconomyHandler.isActive() && !resident.getAccount().canPayFromHoldings(cost))
throw new TownyException(Translatable.of("msg_err_cannot_afford_plot_set_type_cost", type, TownyEconomyHandler.getFormattedBalance(cost)));
throw new TownyException(Translatable.of("msg_err_cannot_afford_plot_set_type_cost", type, prettyMoney(cost)));

// Handle payment via a confirmation to avoid suprise costs.
if (cost > 0 && TownyEconomyHandler.isActive()) {
Confirmation.runOnAccept(() -> {
if (townBlock.getPlotObjectGroup() == null)
return;

TownyMessaging.sendMsg(resident, Translatable.of("msg_plot_set_cost", TownyEconomyHandler.getFormattedBalance(cost), type));
TownyMessaging.sendMsg(resident, Translatable.of("msg_plot_set_cost", prettyMoney(cost), type));

for (TownBlock tb : townBlock.getPlotObjectGroup().getTownBlocks()) {
try {
Expand All @@ -1597,11 +1597,9 @@ public void parsePlotGroupSetTownBlockType(String[] split, Resident resident, To
}
TownyMessaging.sendMsg(player, Translatable.of("msg_set_group_type_to_x", type));
})
.setCost(new ConfirmationTransaction(() -> type.getCost() * plotGroupTownBlocks.size(),
resident.getAccount(),
String.format("Plot group (" + plotGroupTownBlocks.size() + ") set to %s", type),
Translatable.of("msg_err_cannot_afford_plot_set_type_cost", type, TownyEconomyHandler.getFormattedBalance(cost))))
.setTitle(Translatable.of("msg_confirm_purchase", TownyEconomyHandler.getFormattedBalance(cost)))
.setCost(new ConfirmationTransaction(() -> cost, resident, String.format("Plot group (%s) set to %s", plotGroupTownBlocks.size(), type),
Translatable.of("msg_err_cannot_afford_plot_set_type_cost", type, prettyMoney(cost))))
.setTitle(Translatable.of("msg_confirm_purchase", prettyMoney(cost)))
.sendTo(BukkitTools.getPlayerExact(resident.getName()));
// No cost or economy so no confirmation.
} else {
Expand Down Expand Up @@ -1837,7 +1835,7 @@ private void continuePlotClaimProcess(List<WorldCoord> selection, Resident resid
PlotGroup group = tb.getPlotObjectGroup();

if (TownyEconomyHandler.isActive() && (!resident.getAccount().canPayFromHoldings(group.getPrice())))
throw new TownyException(Translatable.of("msg_no_funds_claim_plot_group", group.getTownBlocks().size(), TownyEconomyHandler.getFormattedBalance(group.getPrice())));
throw new TownyException(Translatable.of("msg_no_funds_claim_plot_group", group.getTownBlocks().size(), prettyMoney(group.getPrice())));

// Add the confirmation for claiming a plot group.
Confirmation.runOnAccept(() -> {
Expand All @@ -1849,7 +1847,7 @@ private void continuePlotClaimProcess(List<WorldCoord> selection, Resident resid
// Execute the plot claim.
new PlotClaim(Towny.getPlugin(), player, resident, coords, true, false, true).start();
})
.setTitle(Translatable.of("msg_plot_group_claim_confirmation", group.getTownBlocks().size()).append(" ").append(TownyEconomyHandler.getFormattedBalance(group.getPrice())).append(". ").append(Translatable.of("are_you_sure_you_want_to_continue")))
.setTitle(Translatable.of("msg_plot_group_claim_confirmation", group.getTownBlocks().size()).append(" ").append(prettyMoney(group.getPrice())).append(". ").append(Translatable.of("are_you_sure_you_want_to_continue")))
.sendTo(player);

return;
Expand Down Expand Up @@ -1877,15 +1875,15 @@ private void continuePlotClaimProcess(List<WorldCoord> selection, Resident resid
throw new TownyException(Translatable.of("msg_max_plot_own", maxPlots));

if (TownyEconomyHandler.isActive() && (!resident.getAccount().canPayFromHoldings(cost)))
throw new TownyException(Translatable.of("msg_no_funds_claim_plot", TownyEconomyHandler.getFormattedBalance(cost)));
throw new TownyException(Translatable.of("msg_no_funds_claim_plot", prettyMoney(cost)));

if (cost != 0) {
final List<WorldCoord> finalSelection = selection;
Confirmation.runOnAccept(() -> {
// Start the claim task
new PlotClaim(plugin, player, resident, finalSelection, true, false, false).start();
})
.setTitle(Translatable.of("msg_confirm_purchase", TownyEconomyHandler.getFormattedBalance(cost)))
.setTitle(Translatable.of("msg_confirm_purchase", prettyMoney(cost)))
.sendTo(player);
} else {
// Start the claim task
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ private void parseResidentJail(Player player, String[] split) throws TownyExcept
TownyMessaging.sendErrorMsg(player, Translatable.of("msg_err_unable_to_pay_bail"));
}
})
.setTitle(Translatable.of("msg_confirm_purchase", TownyEconomyHandler.getFormattedBalance(cost)))
.setTitle(Translatable.of("msg_confirm_purchase", prettyMoney(cost)))
.sendTo(player);
}

Expand Down
Loading

0 comments on commit 6773c7c

Please sign in to comment.