Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
--- a/com/mojang/brigadier/tree/CommandNode.java
+++ b/com/mojang/brigadier/tree/CommandNode.java
@@ -27,11 +_,22 @@
private final Map<String, CommandNode<S>> children = new LinkedHashMap<>();
@@ -24,14 +_,25 @@
import java.util.function.Predicate;

public abstract class CommandNode<S> implements Comparable<CommandNode<S>> {
- private final Map<String, CommandNode<S>> children = new LinkedHashMap<>();
+ public final Map<String, CommandNode<S>> children = Collections.synchronizedMap(new LinkedHashMap<>()); // Paper - Prevent concurrent modification when sending commands; public
private final Map<String, LiteralCommandNode<S>> literals = new LinkedHashMap<>();
private final Map<String, ArgumentCommandNode<S, ?>> arguments = new LinkedHashMap<>();
- private final Predicate<S> requirement;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@
}

return null;
@@ -399,17 +_,110 @@
@@ -399,17 +_,109 @@
}

public void sendCommands(ServerPlayer player) {
Expand All @@ -145,9 +145,7 @@
+ // CraftBukkit start
+ // Register Vanilla commands into builtRoot as before
+ // Paper start - Perf: Async command map building
+ // Copy root children to avoid concurrent modification during building
+ final java.util.Collection<CommandNode<CommandSourceStack>> commandNodes = new java.util.ArrayList<>(this.dispatcher.getRoot().getChildren());
+ COMMAND_SENDING_POOL.execute(() -> this.sendAsync(player, commandNodes));
+ COMMAND_SENDING_POOL.execute(() -> this.sendAsync(player));
+ }
+
+ // Fixed pool, but with discard policy
Expand All @@ -161,13 +159,12 @@
+ new java.util.concurrent.ThreadPoolExecutor.DiscardPolicy()
+ );
+
+ private void sendAsync(ServerPlayer player, java.util.Collection<CommandNode<CommandSourceStack>> dispatcherRootChildren) {
+ private void sendAsync(ServerPlayer player) {
+ // Paper end - Perf: Async command map building
Map<CommandNode<CommandSourceStack>, CommandNode<CommandSourceStack>> map = new HashMap<>();
RootCommandNode<CommandSourceStack> rootCommandNode = new RootCommandNode<>();
map.put(this.dispatcher.getRoot(), rootCommandNode);
- fillUsableCommands(this.dispatcher.getRoot(), rootCommandNode, player.createCommandSourceStack(), map);
+ fillUsableCommands(dispatcherRootChildren, rootCommandNode, player.createCommandSourceStack(), map); // Paper - Perf: Async command map building; pass copy of children
fillUsableCommands(this.dispatcher.getRoot(), rootCommandNode, player.createCommandSourceStack(), map);
+
+ java.util.Collection<String> bukkit = new java.util.LinkedHashSet<>();
+ for (CommandNode node : rootCommandNode.getChildren()) {
Expand Down Expand Up @@ -197,9 +194,9 @@
}

- private static <S> void fillUsableCommands(CommandNode<S> root, CommandNode<S> current, S source, Map<CommandNode<S>, CommandNode<S>> output) {
- for (CommandNode<S> commandNode : root.getChildren()) {
+ private static <S> void fillUsableCommands(java.util.Collection<CommandNode<S>> children, CommandNode<S> current, S source, Map<CommandNode<S>, CommandNode<S>> output) { // Paper - Perf: Async command map building; pass copy of children
+ for (CommandNode<S> commandNode : children) { // Paper - Perf: Async command map building; pass copy of children
+ private static <S> void fillUsableCommands(CommandNode<S> root, CommandNode<S> current, S source, Map<CommandNode<S>, CommandNode<S>> output) { // Paper - Perf: Async command map building; pass copy of children
+ synchronized (root.children) { // Paper - Perf: Async command map building
for (CommandNode<S> commandNode : root.getChildren()) {
+ // Paper start - Brigadier API
+ if (commandNode.clientNode != null) {
+ commandNode = commandNode.clientNode;
Expand Down Expand Up @@ -246,12 +243,11 @@
if (argumentBuilder.getRedirect() != null) {
argumentBuilder.redirect(output.get(argumentBuilder.getRedirect()));
}
@@ -418,7 +_,7 @@
output.put(commandNode, commandNode1);
current.addChild(commandNode1);
if (!commandNode.getChildren().isEmpty()) {
- fillUsableCommands(commandNode, commandNode1, source, output);
+ fillUsableCommands(commandNode.getChildren(), commandNode1, source, output); // Paper - Perf: Async command map building; pass copy of children
@@ -422,6 +_,7 @@
}
}
}
+ } // Paper - Perf: Async command map building
}

public static LiteralArgumentBuilder<CommandSourceStack> literal(String name) {
Loading