Skip to content
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 @@ -273,6 +273,22 @@ public static Result join(Faction joiner, Coalition coalition) {
if (!coalition.isInvited(joiner.getId(), CoalitionRegistry.now())) {
return Result.fail("§cYou have not been invited to that coalition.");
}
String block = admit(joiner, coalition);
return block != null ? Result.fail(block) : Result.ok("§aYou joined the " + displayName(coalition) + " §acoalition.");
}

/** Staff add a faction as if it had accepted an invite; every other joining rule applies. */
public static Result adminAdd(Coalition coalition, Faction joiner) {
if (!CoalitionSettings.enabled) return Result.fail(DISABLED);
if (joiner == null) return Result.fail(NO_FACTION);
String block = admit(joiner, coalition);
if (block != null) return Result.fail(block);
notifyFaction(joiner, "§aStaff added you to the " + displayName(coalition) + " §acoalition.");
return Result.ok("§aAdded " + joiner.getName() + " §ato the " + displayName(coalition) + " §acoalition.");
}

/** Adds the faction once the join rules allow it; returns why not otherwise. */
private static String admit(Faction joiner, Coalition coalition) {
String block = membershipBlock(joiner);
Faction target = target(coalition);
if (block == null && (target == null || targetLost(coalition))) block = "§cThat coalition has lost its target.";
Expand All @@ -292,12 +308,12 @@ public static Result join(Faction joiner, Coalition coalition) {
}
}
if (block == null) block = capacityBlock(joiner, false);
if (block != null) return Result.fail(block);
if (block != null) return block;
notifyMembers(coalition, "§a" + joiner.getName() + " §ajoined the " + displayName(coalition) + " §acoalition.");
coalition.addMember(joiner.getId(), CoalitionRegistry.now());
coalition.setSingleMemberSince(null);
CoalitionRegistry.save();
return Result.ok("§aYou joined the " + displayName(coalition) + " §acoalition.");
return null;
}

public static Result leave(Faction member) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public final class CoalitionCommandManager implements CommandExecutor {
public static final List<String> SUBCOMMANDS = List.of(
"menu", "list", "create", "invite", "join", "leave", "kick", "leader", "target",
"setbanner", "resetbanner", "offensive", "disband");
public static final List<String> ADMIN_SUBCOMMANDS = List.of("disband", "offensive", "kick", "setleader", "cost");
public static final List<String> ADMIN_SUBCOMMANDS = List.of("disband", "offensive", "add", "kick", "setleader", "cost");
static final String NOT_A_LEADER = "§cOnly a faction leader can do that.";

@Override
Expand Down Expand Up @@ -164,20 +164,22 @@ private void admin(CommandSender sender, String[] args) {
sender.sendMessage("§7" + CoalitionService.displayName(coalition) + " §7is now "
+ (coalition.isOffensive() ? "offensive" : "defensive") + ".");
}
case "kick", "setleader" -> {
case "add", "kick", "setleader" -> {
if (args.length < 4) {
sender.sendMessage("§cUsage: /coalition admin " + sub + " <faction> <coalition>");
return;
}
Coalition coalition = coalitionArg(sender, args, 3, sub + " <faction> <coalition>");
if (coalition == null) return;
Faction faction = MercenaryCommandManager.resolveFaction(args[2]);
CoalitionService.Result result = sub.equals("kick")
? CoalitionService.adminKick(coalition, faction)
: CoalitionService.adminSetLeader(coalition, faction);
CoalitionService.Result result = switch (sub) {
case "add" -> CoalitionService.adminAdd(coalition, faction);
case "kick" -> CoalitionService.adminKick(coalition, faction);
default -> CoalitionService.adminSetLeader(coalition, faction);
};
sender.sendMessage(result.message());
}
default -> sender.sendMessage("§cUsage: /coalition admin <disband|offensive|kick|setleader|cost>");
default -> sender.sendMessage("§cUsage: /coalition admin <disband|offensive|add|kick|setleader|cost>");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public List<String> onTabComplete(CommandSender sender, Command command, String
String action = args[1].toLowerCase(Locale.ROOT);
if (action.equals("cost")) return prefix(args[args.length - 1], factionIds());
if (action.equals("offensive") && args.length == 3) return prefix(args[2], List.of("on", "off"));
if ((action.equals("kick") || action.equals("setleader")) && args.length == 3) {
if ((action.equals("add") || action.equals("kick") || action.equals("setleader")) && args.length == 3) {
return prefix(args[2], factionIds());
}
return args.length <= 4 ? prefix(args[args.length - 1], coalitionNames()) : List.of();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,14 @@ private boolean dispatchCommand(CommandSender sender, Command cmd, String label,
}
AdminLandService.forceRemoveCapital(g).forEach(p::sendMessage);
return true;
} else if(cmd.getName().equalsIgnoreCase(cmd2) && args[0].equalsIgnoreCase("forcejoin") && args.length >= 3) {
if(!Permissions.isAdmin(sender)) {
p.sendMessage("§a[SimpleFactions]§c You do not have access to this command");
return true;
}
Guild g = FactionManager.getGuildByString(args[1]);
p.sendMessage(g == null ? "§cNo guild by the id "+args[1] : StaffJoins.guild(g, rest(args, 2)));
return true;
} else if(cmd.getName().equalsIgnoreCase(cmd2) && args[0].equalsIgnoreCase("forceleader") && args.length >= 3) {
if(!Permissions.isAdmin(sender)) {
p.sendMessage("§a[SimpleFactions]§c You do not have access to this command");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,18 @@ private void admin(Player p, String[] args) {
p.sendMessage("§a[SimpleFactions]§c You do not have access to this command");
return;
}
if (args.length >= 2 && args[1].equalsIgnoreCase("add")) {
if (args.length < 4) {
p.sendMessage("§cUsage: §e/company admin add <company> <character>");
return;
}
MercenaryCompany company = resolveCompany(args[2]);
p.sendMessage(company == null ? "§cNo company by that name."
: StaffJoins.company(company, String.join(" ", java.util.Arrays.copyOfRange(args, 3, args.length))));
return;
}
if (args.length < 3) {
p.sendMessage("§cUsage: §e/company admin give|take <company> [amount]");
p.sendMessage("§cUsage: §e/company admin give|take|add <company> [amount|character]");
return;
}
boolean give;
Expand Down
108 changes: 108 additions & 0 deletions src/main/java/net/tfminecraft/simplefactions/managers/StaffJoins.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package net.tfminecraft.simplefactions.managers;

import java.util.List;
import java.util.UUID;

import org.bukkit.Bukkit;
import org.bukkit.entity.Player;

import net.tfminecraft.simplefactions.guild.Guild;
import net.tfminecraft.simplefactions.guild.HeldRealms;
import net.tfminecraft.simplefactions.identity.Members;
import net.tfminecraft.simplefactions.mercenary.MercenaryResult;
import net.tfminecraft.simplefactions.mercenary.company.MercenaryCompanies;
import net.tfminecraft.simplefactions.mercenary.company.MercenaryCompany;
import net.tfminecraft.simplefactions.mercenary.company.MercenaryCompanyService;
import net.tfminecraft.simplefactions.mercenary.company.MercenaryEligibility;
import net.tfminecraft.simplefactions.objects.Faction;
import net.tfminecraft.simplefactions.war.battle.campaign.warband.CampaignWarbandSignupService;
import net.tfminecraft.simplefactions.war.battle.warband.Warband;
import net.tfminecraft.tlibs.character.CharacterInfo;

/**
* Staff tools that put a character straight into a guild, mercenary company or
* warband. They skip the invite and nothing else: every other joining rule
* still applies. Each returns the line to show the staff member.
*/
public final class StaffJoins {
private StaffJoins() {}

static String noMatch(String input) {
return "§cNo living character matches " + input + "§c; use an online character's name or a character ID";
}

/** Typed character IDs reach offline and dead characters too, so only the living pass. */
private static String living(String input) {
String key = Members.findOnline(input);
return key != null && Members.info(key).map(CharacterInfo::alive).orElse(false) ? key : null;
}

/** {@code /guild forcejoin}: a stranger or a member of the base guild joins a guild of the same realm. */
public static String guild(Guild guild, String input) {
if (guild.isBase()) return "§cThis is the base guild, use /faction forcejoin instead";
Faction realm = guild.getFaction();
if (HeldRealms.isClosing(realm)) return HeldRealms.CLOSING;
String key = living(input);
if (key == null) return noMatch(input);
if (guild.isMember(key)) return "§c" + Members.display(key) + " §cis already in " + guild.getName();
Guild current = FactionManager.getGuildByMember(key);
if (current != null && current.getFaction() != realm) {
return "§c" + Members.display(key) + " §cbelongs to " + current.getFaction().getName()
+ "§c, another faction";
}
if (current != null && !current.isBase()) {
return "§c" + Members.display(key) + " §cis already in the guild " + current.getName();
}
if (current != null && current.isLeader(key)) {
return "§c" + Members.display(key) + " §cleads the faction and cannot join a guild";
}
guild.addMember(key);
realm.updatePrestige();
Members.online(key).ifPresent(joiner -> joiner.sendMessage("§aStaff added you to the guild " + guild.getName()));
// The whole realm hears of it, as with an accepted invite.
List<String> realmMembers = realm.getMembers();
for (Player online : Bukkit.getOnlinePlayers()) {
String member = Members.key(online);
if (member != null && !member.equals(key) && realmMembers.contains(member)) {
online.sendMessage("§a" + Members.display(key) + " joined the guild " + guild.getName() + "§a!");
}
}
return "§aAdded " + Members.display(key) + " §ato " + guild.getName();
}

/** {@code /company admin add}: enlists a character in a free slot. */
public static String company(MercenaryCompany company, String input) {
String key = living(input);
if (key == null) return noMatch(input);
// The service words these two refusals for the joining player, so staff get their own.
if (!MercenaryEligibility.canJoin(key)) {
return "§c" + Members.display(key) + " §cdoes not have the mercenary trait, so cannot enlist";
}
MercenaryCompany current = MercenaryCompanies.findByMember(key);
if (current != null) return "§c" + Members.display(key) + " §calready serves in " + current.getName();
MercenaryResult result = MercenaryCompanyService.join(company, key);
if (!result.ok()) return "§cCannot enlist " + Members.display(key) + ": " + result.message();
Members.online(key).ifPresent(joiner -> joiner.sendMessage("§aStaff enlisted you in " + company.getName() + "."));
Members.online(company.getLeader()).ifPresent(leader ->
leader.sendMessage("§a" + Members.display(key) + " signed on with the company."));
return "§aEnlisted " + Members.display(key) + " §ain " + company.getName();
}

/** {@code /warband forcejoin}: signs a character up as if the warband were open to them. */
public static String warband(Warband warband, String input) {
String key = living(input);
if (key == null) return noMatch(input);
UUID account = Members.accountId(key).orElse(null);
if (account == null) return noMatch(input);
if (warband.hasMember(account)) return "§c" + Members.display(key) + " §cis already in " + warband.getId();
Faction faction = FactionManager.getByMember(key);
if (warband.isFaction() && faction == null) {
return "§cThis is a faction warband, " + Members.display(key) + " §cneeds a faction to join";
}
Player online = Members.player(key);
String failure = CampaignWarbandSignupService.signupMember(account, key, warband, faction, online);
if (failure != null) return "§cCannot add " + Members.display(key) + ": " + failure;
if (online != null) online.sendMessage("§aStaff added you to the warband " + warband.getId());
return "§aAdded " + Members.display(key) + " §ato " + warband.getId();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,11 @@ private List<String> completeCompany(Player p, String[] args) {
if(args.length == 2 && args[0].equalsIgnoreCase("admin") && Permissions.isAdmin(p)) {
completions.add("give");
completions.add("take");
completions.add("add");
return filtered(completions, args[1]);
}
if(args.length == 3 && args[0].equalsIgnoreCase("admin") && Permissions.isAdmin(p)
&& (args[1].equalsIgnoreCase("give") || args[1].equalsIgnoreCase("take"))) {
&& (args[1].equalsIgnoreCase("give") || args[1].equalsIgnoreCase("take") || args[1].equalsIgnoreCase("add"))) {
for(Guild g : FactionManager.getAllGuilds()) {
if(g == null || g.getCompany() == null) continue;
if(g.getCompany().getName() != null && !g.getCompany().getName().contains(" ")) {
Expand All @@ -82,6 +83,9 @@ private List<String> completeCompany(Player p, String[] args) {
}
return filtered(completions, args[2]);
}
if(args.length >= 4 && args[0].equalsIgnoreCase("admin") && args[1].equalsIgnoreCase("add") && Permissions.isAdmin(p)) {
return Members.completions(onlineCharacters(), java.util.Arrays.copyOfRange(args, 2, args.length));
}
if(args.length == 4 && args[0].equalsIgnoreCase("admin") && Permissions.isAdmin(p)) {

return completions;
Expand Down Expand Up @@ -130,6 +134,16 @@ private List<String> completeMercenaries(String[] args) {
return completions;
}

/** Names of the characters being played right now. */
static List<String> onlineCharacters() {
List<String> names = new ArrayList<>();
for(Player online : Bukkit.getOnlinePlayers()) {
String key = Members.key(online);
if(key != null) names.add(Members.display(key));
}
return names;
}

/** Drops the subcommand, so a member name that starts at the third word completes like one at the second. */
private static String[] afterFirst(String[] args) {
return java.util.Arrays.copyOfRange(args, 1, args.length);
Expand Down Expand Up @@ -276,6 +290,7 @@ else if(cmd.getName().equalsIgnoreCase("guild") && args.length >= 0 && args.leng
completions.add("dummify");
completions.add("dummyleader");
completions.add("forceleader");
completions.add("forcejoin");
if(Cache.provincesEnabled) completions.add("forceremovecapital");
}
return completions;
Expand Down Expand Up @@ -651,6 +666,21 @@ else if(cmd.getName().equalsIgnoreCase("faction") && args.length >= 0 && args.le
if(g != null && !g.isBase() && g.hasCapital() && g.getId().toLowerCase().startsWith(args[1].toLowerCase())) completions.add(g.getId());
}
return completions;
} else if(cmd.getName().equalsIgnoreCase("guild") && args.length >= 2 && args[0].equalsIgnoreCase("forcejoin")){
if(args.length > 2) {
Guild g = FactionManager.getGuildByString(args[1]);
List<String> names = new ArrayList<String>();
for(Player online : Bukkit.getOnlinePlayers()) {
String key = Members.key(online);
if(g != null && key != null && !g.isMember(key)) names.add(Members.display(key));
}
return Members.completions(names, afterFirst(args));
}
List<String> completions = new ArrayList<String>();
for(Guild g : FactionManager.getAllGuilds()) {
if(g != null && !g.isBase() && g.getId().toLowerCase().startsWith(args[1].toLowerCase())) completions.add(g.getId());
}
return completions;
} else if(cmd.getName().equalsIgnoreCase("guild") && args.length == 2 && args[0].equalsIgnoreCase("forceleader")){
List<String> completions = new ArrayList<String>();
for(Faction f : FactionManager.factions) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,16 @@ public boolean onCommand(CommandSender sender, Command cmd, String label, String
BattlePersistenceService.deleteWarband(w);
p.sendMessage("§aWarband "+w.getId()+" §adeleted!");
return true;
} else if(cmd.getName().equalsIgnoreCase(cmd1) && args[0].equalsIgnoreCase("forcejoin") && args.length >= 3) {
if(!BattlePermissions.isAdmin(sender)) {
p.sendMessage("§a[Battle]§4You do not have access to this command");
return true;
}
Warband w = WarbandManager.getByString(args[1]);
p.sendMessage(w == null ? "§cWarband not found"
: net.tfminecraft.simplefactions.managers.StaffJoins.warband(w,
String.join(" ", java.util.Arrays.copyOfRange(args, 2, args.length))));
return true;
} else if(cmd.getName().equalsIgnoreCase(cmd1) && args[0].equalsIgnoreCase("toggleopen") && args.length == 1) {
Warband w = WarbandManager.getByLeader(p);
if(w == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ private List<String> complete(CommandSender sender, Command cmd, String[] args)
completions.add("toggleopen");
completions.add("leave");
completions.add("retreat");
if(BattlePermissions.isAdmin(sender)) completions.add("forcejoin");
return completions;
}
} else if(cmd.getName().equalsIgnoreCase("warband") && args.length == 2 && args[0].equalsIgnoreCase("create")){
Expand Down Expand Up @@ -84,6 +85,16 @@ private List<String> complete(CommandSender sender, Command cmd, String[] args)
band, faction, player, CampaignClock.now()) == null) ids.add(band.getId());
}
return ids;
} else if(cmd.getName().equalsIgnoreCase("warband") && args.length >= 2 && args[0].equalsIgnoreCase("forcejoin")) {
if(!BattlePermissions.isAdmin(sender)) return List.of();
if(args.length == 2) return WarbandManager.get().stream().map(Warband::getId).toList();
List<String> names = new ArrayList<>();
for(Player online : Bukkit.getOnlinePlayers()) {
if(Members.key(online) != null && WarbandManager.getByMemberId(online.getUniqueId()) == null) {
names.add(Members.name(online));
}
}
return Members.completions(names, java.util.Arrays.copyOfRange(args, 1, args.length));
} else if(cmd.getName().equalsIgnoreCase("warband") && args.length == 2 && args[0].equalsIgnoreCase("invite")){
if(sender instanceof Player){
List<String> completions = new ArrayList<String>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@
verify(tom).sendMessage("§7Cancelled. The coalition stays defensive.");

run(tom, "offensive");
prompt.onPlayerQuit(new PlayerQuitEvent(tom, "bye"));

Check warning on line 164 in src/test/java/net/tfminecraft/simplefactions/diplomacy/coalition/CoalitionCommandTest.java

View workflow job for this annotation

GitHub Actions / build

PlayerQuitEvent(org.bukkit.entity.Player,java.lang.String) in org.bukkit.event.player.PlayerQuitEvent has been deprecated and marked for removal
AsyncPlayerChatEvent afterQuit = new AsyncPlayerChatEvent(true, tom, "CODE", Set.of());
prompt.onPlayerChat(afterQuit);
assertFalse(afterQuit.isCancelled());
Expand Down Expand Up @@ -217,7 +217,7 @@
Coalition league = league();

run(staff, "admin");
verify(staff).sendMessage("§cUsage: /coalition admin <disband|offensive|kick|setleader|cost>");
verify(staff).sendMessage("§cUsage: /coalition admin <disband|offensive|add|kick|setleader|cost>");
run(staff, "admin", "offensive", "maybe", "Grand League");
verify(staff).sendMessage("§cUsage: /coalition admin offensive <on|off> <coalition>");
run(staff, "admin", "offensive", "on");
Expand All @@ -234,6 +234,9 @@
assertFalse(league.isMember("bog"));
run(staff, "admin", "setleader", "fig", "Grand League");
assertTrue(league.isLeader("fig"));
run(staff, "admin", "add", "bog", "Grand League");
assertTrue(league.isMember("bog"));
verify(staff).sendMessage("§aAdded bog §ato the Grand League §acoalition.");

run(staff, "admin", "disband");
verify(staff).sendMessage("§cUsage: /coalition admin disband <coalition>");
Expand Down Expand Up @@ -276,6 +279,7 @@
assertTrue(tabs.onTabComplete(tom, command, "coalition", new String[] {"invite", "bog", ""}).isEmpty());
assertTrue(tabs.onTabComplete(tom, command, "coalition", new String[] {"admin", ""}).isEmpty());
assertEquals(List.of("cost"), tabs.onTabComplete(staff, command, "coalition", new String[] {"admin", "co"}));
assertEquals(List.of("fig"), tabs.onTabComplete(staff, command, "coalition", new String[] {"admin", "add", "f"}));
assertEquals(List.of("fig"), tabs.onTabComplete(staff, command, "coalition", new String[] {"admin", "cost", "bog", "f"}));
assertEquals(List.of("on", "off"), tabs.onTabComplete(staff, command, "coalition", new String[] {"admin", "offensive", ""}));
assertEquals(List.of("Grand League"), tabs.onTabComplete(staff, command, "coalition", new String[] {"admin", "offensive", "on", "G"}));
Expand Down
Loading
Loading