From 19101388881ea2d1e4da894ced84e44eca33aba1 Mon Sep 17 00:00:00 2001 From: mnfu Date: Fri, 13 Mar 2026 17:45:49 -0400 Subject: [PATCH] add playername lookup to /clan info major refactor to SetCommand.java minor fixes/alterations elsewhere, mainly to documentation --- README.md | 24 +-- .../mnfu/clantag/commands/AdminCommand.java | 2 +- .../mnfu/clantag/commands/HelpCommand.java | 4 +- .../mnfu/clantag/commands/InfoCommand.java | 53 ++++- .../mnfu/clantag/commands/SetCommand.java | 189 +++++++----------- 5 files changed, 134 insertions(+), 138 deletions(-) diff --git a/README.md b/README.md index 86bab03..91ab38a 100644 --- a/README.md +++ b/README.md @@ -28,17 +28,17 @@ Currently the default value is not configurable, as this was made for a specific ### Regular Commands -| Command | Description | -|----------------------------|---------------------------------------------------------------------------------------------| -| `/clan` | Base command. | -| `/clan help [pageName]` | Shows a help menu page (defaults to this page if pageName isn't chosen). | -| `/clan create ` | Creates a clan if it doesn't already exist, the name is allowed, and you are not in a clan. | -| `/clan info ` | Shows info about a certain clan. If blank, attempts to use your clan. | -| `/clan invites` | Views your current clan invites in a neat list to accept/decline. | -| `/clan accept ` | Alternative to clicking in chat to accept an invite. | -| `/clan decline ` | Alternative to clicking in chat to decline an invite. | -| `/clan join ` | Joins a clan if it is open to joins. | -| `/clan leave` | Leaves your current clan. If you are the leader with no other members, disbands the clan. | +| Command | Description | +|----------------------------------------------------|-------------------------------------------------------------------------------------------| +| `/clan` | Base command. | +| `/clan help [pageName]` | Shows a help menu page (defaults to this page if pageName isn't chosen). | +| `/clan create ` | Creates a clan if it doesn't already exist, the name is allowed, and you are not in a clan. | +| `/clan info [name\|player] ` | Shows info about a certain clan. If blank, attempts to use your clan. | +| `/clan invites` | Views your current clan invites in a neat list to accept/decline. | +| `/clan accept ` | Alternative to clicking in chat to accept an invite. | +| `/clan decline ` | Alternative to clicking in chat to decline an invite. | +| `/clan join ` | Joins a clan if it is open to joins. | +| `/clan leave` | Leaves your current clan. If you are the leader with no other members, disbands the clan. | ### Clan Officer Commands - Restricted to Officers and Above @@ -55,7 +55,7 @@ Currently the default value is not configurable, as this was made for a specific | `/clan demote ` | Demotes a player to Member rank. | | `/clan disband [confirm]` | Deletes a clan (if confirmed). | | `/clan set color ` | Changes the color code of your clan. | -| `/clan set access ` | Changes your clan’s access state. | +| `/clan set access [open\|invite_only\|toggle]` | Changes your clan’s access state. | | `/clan set name ` | Changes the name of your clan if allowed and available. | | `/clan transfer ` | Transfers clan ownership to a member. | diff --git a/src/main/java/mnfu/clantag/commands/AdminCommand.java b/src/main/java/mnfu/clantag/commands/AdminCommand.java index 929351c..58bb7b7 100644 --- a/src/main/java/mnfu/clantag/commands/AdminCommand.java +++ b/src/main/java/mnfu/clantag/commands/AdminCommand.java @@ -356,7 +356,7 @@ private int executeRename(CommandContext context) { return 0; } if (newClanName.length() < 3 || newClanName.length() > 16) { - context.getSource().sendMessage(Text.literal("Warning: Your proposed new clan name will override length defaults!").formatted(Formatting.YELLOW)); + context.getSource().sendMessage(Text.literal("Warning: Proposed new clan name will override length limits!").formatted(Formatting.YELLOW)); } boolean clanRenamed = clanManager.changeName(oldClanName, newClanName); diff --git a/src/main/java/mnfu/clantag/commands/HelpCommand.java b/src/main/java/mnfu/clantag/commands/HelpCommand.java index 96b7a4e..cc77e83 100644 --- a/src/main/java/mnfu/clantag/commands/HelpCommand.java +++ b/src/main/java/mnfu/clantag/commands/HelpCommand.java @@ -53,7 +53,7 @@ public MutableText buildGeneralMessage () { message.append(Text.literal("[ General Commands ]").formatted(Formatting.WHITE)).append("\n"); message.append(Text.literal("/clan help [pageName]").formatted(Formatting.YELLOW)).append(" - Shows a help menu page (defaults to this page if [pageName] isn't chosen)").formatted(Formatting.GRAY).append("\n"); message.append(Text.literal("/clan create ").formatted(Formatting.YELLOW)).append(" - Creates a clan if it doesn't already exist").formatted(Formatting.GRAY).append("\n"); - message.append(Text.literal("/clan info ").formatted(Formatting.YELLOW)).append(" - Shows info about a clan, and if is blank, it shows your clan").formatted(Formatting.GRAY).append("\n"); + message.append(Text.literal("/clan info [name|player] ").formatted(Formatting.YELLOW)).append(" - Shows info about a clan, defaults to your clan if no arguments given").formatted(Formatting.GRAY).append("\n"); message.append(Text.literal("/clan invites").formatted(Formatting.YELLOW)).append(" - Displays your current clan invites to accept/decline").formatted(Formatting.GRAY).append("\n"); message.append(Text.literal("/clan accept ").formatted(Formatting.YELLOW)).append(" - Accepts a clan invite").formatted(Formatting.GRAY).append("\n"); message.append(Text.literal("/clan decline ").formatted(Formatting.YELLOW)).append(" - Declines a clan invite").formatted(Formatting.GRAY).append("\n"); @@ -85,7 +85,7 @@ public MutableText buildManageMessage () { message.append(Text.literal("/clan demote ").formatted(Formatting.YELLOW)).append(" - Demotes a player in the clan rank hierarchy").formatted(Formatting.GRAY).append("\n"); message.append(Text.literal("/clan disband [confirm]").formatted(Formatting.YELLOW)).append(" - Facilitates the deletion of your clan").formatted(Formatting.GRAY).append("\n"); message.append(Text.literal("/clan set color ").formatted(Formatting.YELLOW)).append(" - Sets your clan color (supports \"WHITE\" or #FFFFFF or FFFFFF formats)").formatted(Formatting.GRAY).append("\n"); - message.append(Text.literal("/clan set access ").formatted(Formatting.YELLOW)).append(" - Sets your clan access to open or invite only").formatted(Formatting.GRAY).append("\n"); + message.append(Text.literal("/clan set access [open|invite_only|toggle]").formatted(Formatting.YELLOW)).append(" - Sets your clan access to open or invite only").formatted(Formatting.GRAY).append("\n"); message.append(Text.literal("/clan set name ").formatted(Formatting.YELLOW)).append(" - Sets your clan name to if it is available").formatted(Formatting.GRAY).append("\n"); message.append(Text.literal("/clan transfer ").formatted(Formatting.YELLOW)).append(" - Transfers clan ownership to ").formatted(Formatting.GRAY).append("\n"); message.append(Text.literal("[General Help Page]") diff --git a/src/main/java/mnfu/clantag/commands/InfoCommand.java b/src/main/java/mnfu/clantag/commands/InfoCommand.java index eb481b3..5fc9221 100644 --- a/src/main/java/mnfu/clantag/commands/InfoCommand.java +++ b/src/main/java/mnfu/clantag/commands/InfoCommand.java @@ -14,12 +14,14 @@ import net.minecraft.text.TextColor; import net.minecraft.util.Formatting; +import java.util.Collection; import java.util.LinkedHashSet; import java.util.List; import java.util.UUID; import java.util.concurrent.CompletableFuture; import static mnfu.clantag.commands.CommandUtils.getPlayerName; +import static mnfu.clantag.commands.CommandUtils.getUuid; public class InfoCommand { private final ClanManager clanManager; @@ -31,14 +33,27 @@ public InfoCommand(ClanManager clanManager) { public LiteralArgumentBuilder build() { return CommandManager.literal("info") .executes(this::executeForSelf) - .then(CommandManager.argument("clanName", StringArgumentType.greedyString()) - .suggests((context, builder) -> { - for (String canonicalName : clanManager.getAllClansCanonicalNames()) { - builder.suggest(canonicalName); - } - return builder.buildFuture(); - }) - .executes(this::executeForClanName)); + .then(CommandManager.literal("name") + .then(CommandManager.argument("clanName", StringArgumentType.greedyString()) + .suggests((context, builder) -> { + for (String canonicalName : clanManager.getAllClansCanonicalNames()) { + builder.suggest(canonicalName); + } + return builder.buildFuture(); + }) + .executes(this::executeForClanName) + ) + ) + .then(CommandManager.literal("player") + .then(CommandManager.argument("playerName", StringArgumentType.word()) + .suggests((context, builder) -> { + Collection onlinePlayers = context.getSource().getPlayerNames(); + onlinePlayers.forEach(builder::suggest); + return builder.buildFuture(); + }) + .executes(this::executeForPlayer) + ) + ); } private int executeForSelf(CommandContext context) { @@ -72,6 +87,28 @@ private int executeForClanName(CommandContext context) { return 1; } + private int executeForPlayer(CommandContext context) { + String playerName = StringArgumentType.getString(context, "playerName"); + + getUuid(context, playerName).thenAccept(optUuid -> { + UUID playerUuid = optUuid.orElse(null); + if (playerUuid == null) { + context.getSource().sendError(Text.literal("Player not found!")); + return; + } + + Clan clan = clanManager.getPlayerClan(playerUuid); + if (clan == null) { + context.getSource().sendError(Text.literal("This player is not in a clan.")); + return; + } + + displayClanInfo(context, clan); + }); + + return 1; + } + private void displayClanInfo(CommandContext context, Clan clan) { MutableText message = Text.empty(); TextColor clanColor = TextColor.parse(clan.hexColor()).getOrThrow(); diff --git a/src/main/java/mnfu/clantag/commands/SetCommand.java b/src/main/java/mnfu/clantag/commands/SetCommand.java index 20d16e5..8cc217f 100644 --- a/src/main/java/mnfu/clantag/commands/SetCommand.java +++ b/src/main/java/mnfu/clantag/commands/SetCommand.java @@ -8,7 +8,6 @@ import mnfu.clantag.ClanManager.JoinPolicy; import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; - import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.MutableText; import net.minecraft.text.Style; @@ -45,22 +44,13 @@ public LiteralArgumentBuilder build() { return 0; }) ) + // access subcommands .then(CommandManager.literal("access") - .then(CommandManager.argument("joinPolicy", StringArgumentType.word()) - .suggests((context, builder) -> { - for (JoinPolicy policy : JoinPolicy.values()) { - builder.suggest(policy.name().toLowerCase(Locale.ROOT)); - } - builder.suggest("toggle"); - return builder.buildFuture(); - }) - .executes(this::executeAccess) - ) - .executes(context -> { - context.getSource().sendError(Text.literal("Usage: /clan set access ")); - return 0; - }) + .then(CommandManager.literal("open").executes(ctx -> executeAccess(ctx, JoinPolicy.OPEN))) + .then(CommandManager.literal("invite_only").executes(ctx -> executeAccess(ctx, JoinPolicy.INVITE_ONLY))) + .then(CommandManager.literal("toggle").executes(this::executeAccessToggle)) ) + // name .then(CommandManager.literal("name") .then(CommandManager.argument("newClanName", StringArgumentType.greedyString()) .executes(this::executeName) @@ -70,7 +60,6 @@ public LiteralArgumentBuilder build() { return 0; }) ) - // default response .executes(context -> { context.getSource().sendError(Text.literal("Valid subcommands: color, access, name")); @@ -82,26 +71,19 @@ private int executeColor(CommandContext context) { ServerPlayerEntity executor = context.getSource().getPlayer(); if (executor == null) return 0; Clan clan = clanManager.getPlayerClan(executor.getUuid()); - if (clan == null) { - context.getSource().sendError(Text.literal("You are not in a clan!")); - return 0; - } - if (!clan.leader().equals(executor.getUuid())) { - context.getSource().sendError(Text.literal("You must be a clan leader to use this command!")); - return 0; - } + if (!checkClanLeader(executor, clan, context)) return 0; + assert clan != null; // checkClanLeader handles this case String newColor = StringArgumentType.getString(context, "newColorNameOrHex"); - if (newColor == null || newColor.isEmpty()) return 0; - // try to interpret as formatting name first + Formatting formatting = Formatting.byName(newColor); if (formatting != null && formatting.isColor()) { newColor = "#" + Integer.toHexString(formatting.getColorValue()).toUpperCase(Locale.ROOT); } else if (newColor.matches("(?i)^#?[0-9a-f]{1,6}$")) { newColor = "#" + newColor.replaceFirst("^#", "").toUpperCase(Locale.ROOT); } else if ("reset".equalsIgnoreCase(newColor)) { - newColor = "#" + Integer.toHexString(Formatting.WHITE.getColorValue()).toUpperCase(Locale.ROOT); // Reset to white + newColor = "#" + Integer.toHexString(Formatting.WHITE.getColorValue()).toUpperCase(Locale.ROOT); } else { context.getSource().sendError(Text.literal(newColor + " is not a valid hex color or minecraft color.")); return 0; @@ -109,90 +91,62 @@ private int executeColor(CommandContext context) { String oldColor = clan.hexColor(); boolean success = clanManager.changeColor(clan.name(), newColor); - if (success) { - MutableText message = Text.empty(); - TextColor oldClanTextColor = TextColor.parse(oldColor).getOrThrow(); - TextColor newClanTextColor = TextColor.parse(newColor).getOrThrow(); - - message.append(Text.literal("Updated clan color from ").formatted(Formatting.GRAY)); - message.append(Text.literal(colorDisplayName(oldColor)) - .setStyle(Style.EMPTY.withColor(oldClanTextColor))); - message.append(Text.literal(" to ").formatted(Formatting.GRAY)); - message.append(Text.literal(colorDisplayName(newColor))) - .setStyle(Style.EMPTY.withColor(newClanTextColor)); - message.append(Text.literal("!").formatted(Formatting.GRAY)); - context.getSource().sendMessage(message); - return 1; - } else { + if (!success) { context.getSource().sendError(Text.literal("Failed to update the color for clan " + clan.name())); return 0; } + + MutableText message = Text.empty(); + TextColor oldClanTextColor = TextColor.parse(oldColor).getOrThrow(); + TextColor newClanTextColor = TextColor.parse(newColor).getOrThrow(); + + message.append(Text.literal("Updated clan color from ").formatted(Formatting.GRAY)) + .append(Text.literal(colorDisplayName(oldColor)).setStyle(Style.EMPTY.withColor(oldClanTextColor))) + .append(Text.literal(" to ").formatted(Formatting.GRAY)) + .append(Text.literal(colorDisplayName(newColor)).setStyle(Style.EMPTY.withColor(newClanTextColor))) + .append(Text.literal("!").formatted(Formatting.GRAY)); + + context.getSource().sendMessage(message); + return 1; } - private String colorDisplayName (String colorString) { - MinecraftColor color = MinecraftColor.fromColor( - Integer.parseInt(colorString.substring(1), 16) - ); - if (color != null) { - return color.getDisplayName(); - } else { - return colorString; - } + private String colorDisplayName(String colorString) { + MinecraftColor color = MinecraftColor.fromColor(Integer.parseInt(colorString.substring(1), 16)); + return color != null ? color.getDisplayName() : colorString; } - private int executeAccess(CommandContext context) { + private int executeAccess(CommandContext context, JoinPolicy newPolicy) { ServerPlayerEntity executor = context.getSource().getPlayer(); if (executor == null) return 0; Clan clan = clanManager.getPlayerClan(executor.getUuid()); - if (clan == null) { - context.getSource().sendError(Text.literal("You are not in a clan!")); - return 0; - } - if (!clan.leader().equals(executor.getUuid())) { - context.getSource().sendError(Text.literal("You must be a clan leader to use this command!")); - return 0; - } + if (!checkClanLeader(executor, clan, context)) return 0; + assert clan != null; // checkClanLeader handles this case - String clanName = clan.name(); - String rawPolicy = StringArgumentType.getString(context, "joinPolicy"); - String policy = rawPolicy.toLowerCase(Locale.ROOT).replace("_", ""); - - JoinPolicy newPolicy; - boolean toggle = policy.equals("toggle"); - if (toggle) { - newPolicy = clan.isClosed() ? JoinPolicy.OPEN : JoinPolicy.INVITE_ONLY; - } else if (policy.equals("open")) { - newPolicy = JoinPolicy.OPEN; - } else if (policy.equals("inviteonly") || policy.equals("invite")) { - newPolicy = JoinPolicy.INVITE_ONLY; - } else { - context.getSource().sendError(Text.literal(policy + " is not a valid option. Usage: /clan set access ")); - return 0; - } + JoinPolicy oldPolicy = clan.isClosed() ? JoinPolicy.INVITE_ONLY : JoinPolicy.OPEN; + clanManager.changePolicy(clan.name(), newPolicy); - clanManager.changePolicy(clanName, newPolicy); - - MutableText message; - if (toggle) { - message = Text.literal("Toggled clan access from ") - .formatted(Formatting.GRAY) - .append(accessText(clan.isClosed())) - .append(Text.literal(" to ").formatted(Formatting.GRAY)) - .append(accessText(newPolicy != JoinPolicy.OPEN)) - .append(Text.literal("!").formatted(Formatting.GRAY)); - } else { - message = Text.literal("Updated clan access from ") - .formatted(Formatting.GRAY) - .append(accessText(clan.isClosed())) - .append(Text.literal(" to ").formatted(Formatting.GRAY)) - .append(accessText(newPolicy != JoinPolicy.OPEN)) - .append(Text.literal("!").formatted(Formatting.GRAY)); - } + MutableText message = Text.empty() + .append(Text.literal("Updated clan access from ").formatted(Formatting.GRAY)) + .append(accessText(oldPolicy != JoinPolicy.OPEN)) + .append(Text.literal(" to ").formatted(Formatting.GRAY)) + .append(accessText(newPolicy != JoinPolicy.OPEN)) + .append(Text.literal("!").formatted(Formatting.GRAY)); context.getSource().sendMessage(message); return 1; } + private int executeAccessToggle(CommandContext context) { + ServerPlayerEntity executor = context.getSource().getPlayer(); + if (executor == null) return 0; + Clan clan = clanManager.getPlayerClan(executor.getUuid()); + if (!checkClanLeader(executor, clan, context)) return 0; + assert clan != null; // checkClanLeader handles this case + + JoinPolicy newPolicy = clan.isClosed() ? JoinPolicy.OPEN : JoinPolicy.INVITE_ONLY; + return executeAccess(context, newPolicy); + } + private MutableText accessText(boolean closed) { return Text.literal(closed ? "Invite Only" : "Open") .formatted(closed ? Formatting.RED : Formatting.GREEN); @@ -202,14 +156,8 @@ private int executeName(CommandContext context) { ServerPlayerEntity executor = context.getSource().getPlayer(); if (executor == null) return 0; Clan clan = clanManager.getPlayerClan(executor.getUuid()); - if (clan == null) { - context.getSource().sendError(Text.literal("You are not in a clan!")); - return 0; - } - if (!clan.leader().equals(executor.getUuid())) { - context.getSource().sendError(Text.literal("You must be a clan leader to use this command!")); - return 0; - } + if (!checkClanLeader(executor, clan, context)) return 0; + assert clan != null; // checkClanLeader handles this case String newClanName = StringArgumentType.getString(context, "newClanName"); if (newClanName.contains(" ")) { @@ -222,20 +170,31 @@ private int executeName(CommandContext context) { } boolean clanRenamed = clanManager.changeName(clan.name(), newClanName); - if (clanRenamed) { - TextColor clanTextColor = TextColor.parse(clan.hexColor()).getOrThrow(); - MutableText message = Text.literal("Updated clan name from ") - .formatted(Formatting.GRAY) - .append(Text.literal(clan.name()).setStyle(Style.EMPTY.withColor(clanTextColor))) - .append(Text.literal(" to ").formatted(Formatting.GRAY)) - .append(Text.literal(newClanName).setStyle(Style.EMPTY.withColor(clanTextColor))) - .append(Text.literal("!").formatted(Formatting.GRAY)); - - context.getSource().sendMessage(message); - return 1; - } else { + if (!clanRenamed) { context.getSource().sendError(Text.literal("Clan " + newClanName + " already exists, or " + newClanName + " isn't an allowed name!")); return 0; } + + TextColor clanTextColor = TextColor.parse(clan.hexColor()).getOrThrow(); + MutableText message = Text.literal("Updated clan name from ").formatted(Formatting.GRAY) + .append(Text.literal(clan.name()).setStyle(Style.EMPTY.withColor(clanTextColor))) + .append(Text.literal(" to ").formatted(Formatting.GRAY)) + .append(Text.literal(newClanName).setStyle(Style.EMPTY.withColor(clanTextColor))) + .append(Text.literal("!").formatted(Formatting.GRAY)); + + context.getSource().sendMessage(message); + return 1; + } + + private boolean checkClanLeader(ServerPlayerEntity executor, Clan clan, CommandContext context) { + if (clan == null) { + context.getSource().sendError(Text.literal("You are not in a clan!")); + return false; + } + if (!clan.leader().equals(executor.getUuid())) { + context.getSource().sendError(Text.literal("You must be a clan leader to use this command!")); + return false; + } + return true; } -} +} \ No newline at end of file