From ea24e2c6aa5a6b230af2edb7c1f65d6d7b8d9a22 Mon Sep 17 00:00:00 2001 From: Rick Date: Tue, 26 Nov 2024 20:45:52 +0100 Subject: [PATCH] Fix incorrect command serialization by creating new Command Fixes #11649 - As noted in the issue, when CommandNodes are serialized they are used as the key in a Map. Their equals()/hashcode() should only match if they are equal nodes (name & command), but due to the erasure of the command field pre-serialization, nodes with different commands can be mapped onto the same value. This causes the client to interpret both nodes as the same, causing suggestions where they should not. This is fixed by creating a different no-op command for the erasure, instead of them holding the same lambda. --- .../minecraft/commands/Commands.java.patch | 43 +++++++++++++------ 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/paper-server/patches/sources/net/minecraft/commands/Commands.java.patch b/paper-server/patches/sources/net/minecraft/commands/Commands.java.patch index e54c063624..1fc19d5217 100644 --- a/paper-server/patches/sources/net/minecraft/commands/Commands.java.patch +++ b/paper-server/patches/sources/net/minecraft/commands/Commands.java.patch @@ -1,9 +1,10 @@ --- a/net/minecraft/commands/Commands.java +++ b/net/minecraft/commands/Commands.java -@@ -139,6 +139,14 @@ +@@ -138,6 +138,14 @@ + import net.minecraft.world.flag.FeatureFlags; import net.minecraft.world.level.GameRules; import org.slf4j.Logger; - ++ +// CraftBukkit start +import com.google.common.base.Joiner; +import java.util.Collection; @@ -11,10 +12,9 @@ +import org.bukkit.event.player.PlayerCommandSendEvent; +import org.bukkit.event.server.ServerCommandEvent; +// CraftBukkit end -+ + public class Commands { - private static final ThreadLocal> CURRENT_EXECUTION_CONTEXT = new ThreadLocal(); @@ -151,6 +159,7 @@ private final com.mojang.brigadier.CommandDispatcher dispatcher = new com.mojang.brigadier.CommandDispatcher(); @@ -92,14 +92,14 @@ - this.performCommand(this.dispatcher.parse(command, source), command); + // CraftBukkit start + this.performPrefixedCommand(source, command, command); - } - ++ } ++ + public void performPrefixedCommand(CommandSourceStack commandlistenerwrapper, String s, String label) { + s = s.startsWith("/") ? s.substring(1) : s; + this.performCommand(this.dispatcher.parse(s, commandlistenerwrapper), s, label); + // CraftBukkit end -+ } -+ + } + public void performCommand(ParseResults parseResults, String command) { - CommandSourceStack commandlistenerwrapper = (CommandSourceStack) parseResults.getContext().getSource(); + this.performCommand(parseResults, command, command); @@ -176,7 +176,7 @@ }); if (i > 10) { -@@ -333,7 +413,17 @@ +@@ -333,8 +413,18 @@ } ichatmutablecomponent.append((Component) Component.translatable("command.context.here").withStyle(ChatFormatting.RED, ChatFormatting.ITALIC)); @@ -186,15 +186,16 @@ + builder + .append(net.kyori.adventure.text.Component.newline()) + .append(io.papermc.paper.adventure.PaperAdventure.asAdventure(ichatmutablecomponent)); -+ } + } + org.bukkit.event.command.UnknownCommandEvent event = new org.bukkit.event.command.UnknownCommandEvent(commandlistenerwrapper.getBukkitSender(), s, org.spigotmc.SpigotConfig.unknownCommandMessage.isEmpty() ? null : builder.build()); + org.bukkit.Bukkit.getServer().getPluginManager().callEvent(event); + if (event.message() != null) { + commandlistenerwrapper.sendFailure(io.papermc.paper.adventure.PaperAdventure.asVanilla(event.message()), false); + // Paper end - Add UnknownCommandEvent - } ++ } return null; + } @@ -368,7 +458,7 @@ executioncontext1.close(); @@ -204,7 +205,7 @@ } } else { callback.accept(executioncontext); -@@ -377,23 +467,121 @@ +@@ -377,30 +467,133 @@ } public void sendCommands(ServerPlayer player) { @@ -331,7 +332,21 @@ argumentbuilder.requires((icompletionprovider) -> { return true; }); -@@ -415,12 +603,12 @@ + if (argumentbuilder.getCommand() != null) { +- argumentbuilder.executes((commandcontext) -> { +- return 0; ++ // Paper start - fix suggestions due to falsely equal nodes ++ argumentbuilder.executes(new com.mojang.brigadier.Command() { ++ @Override ++ public int run(com.mojang.brigadier.context.CommandContext commandContext) throws CommandSyntaxException { ++ return 0; ++ } + }); ++ // Paper end + } + + if (argumentbuilder instanceof RequiredArgumentBuilder) { +@@ -415,12 +608,12 @@ argumentbuilder.redirect((CommandNode) resultNodes.get(argumentbuilder.getRedirect())); } @@ -346,7 +361,7 @@ } } } -@@ -481,7 +669,7 @@ +@@ -481,7 +674,7 @@ } private HolderLookup.RegistryLookup.Delegate createLookup(final HolderLookup.RegistryLookup original) {