Skip to content

Commit

Permalink
Add the ability for nations to sanction towns, preventing them from j…
Browse files Browse the repository at this point in the history
…oining the nation via invite or join. (#7129)

* Add the ability for nations to sanction towns, preventing them from
joining the nation via invite or join.

Closes #6544.

* Forgot a lang string.

* Add admin command

* Can't forget about the name blacklist!

* Fix lang strings, add ability to /n sanctiontown list [nation], add
events.
  • Loading branch information
LlmDl authored Dec 21, 2023
1 parent 98c99f0 commit f046154
Show file tree
Hide file tree
Showing 13 changed files with 282 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -937,6 +937,17 @@ 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"))
.add("list [nation]", Translatable.of("nation_sanction_help_4"));
}
},

ALLIES_STRING {
@Override
protected MenuBuilder load() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import com.palmergames.bukkit.towny.event.NationPreRemoveEnemyEvent;
import com.palmergames.bukkit.towny.event.nation.NationRankAddEvent;
import com.palmergames.bukkit.towny.event.nation.NationRankRemoveEvent;
import com.palmergames.bukkit.towny.event.nation.NationSanctionTownAddEvent;
import com.palmergames.bukkit.towny.event.nation.NationSanctionTownRemoveEvent;
import com.palmergames.bukkit.towny.event.nation.NationSetSpawnEvent;
import com.palmergames.bukkit.towny.event.nation.NationTownLeaveEvent;
import com.palmergames.bukkit.towny.event.NationRemoveEnemyEvent;
Expand Down Expand Up @@ -125,6 +127,7 @@ public class NationCommand extends BaseCommand implements CommandExecutor {
"enemylist",
"ally",
"spawn",
"sanctiontown",
"king",
"leader",
"bankhistory",
Expand Down Expand Up @@ -235,6 +238,18 @@ 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 && args[1].equalsIgnoreCase("add") || args[1].equalsIgnoreCase("remove"))
return NameUtil.filterByStart(TownyUniverse.getInstance().getTowns()
.stream()
.filter(t -> !nation.hasTown(t))
.map(Town::getName)
.collect(Collectors.toList()), args[2]);
if (args.length == 3 && args[1].equalsIgnoreCase("list"))
return getTownyStartingWith(args[2], "n");
break;
case "add":
return getTownyStartingWith(args[args.length - 1], "t");
case "kick":
Expand Down Expand Up @@ -528,6 +543,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 +684,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 @@ -1180,6 +1202,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 @@ -1398,6 +1427,73 @@ public static void nationKick(CommandSender sender, Nation nation, List<Town> ki
TownyMessaging.sendErrorMsg(sender, Translatable.of("msg_invalid_name"));
}

public static 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("msg_err_no_nation_cannot_do"));

if (args[0].toLowerCase(Locale.ROOT).equals("list")) {
if (args.length == 2)
nation = getNationOrThrow(args[1]);
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);
default -> HelpMenu.NATION_SANCTIONTOWN.send(sender);
}
}

private static void nationSanctionTownList(CommandSender sender, Nation nation) {
if (nation.getSanctionedTowns().isEmpty()) {
TownyMessaging.sendMsg(sender, Translatable.of("msg_err_nation_has_no_sanctioned_towns"));
return;
}
Translator translator = Translator.locale(sender);
TownyMessaging.sendMessage(sender, ChatTools.formatTitle(nation.getName() + " " + translator.of("title_nation_sanctioned_towns")));
TownyMessaging.sendMessage(sender, TownyFormatter.getFormattedTownyObjects(translator.of("title_nation_sanctioned_towns"), new ArrayList<>(nation.getSanctionedTowns())));
}

private static 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_town_already_sanctioned"));

BukkitTools.ifCancelledThenThrow(new NationSanctionTownAddEvent(nation, town));

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

private static 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"));

BukkitTools.ifCancelledThenThrow(new NationSanctionTownRemoveEvent(nation, town));

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 @@ -172,6 +172,7 @@ public class TownyAdminCommand extends BaseCommand implements CommandExecutor {
"rename",
"delete",
"toggle",
"sanctiontown",
"set",
"meta",
"deposit",
Expand Down Expand Up @@ -508,6 +509,9 @@ else if (args.length > 3 && TownyCommandAddonAPI.hasCommand(CommandType.TOWNYADM
if (args.length == 2) {
return filterByStartOrGetTownyStartingWith(Collections.singletonList("new"), args[1], "+n");
} else if (args.length > 2 && !args[1].equalsIgnoreCase("new")) {
Nation nation = TownyUniverse.getInstance().getNation(args[1]);
if (nation == null)
return Collections.emptyList();
switch (args[2].toLowerCase(Locale.ROOT)) {
case "add":
if (args.length == 4)
Expand All @@ -518,14 +522,8 @@ else if (args.length > 3 && TownyCommandAddonAPI.hasCommand(CommandType.TOWNYADM
else if (args.length == 5)
return NameUtil.filterByStart(BaseCommand.setOnOffCompletes, args[4]);
case "set": {
Nation nation = TownyUniverse.getInstance().getNation(args[1]);
if (nation != null) {
if (args.length == 4) {
return NameUtil.filterByStart(adminNationSetTabCompletes, args[3]);
}
}
else {
return Collections.emptyList();
if (args.length == 4) {
return NameUtil.filterByStart(adminNationSetTabCompletes, args[3]);
}
}
case "meta":
Expand All @@ -546,6 +544,16 @@ else if (args.length == 5)
return getTownyStartingWith(args[4], "r");
else if (args.length == 6)
return NameUtil.filterByStart(TownyPerms.getNationRanks(), args[5]);
case "sanctiontown":
if (args.length == 4)
return NameUtil.filterByStart(Arrays.asList("add","remove","list"), args[3]);
if (args.length == 5 && args[3].equalsIgnoreCase("add") || args[4].equalsIgnoreCase("remove"))
return NameUtil.filterByStart(TownyUniverse.getInstance().getTowns()
.stream()
.filter(t -> !nation.hasTown(t))
.map(Town::getName)
.collect(Collectors.toList()), args[4]);
break;
case "enemy":
case "ally":
if (args.length == 4)
Expand Down Expand Up @@ -1633,6 +1641,10 @@ public void parseAdminNationCommand(CommandSender sender, String[] split) throws
checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYADMIN_NATION_KICK.getNode());
NationCommand.nationKick(sender, nation, TownyAPI.getInstance().getTowns(StringMgmt.remArgs(split, 2)));
break;
case "sanctiontown":
checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYADMIN_NATION_SANCTIONTOWN.getNode());
NationCommand.nationSanctionTown(sender, nation, StringMgmt.remArgs(split, 2));
break;
case "delete":
checkPermOrThrow(sender, PermissionNodes.TOWNY_COMMAND_TOWNYADMIN_NATION_DELETE.getNode());
Confirmation.runOnAccept(() -> {
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
@@ -0,0 +1,38 @@
package com.palmergames.bukkit.towny.event.nation;

import com.palmergames.bukkit.towny.event.CancellableTownyEvent;
import com.palmergames.bukkit.towny.object.Nation;
import com.palmergames.bukkit.towny.object.Town;

import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;

public class NationSanctionTownAddEvent extends CancellableTownyEvent {
private static final HandlerList HANDLER_LIST = new HandlerList();

private final Nation nation;
private final Town town;

public NationSanctionTownAddEvent(Nation nation, Town town) {
this.nation = nation;
this.town = town;
}

public Nation getNation() {
return nation;
}

public Town getTown() {
return town;
}

public static HandlerList getHandlerList() {
return HANDLER_LIST;
}

@NotNull
@Override
public HandlerList getHandlers() {
return HANDLER_LIST;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.palmergames.bukkit.towny.event.nation;

import com.palmergames.bukkit.towny.event.CancellableTownyEvent;
import com.palmergames.bukkit.towny.object.Nation;
import com.palmergames.bukkit.towny.object.Town;

import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;

public class NationSanctionTownRemoveEvent extends CancellableTownyEvent {
private static final HandlerList HANDLER_LIST = new HandlerList();

private final Nation nation;
private final Town town;

public NationSanctionTownRemoveEvent(Nation nation, Town town) {
this.nation = nation;
this.town = town;
}

public Nation getNation() {
return nation;
}

public Town getTown() {
return town;
}

public static HandlerList getHandlerList() {
return HANDLER_LIST;
}

@NotNull
@Override
public HandlerList getHandlers() {
return HANDLER_LIST;
}
}
Loading

0 comments on commit f046154

Please sign in to comment.