Skip to content

Commit

Permalink
Add the ability for nations to sanction towns, preventing them from
Browse files Browse the repository at this point in the history
joining the nation via invite or join.

Closes #6544.
  • Loading branch information
LlmDl committed Dec 20, 2023
1 parent 7b680dc commit 5f513df
Show file tree
Hide file tree
Showing 8 changed files with 166 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -937,6 +937,16 @@ protected MenuBuilder load() {
}
},

NATION_SANCTIONTOWN {
@Override
protected MenuBuilder load() {
return new MenuBuilder("nation sanctiontown")
.add("add [town]", Translatable.of("nation_sanction_help_1"))
.add("remove [town]", Translatable.of("nation_sanction_help_2"))
.add("list", Translatable.of("nation_sanction_help_3"));
}
},

ALLIES_STRING {
@Override
protected MenuBuilder load() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ public class NationCommand extends BaseCommand implements CommandExecutor {
"enemylist",
"ally",
"spawn",
"sanctiontown",
"king",
"leader",
"bankhistory",
Expand Down Expand Up @@ -235,6 +236,15 @@ else if (args.length == 3)
if (args.length == 3) {
return Collections.singletonList("-ignore");
}
case "sanctiontown":
if (args.length == 2)
return NameUtil.filterByStart(Arrays.asList("add", "remove", "list"), args[1]);
if (args.length == 3)
return NameUtil.filterByStart(TownyUniverse.getInstance().getTowns()
.stream()
.filter(t -> !nation.hasTown(t))
.map(Town::getName)
.collect(Collectors.toList()), args[2]);
case "add":
return getTownyStartingWith(args[args.length - 1], "t");
case "kick":
Expand Down Expand Up @@ -528,6 +538,9 @@ public void parseNationCommand(final Player player, String[] split) throws Towny
checkPermOrThrow(player, PermissionNodes.TOWNY_COMMAND_NATION_KICK.getNode());
nationKick(player, StringMgmt.remFirstArg(split));
break;
case "sanctiontown":
nationSanctionTown(player, null, StringMgmt.remFirstArg(split));
break;
case "set":
/* Permission test is internal*/
nationSet(player, StringMgmt.remFirstArg(split), false, null);
Expand Down Expand Up @@ -666,7 +679,11 @@ private void parseNationJoin(Player player, String[] args) {
// Check if town is town is free to join.
if (!nation.isOpen())
throw new TownyException(Translatable.of("msg_err_nation_not_open", nation.getFormattedName()));


// Check if the town is sanctioned and not allowed to join.
if (nation.hasSanctionedTown(town))
throw new TownyException(Translatable.of("msg_err_cannot_join_nation_sanctioned_town", nation.getName()));

if (!testTownHasEnoughResidents(town))
throw new TownyException(Translatable.of("msg_err_not_enough_residents_join_nation", town.getName()));

Expand Down Expand Up @@ -1179,6 +1196,13 @@ public void nationAdd(Player player, String[] names) throws TownyException {
continue;
}

if (nation.hasSanctionedTown(town)) {
// Town is sanctioned and cannot join.
removeinvites.add(townname);
TownyMessaging.sendErrorMsg(player, Translatable.of("msg_err_cannot_add_sanctioned_town", townname));
continue;
}

if (!testNationMaxResidents(nation, town)) {
// Town has too many residents to join the nation
removeinvites.add(townname);
Expand Down Expand Up @@ -1397,6 +1421,66 @@ public static void nationKick(CommandSender sender, Nation nation, List<Town> ki
TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_invalid_name"));
}

private void nationSanctionTown(CommandSender sender, Nation nation, String[] args) throws TownyException {
if (args.length == 0 || args[0].equals("?")) {
HelpMenu.NATION_SANCTIONTOWN.send(sender);
return;
}

if (nation == null && sender instanceof Player player)
nation = getNationFromPlayerOrThrow(player);

if (nation == null)
throw new TownyException(Translatable.of(""));

if (args[0].toLowerCase(Locale.ROOT).equals("list")) {
nationSanctionTownList(sender, nation);
return;
}

if (args.length != 2) {
HelpMenu.NATION_SANCTIONTOWN.send(sender);
return;
}
checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_NATION_SANCTIONTOWN.getNode());
Town town = getTownOrThrow(args[1]);
switch(args[0].toLowerCase(Locale.ROOT)) {
case "add" -> nationSanctionTownAdd(sender, nation, town);
case "remove" -> nationSactionTownRemove(sender, nation, town);
}
}

private void nationSanctionTownList(CommandSender sender, Nation nation) {

if (nation.getSanctionedTowns().isEmpty())
TownyMessaging.sendMsg(sender, Translatable.of("msg_error_nation_has_no_enemies"));
else {
TownyMessaging.sendMessage(sender, ChatTools.formatTitle(nation.getName() + " " + Translatable.of("title_nation_sanctioned_towns").forLocale(sender)));
TownyMessaging.sendMessage(sender, TownyFormatter.getFormattedTownyObjects(Translatable.of("title_nation_sanctioned_towns").forLocale(sender), new ArrayList<>(nation.getSanctionedTowns())));
}
}

private void nationSanctionTownAdd(CommandSender sender, Nation nation, Town town) throws TownyException {
if (nation.hasTown(town))
throw new TownyException(Translatable.of("msg_err_nation_cannot_sanction_own_town"));

if (nation.hasSanctionedTown(town))
throw new TownyException(Translatable.of("msg_err_nation_cannot_sanction_own_town"));

nation.addSanctionedTown(town);
nation.save();
TownyMessaging.sendMsg(sender, Translatable.of("msg_err_nation_town_sanctioned", town.getName()));
}

private void nationSactionTownRemove(CommandSender sender, Nation nation, Town town) throws TownyException {
if (!nation.hasSanctionedTown(town))
throw new TownyException(Translatable.of("msg_err_nation_town_isnt_sanctioned"));

nation.removeSanctionedTown(town);
nation.save();
TownyMessaging.sendMsg(sender, Translatable.of("msg_err_nation_town_unsanctioned", town.getName()));
}

private void nationAlly(Player player, String[] split) throws TownyException {
if (split.length == 0) {
HelpMenu.ALLIES_STRING.send(player);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ private static List<String> getNationColumns(){
columns.add("`isOpen` bool NOT NULL DEFAULT '1'");
columns.add("`metadata` text DEFAULT NULL");
columns.add("`conqueredTax` float NOT NULL");
columns.add("`sanctionedTowns` mediumtext DEFAULT NULL");
return columns;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1218,6 +1218,11 @@ public boolean loadNation(Nation nation) {
if (line != null && !line.isEmpty())
nation.setConqueredTax(Double.parseDouble(line));

line = keys.get("sanctionedTowns");
if (line != null) {
nation.loadSanctionedTowns(line.split("#"));
}

} catch (Exception e) {
plugin.getLogger().log(Level.WARNING, Translation.of("flatfile_err_reading_nation_file_at_line", nation.getName(), line, nation.getName()), e);
return false;
Expand Down Expand Up @@ -2136,6 +2141,9 @@ public boolean saveNation(Nation nation) {
list.add("metadata=" + serializeMetadata(nation));

list.add("conqueredTax=" + nation.getConqueredTax());

// SanctionedTowns
list.add("sanctionedTowns=" + StringMgmt.join(nation.getSanctionedTownsForSaving(), "#"));
/*
* Make sure we only save in async
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1387,6 +1387,11 @@ private boolean loadNation(ResultSet rs) {
} catch (SQLException ignored) {
}

line = rs.getString("sanctionedTowns");
if (line != null) {
nation.loadSanctionedTowns(line.split("#"));
}

return true;
} catch (SQLException e) {
TownyMessaging.sendErrorMsg("SQL: Load Nation " + name + " SQL Error - " + e.getMessage());
Expand Down Expand Up @@ -2349,7 +2354,7 @@ public synchronized boolean saveNation(Nation nation) {
nat_hm.put("metadata", "");

nat_hm.put("conqueredTax", nation.getConqueredTax());

nat_hm.put("sanctionedTowns", StringMgmt.join(nation.getSanctionedTownsForSaving(), "#"));
updateDB("NATIONS", nat_hm, Collections.singletonList("name"));

} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,15 @@
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;

public class Nation extends Government {

private static final String ECONOMY_ACCOUNT_PREFIX = TownySettings.getNationAccountPrefix();

private final List<Town> towns = new ArrayList<>();
private final List<Town> sanctionedTowns = new ArrayList<>();
private List<Nation> allies = new ArrayList<>();
private List<Nation> enemies = new ArrayList<>();
private Town capital;
Expand Down Expand Up @@ -698,4 +700,34 @@ public int getLevel(int populationSize) {
public void playerBroadCastMessageToNation(Player player, String message) {
TownyMessaging.sendPrefixedNationMessage(this, Translatable.of("town_say_format", player.getName(), TownyComponents.stripClickTags(message)));
}


public List<Town> getSanctionedTowns() {
return sanctionedTowns;
}

public boolean hasSanctionedTown(Town town) {
return sanctionedTowns.contains(town);
}

public void addSanctionedTown(Town town) {
if (!sanctionedTowns.contains(town))
sanctionedTowns.add(town);
}

public void removeSanctionedTown(Town town) {
sanctionedTowns.remove(town);
}

public List<String> getSanctionedTownsForSaving() {
return sanctionedTowns.stream().map(t -> t.getUUID().toString()).collect(Collectors.toList());
}

public void loadSanctionedTowns(String[] tokens) {
for (String stringUUID : tokens) {
UUID uuid = UUID.fromString(stringUUID);
if (uuid != null && TownyAPI.getInstance().getTown(uuid) != null)
sanctionedTowns.add(TownyAPI.getInstance().getTown(uuid));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ public enum PermissionNodes {
TOWNY_COMMAND_NATION_BANKHISTORY("towny.command.nation.bankhistory"),
TOWNY_COMMAND_NATION_BALTOP("towny.command.nation.baltop"),
TOWNY_COMMAND_NATION_KICK("towny.command.nation.kick"),
TOWNY_COMMAND_NATION_SANCTIONTOWN("towny.command.nation.sanctiontown"),

/*
* Town command permissions
Expand Down
24 changes: 23 additions & 1 deletion Towny/src/main/resources/lang/en-US.yml
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,10 @@ nation_toggle_help_1: "Toggles public status, allowing non-residents to use /n s
nation_toggle_help_2: "Toggles open status, allowing towns to join without an invite."
nation_toggle_help_3: "Toggles taxpercent, making towns pay a percentage instead of fixed rate."

nation_sanction_help_1: "Adds a town to the SanctionedTown list."
nation_sanction_help_2: "Removes a town from the SanctionedTown list."
nation_sanction_help_3: "Lists the nation's Sanctioned Towns."

king_help_1: 'Nation Leader Help'
king_help_2: 'Set your alliance.'
king_help_3: 'Set your enemies.'
Expand Down Expand Up @@ -2371,4 +2375,22 @@ msg_err_resident_is_npc: "You cannot do this to an NPC resident."
# Message shown when a resident doesn't own any land and the /res plotlist command is used.
msg_err_resident_doesnt_own_any_land: "The resident does not own any land personally."

msg_unnamed: "Unnamed"
msg_unnamed: "Unnamed"

msg_err_nation_cannot_sanction_own_town: "You cannot sanction a town that is a part of your nation."

msg_err_nation_town_isnt_sanctioned: "Your nation is not sanctioning that town."

msg_err_nation_town_already_sanctioned: "Your nation already sanctions that town."

msg_err_nation_town_sanctioned: "Your nation has now sanctioned %s, they will not be allowed to join your nation."

msg_err_nation_town_unsanctioned: "Your nation is no longer sanctioning %s."

msg_err_nation_has_no_sanctioned_towns: "Your nation has no sanctioned towns."

title_nation_sanctioned_towns: 'Sanctioned Towns'

msg_err_cannot_add_sanctioned_town: "Your nation cannot add %s, your nation has sanctioned them."

msg_err_cannot_join_nation_sanctioned_town: "Your town cannot join %s, this nation has sanctioned your town."

0 comments on commit 5f513df

Please sign in to comment.