Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 5 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -1179,6 +1201,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 +1426,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