Skip to content

Instantly share code, notes, and snippets.

@aikar
Created June 18, 2020 06:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aikar/1f37e6d7c56541948d6d9adbf0939a6a to your computer and use it in GitHub Desktop.
Save aikar/1f37e6d7c56541948d6d9adbf0939a6a to your computer and use it in GitHub Desktop.
diff --git a/src/main/java/net/minecraft/server/CommandDispatcher.java b/src/main/java/net/minecraft/server/CommandDispatcher.java
index 2d512aa4f9a..34454a8efa6 100644
--- a/src/main/java/net/minecraft/server/CommandDispatcher.java
+++ b/src/main/java/net/minecraft/server/CommandDispatcher.java
@@ -1,5 +1,6 @@
package net.minecraft.server;
+import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Maps;
import com.mojang.brigadier.ParseResults;
import com.mojang.brigadier.StringReader;
@@ -13,6 +14,7 @@ import com.mojang.brigadier.tree.CommandNode;
import com.mojang.brigadier.tree.RootCommandNode;
import java.util.Collection;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import javax.annotation.Nullable;
@@ -250,17 +252,18 @@ public class CommandDispatcher {
private void sendAsync(EntityPlayer entityplayer) {
// Paper end - Async command map building
Map<CommandNode<CommandListenerWrapper>, CommandNode<ICompletionProvider>> map = Maps.newIdentityHashMap(); // Use identity to prevent aliasing issues
+ ArrayListMultimap<CommandNode, Runnable> pendingInit = ArrayListMultimap.create(); // CraftBukkit
RootCommandNode vanillaRoot = new RootCommandNode();
RootCommandNode<CommandListenerWrapper> vanilla = entityplayer.server.vanillaCommandDispatcher.a().getRoot();
map.put(vanilla, vanillaRoot);
- this.a(vanilla, vanillaRoot, entityplayer.getCommandListener(), (Map) map);
+ this.a(vanilla, vanillaRoot, entityplayer.getCommandListener(), (Map) map, pendingInit); // CraftBukkit
// Now build the global commands in a second pass
RootCommandNode<ICompletionProvider> rootcommandnode = new RootCommandNode();
map.put(this.b.getRoot(), rootcommandnode);
- this.a(this.b.getRoot(), rootcommandnode, entityplayer.getCommandListener(), (Map) map);
+ this.a(this.b.getRoot(), rootcommandnode, entityplayer.getCommandListener(), (Map) map, pendingInit); // CraftBukkit
Collection<String> bukkit = new LinkedHashSet<>();
for (CommandNode node : rootcommandnode.getChildren()) {
@@ -289,7 +292,7 @@ public class CommandDispatcher {
entityplayer.playerConnection.sendPacket(new PacketPlayOutCommands(rootcommandnode));
}
- private void a(CommandNode<CommandListenerWrapper> commandnode, CommandNode<ICompletionProvider> commandnode1, CommandListenerWrapper commandlistenerwrapper, Map<CommandNode<CommandListenerWrapper>, CommandNode<ICompletionProvider>> map) {
+ private void a(CommandNode<CommandListenerWrapper> commandnode, CommandNode<ICompletionProvider> commandnode1, CommandListenerWrapper commandlistenerwrapper, Map<CommandNode<CommandListenerWrapper>, CommandNode<ICompletionProvider>> map, ArrayListMultimap<CommandNode, Runnable> pendingInit) { // CraftBukkit
Iterator iterator = commandnode.getChildren().iterator();
while (iterator.hasNext()) {
@@ -316,22 +319,39 @@ public class CommandDispatcher {
}
}
- if (argumentbuilder.getRedirect() != null) {
- argumentbuilder.redirect((CommandNode) map.get(argumentbuilder.getRedirect()));
- }
-
- CommandNode commandnode3 = argumentbuilder.build(); // CraftBukkit - decompile error
-
- map.put(commandnode2, commandnode3);
- commandnode1.addChild(commandnode3);
- if (!commandnode2.getChildren().isEmpty()) {
- this.a(commandnode2, commandnode3, commandlistenerwrapper, map);
+ // CraftBukkit start
+ CommandNode target = argumentbuilder.getRedirect();
+ if (target != null) {
+ CommandNode clonedRef = map.get(target);
+ if (clonedRef == null) {
+ pendingInit.put(target, () -> {
+ // Should be set now
+ argumentbuilder.redirect(map.get(target));
+ addBuilder(commandnode1, commandlistenerwrapper, map, commandnode2, argumentbuilder, pendingInit);
+ });
+ continue;
+ }
+ argumentbuilder.redirect(clonedRef);
}
+ addBuilder(commandnode1, commandlistenerwrapper, map, commandnode2, argumentbuilder, pendingInit);
}
}
}
+ private void addBuilder(CommandNode<ICompletionProvider> commandnode1, CommandListenerWrapper commandlistenerwrapper, Map<CommandNode<CommandListenerWrapper>, CommandNode<ICompletionProvider>> map, CommandNode<CommandListenerWrapper> commandnode2, ArgumentBuilder argumentbuilder, ArrayListMultimap<CommandNode, Runnable> pendingInit) {
+ CommandNode commandnode3 = argumentbuilder.build(); // CraftBukkit - decompile error
+
+ map.put(commandnode2, commandnode3);
+ commandnode1.addChild(commandnode3);
+ if (!commandnode2.getChildren().isEmpty()) {
+ this.a(commandnode2, commandnode3, commandlistenerwrapper, map, pendingInit);
+ }
+ List<Runnable> pending = pendingInit.removeAll(commandnode2);
+ pending.forEach(Runnable::run);
+ }
+ // CraftBukkit end
+
public static LiteralArgumentBuilder<CommandListenerWrapper> a(String s) {
return LiteralArgumentBuilder.literal(s);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment