diff --git a/changeset.md b/changeset.md new file mode 100644 index 00000000..0ff24f83 --- /dev/null +++ b/changeset.md @@ -0,0 +1,7 @@ +Fixes: + +- Fix OPs being unable to set styled nicknames for other players when + `use_permissions_api` is `false` (#300). Nickname style permissions are now + checked against the player running the command. + - New config option, `nickname_style_perms_check_target` (default `false`), + restores the old behavior of checking the target player. diff --git a/docs/Config-Documentation.md b/docs/Config-Documentation.md index 10958dae..36338339 100644 --- a/docs/Config-Documentation.md +++ b/docs/Config-Documentation.md @@ -64,6 +64,7 @@ The config file can be found at `config/EssentialCommands.properties` | nickname_above_head | false | boolean | | nickname_max_length | 32 | integer | | nickname_prefix | {"text":"~","color":"red"} | MinecraftText | +| nickname_style_perms_check_target | false | boolean | | nicknames_as_command_arg | Never | NicknameCommandArgMode | | nicknames_in_player_list | true | boolean | | nicknames_must_be_unique | false | boolean | diff --git a/docs/Feature-Guide.md b/docs/Feature-Guide.md index 9bdb50da..a3135f35 100644 --- a/docs/Feature-Guide.md +++ b/docs/Feature-Guide.md @@ -225,6 +225,7 @@ The `` is [MinecraftText](./Minecraft-Text.md), meaning it can be one - `EssentialCommandsOnly` - Nicknames resolve and suggest only in Essential Commands - `Everywhere` - Nicknames resolve and suggest in all commands (e.g. `/tp`, `/give`) - `nicknames_must_be_unique` - Block nicknames that duplicate another player's nickname or match an existing username (case-insensitive) - Default: `false` +- `nickname_style_perms_check_target` - If `true`, nickname style permissions (color, fancy, hover, click) are checked against the player receiving the nickname instead of the player running the command (the behavior before #300 was fixed) - Default: `false` ## Utility Commands diff --git a/src/main/java/com/fibermc/essentialcommands/commands/NicknameSetCommand.java b/src/main/java/com/fibermc/essentialcommands/commands/NicknameSetCommand.java index be430029..5fd45628 100644 --- a/src/main/java/com/fibermc/essentialcommands/commands/NicknameSetCommand.java +++ b/src/main/java/com/fibermc/essentialcommands/commands/NicknameSetCommand.java @@ -39,26 +39,27 @@ public static int runStringToText(CommandContext context) th public static int exec(CommandContext context, Component rawNicknameText) throws CommandSyntaxException { ServerPlayer targetPlayer = CommandUtil.getCommandTargetPlayer(context); + var sender = context.getSource(); - var nicknameWithContext = ECPerms.check(context.getSource(), ECPerms.Registry.nickname_selector_and_ctx, 2) + var nicknameWithContext = ECPerms.check(sender, ECPerms.Registry.nickname_selector_and_ctx, 2) ? ComponentUtils.resolve( ResolutionContext.builder() - .withSource(context.getSource()) + .withSource(sender) .withEntityOverride(targetPlayer) .build(), rawNicknameText, 0) : rawNicknameText; - var nicknameText = ECPerms.check(context.getSource(), ECPerms.Registry.nickname_placeholders, 2) + var nicknameText = ECPerms.check(sender, ECPerms.Registry.nickname_placeholders, 2) ? TagParser.DEFAULT_SAFE.parseComponent(TextNode.convert(nicknameWithContext), ParserContext.of()) : nicknameWithContext; - int successCode = PlayerData.access(targetPlayer).setNickname(nicknameText); - var senderPlayer = context.getSource().getPlayer(); - var senderFeedbackReceiver = FeedbackReceiver.ofSource(context.getSource()); + int successCode = PlayerData.access(targetPlayer).setNickname(nicknameText, sender); - var ecText = ECText.access(senderPlayer); + var senderFeedbackReceiver = FeedbackReceiver.ofSource(sender); + + var ecText = ECText.access(sender.getPlayer()); //inform command sender that the nickname has been set if (successCode >= 0) { diff --git a/src/main/java/com/fibermc/essentialcommands/config/EssentialCommandsConfig.java b/src/main/java/com/fibermc/essentialcommands/config/EssentialCommandsConfig.java index 753579d3..fdfea155 100644 --- a/src/main/java/com/fibermc/essentialcommands/config/EssentialCommandsConfig.java +++ b/src/main/java/com/fibermc/essentialcommands/config/EssentialCommandsConfig.java @@ -92,6 +92,7 @@ public final class EssentialCommandsConfig extends Config NICKNAMES_AS_COMMAND_ARG = new Option<>("nicknames_as_command_arg", NicknameCommandArgMode.Never, NicknameCommandArgMode::valueOf); @ConfigOption public final Option NICKNAMES_MUST_BE_UNIQUE = new Option<>("nicknames_must_be_unique", false, Boolean::parseBoolean); @ConfigOption public final Option NICKNAME_ABOVE_HEAD = new Option<>("nickname_above_head", false, Boolean::parseBoolean); + @ConfigOption public final Option NICKNAME_STYLE_PERMS_CHECK_TARGET = new Option<>("nickname_style_perms_check_target", false, Boolean::parseBoolean); @ConfigOption public final Option RTP_CENTER = new Option<>("rtp_center", RtpCenter.spawn(), RtpCenter::parse, RtpCenter::serialize); @ConfigOption public final Option RTP_RADIUS = new Option<>("rtp_radius", 1000, ConfigUtil::parseInt); @ConfigOption public final Option RTP_MIN_RADIUS = new Option<>("rtp_min_radius", RTP_RADIUS.getValue(), (String s) -> parseIntOrDefault(s, RTP_RADIUS.getValue())); diff --git a/src/main/java/com/fibermc/essentialcommands/config/EssentialCommandsConfigSnapshot.java b/src/main/java/com/fibermc/essentialcommands/config/EssentialCommandsConfigSnapshot.java index 98f103c0..8cab729a 100644 --- a/src/main/java/com/fibermc/essentialcommands/config/EssentialCommandsConfigSnapshot.java +++ b/src/main/java/com/fibermc/essentialcommands/config/EssentialCommandsConfigSnapshot.java @@ -70,6 +70,7 @@ public final class EssentialCommandsConfigSnapshot { public final int NICKNAME_MAX_LENGTH; public final NicknameCommandArgMode NICKNAMES_AS_COMMAND_ARG; public final boolean NICKNAMES_MUST_BE_UNIQUE; + public final boolean NICKNAME_STYLE_PERMS_CHECK_TARGET; public final boolean NICKNAME_ABOVE_HEAD; public final RtpCenter RTP_CENTER; public final int RTP_RADIUS; @@ -151,6 +152,7 @@ private EssentialCommandsConfigSnapshot(EssentialCommandsConfig config) { this.NICKNAME_MAX_LENGTH = config.NICKNAME_MAX_LENGTH.getValue(); this.NICKNAMES_AS_COMMAND_ARG = config.NICKNAMES_AS_COMMAND_ARG.getValue(); this.NICKNAMES_MUST_BE_UNIQUE = config.NICKNAMES_MUST_BE_UNIQUE.getValue(); + this.NICKNAME_STYLE_PERMS_CHECK_TARGET = config.NICKNAME_STYLE_PERMS_CHECK_TARGET.getValue(); this.NICKNAME_ABOVE_HEAD = config.NICKNAME_ABOVE_HEAD.getValue(); this.RTP_CENTER = config.RTP_CENTER.getValue(); this.RTP_RADIUS = config.RTP_RADIUS.getValue(); diff --git a/src/main/java/com/fibermc/essentialcommands/playerdata/PlayerData.java b/src/main/java/com/fibermc/essentialcommands/playerdata/PlayerData.java index b82cb0bb..fe63bf92 100644 --- a/src/main/java/com/fibermc/essentialcommands/playerdata/PlayerData.java +++ b/src/main/java/com/fibermc/essentialcommands/playerdata/PlayerData.java @@ -514,6 +514,10 @@ public MutableComponent copyFullNickname() { } public int setNickname(Component nickname) { + return setNickname(nickname, this.player.createCommandSourceStack()); + } + + public int setNickname(Component nickname, CommandSourceStack actorPermsSrc) { String oldNormalizedNickname = this.normalizedNickname; int resultCode = 0; // Reset nickname @@ -530,23 +534,31 @@ public int setNickname(Component nickname) { if (nickname.getString().length() > CONFIG.NICKNAME_MAX_LENGTH) { return -2; } + + // By default, the person running the command needs the style permissions (color, fancy, etc.). + // nickname_style_perms_check_target=true restores the old behavior of checking the target player. + var permissionSource = CONFIG.NICKNAME_STYLE_PERMS_CHECK_TARGET + ? this.player.createCommandSourceStack() + : actorPermsSrc; + // Ensure player has permissions required to set the specified nickname - boolean hasRequiredPerms = NicknameTextUtil.checkPerms(nickname, this.player.createCommandSourceStack()); + boolean hasRequiredPerms = NicknameTextUtil.checkPerms(nickname, permissionSource); if (!hasRequiredPerms) { EssentialCommands.LOGGER.info( - "{} attempted to set nickname to '{}', with insufficient permissions to do so.", + "{} attempted to set {}'s nickname to '{}', with insufficient permissions to do so.", + permissionSource.getTextName(), this.player.getGameProfile().name(), nickname ); return -1; - } else { - EssentialCommands.LOGGER.info( - "Set {}'s nickname to '{}'.", - this.player.getGameProfile().name(), - nickname - ); } + EssentialCommands.LOGGER.info( + "Set {}'s nickname to '{}'.", + this.player.getGameProfile().name(), + nickname + ); + String candidateNormalized = normalizeNickname(nickname.getString()); if (CONFIG.NICKNAMES_MUST_BE_UNIQUE) {