Readd dead redirect recovery (#12136)

While the paper command system no longer uses redirects for namespaced
registration, vanilla still does. This means that removal of vanilla
redirecting target nodes still causes issues, e.g. the removal of the
vanilla 'msg' node in favour of a command alias one.
Redirecting nodes like tell, minecraft:msg and minecraft:tell are broken
by this and need to by flattened before sending them to the client.
This commit is contained in:
Bjarne Koll
2025-02-17 23:51:52 +01:00
committed by GitHub
parent fd69140d80
commit 3b9106c7d1

View File

@@ -144,7 +144,7 @@
}
return null;
@@ -360,26 +_,85 @@
@@ -360,26 +_,120 @@
}
public void sendCommands(ServerPlayer player) {
@@ -226,6 +226,41 @@
+ if (!org.spigotmc.SpigotConfig.sendNamespaced && commandNode.getName().contains(":")) continue; // Spigot
if (commandNode.canUse(source)) {
ArgumentBuilder<SharedSuggestionProvider, ?> argumentBuilder = (ArgumentBuilder) commandNode.createBuilder();
+ // Paper start
+ /*
+ Because of how commands can be yeeted right left and center due to bad bukkit practices
+ we need to be able to ensure that ALL commands are registered (even redirects).
+
+ What this will do is IF the redirect seems to be "dead" it will create a builder and essentially populate (flatten)
+ all the children from the dead redirect to the node.
+
+ So, if minecraft:msg redirects to msg but the original msg node has been overriden minecraft:msg will now act as msg and will explicilty inherit its children.
+
+ The only way to fix this is to either:
+ - Send EVERYTHING flattened, don't use redirects
+ - Don't allow command nodes to be deleted
+ - Do this :)
+ */
+ // Is there an invalid command redirect?
+ if (argumentBuilder.getRedirect() != null && commandNodeToSuggestionNode.get(argumentBuilder.getRedirect()) == null) {
+ // Create the argument builder with the same values as the specified node, but with a different literal and populated children
+
+ final CommandNode<SharedSuggestionProvider> redirect = argumentBuilder.getRedirect();
+ // Diff copied from LiteralCommand#createBuilder
+ final com.mojang.brigadier.builder.LiteralArgumentBuilder<SharedSuggestionProvider> builder = com.mojang.brigadier.builder.LiteralArgumentBuilder.literal(commandNode.getName());
+ builder.requires(redirect.getRequirement());
+ // builder.forward(redirect.getRedirect(), redirect.getRedirectModifier(), redirect.isFork()); We don't want to migrate the forward, since it's invalid.
+ if (redirect.getCommand() != null) {
+ builder.executes(redirect.getCommand());
+ }
+ // Diff copied from LiteralCommand#createBuilder
+ for (final CommandNode<SharedSuggestionProvider> child : redirect.getChildren()) {
+ builder.then(child);
+ }
+
+ argumentBuilder = builder;
+ }
+ // Paper end
argumentBuilder.requires(suggestions -> true);
- if (argumentBuilder.getCommand() != null) {
- argumentBuilder.executes(commandContext -> 0);