From 4c64fd66b0c998e17976280cc2a79c5ddbe70699 Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Sat, 4 May 2024 15:48:49 -0700 Subject: [PATCH] more docs & tweaks --- .../0477-Brigadier-based-command-API.patch | 54 ++++----- .../1046-Brigadier-based-command-API.patch | 113 ++++++++++-------- 2 files changed, 90 insertions(+), 77 deletions(-) diff --git a/patches/api/0477-Brigadier-based-command-API.patch b/patches/api/0477-Brigadier-based-command-API.patch index e8d44721fb..606f2fd876 100644 --- a/patches/api/0477-Brigadier-based-command-API.patch +++ b/patches/api/0477-Brigadier-based-command-API.patch @@ -394,10 +394,10 @@ index 0000000000000000000000000000000000000000..2db12952461c92a64505d6646f6f49f8 +} diff --git a/src/main/java/io/papermc/paper/command/brigadier/argument/ArgumentTypes.java b/src/main/java/io/papermc/paper/command/brigadier/argument/ArgumentTypes.java new file mode 100644 -index 0000000000000000000000000000000000000000..a3fc1fd8ae82da1ef69e3de97d6181bb1b0404f2 +index 0000000000000000000000000000000000000000..8109abe46b166c335d05a2cc25e91010aa4fa0f5 --- /dev/null +++ b/src/main/java/io/papermc/paper/command/brigadier/argument/ArgumentTypes.java -@@ -0,0 +1,316 @@ +@@ -0,0 +1,315 @@ +package io.papermc.paper.command.brigadier.argument; + +import com.mojang.brigadier.arguments.ArgumentType; @@ -441,10 +441,6 @@ index 0000000000000000000000000000000000000000..a3fc1fd8ae82da1ef69e3de97d6181bb + static final Optional PROVIDER = ServiceLoader.load(VanillaArgumentProvider.class) + .findFirst(); + -+ @ApiStatus.Internal -+ ArgumentTypes() { -+ } -+ + /** + * Represents a selector that can capture any + * entity. @@ -712,14 +708,17 @@ index 0000000000000000000000000000000000000000..a3fc1fd8ae82da1ef69e3de97d6181bb + + private static VanillaArgumentProvider provider() { + return PROVIDER.orElseThrow(); -+ } ++ } ++ ++ private ArgumentTypes() { ++ } +} diff --git a/src/main/java/io/papermc/paper/command/brigadier/argument/CustomArgumentType.java b/src/main/java/io/papermc/paper/command/brigadier/argument/CustomArgumentType.java new file mode 100644 -index 0000000000000000000000000000000000000000..5d33e1e04b1f279d6ad6371d0cfd9f129fcd8370 +index 0000000000000000000000000000000000000000..02acac7f9186677d19c0a62095cc3012bc112961 --- /dev/null +++ b/src/main/java/io/papermc/paper/command/brigadier/argument/CustomArgumentType.java -@@ -0,0 +1,107 @@ +@@ -0,0 +1,106 @@ +package io.papermc.paper.command.brigadier.argument; + +import com.mojang.brigadier.StringReader; @@ -735,28 +734,28 @@ index 0000000000000000000000000000000000000000..5d33e1e04b1f279d6ad6371d0cfd9f12 + +/** + * An argument type that wraps around a native-to-vanilla argument type. -+ * This argument type is special in that the underlying native argument type will -+ * be sent to the client. ++ * This argument receives special handling in that the native argument type will ++ * be sent to the client for possible client-side completions and syntax validation. + *

-+ * When extending this class, you have to implement your own parsing logic. If -+ * you want to have the command value parsed into the native type and then -+ * converted to your custom type, use {@link Converted}. ++ * When implementing this class, you have to create your own parsing logic from a ++ * {@link StringReader}. If only want to convert from the native type ({@code N}) to the custom ++ * type ({@code T}), implement {@link Converted} instead. + * + * @param custom type -+ * @param type with an argument native to minecraft ++ * @param type with an argument native to vanilla Minecraft (from {@link ArgumentTypes}) + */ +@ApiStatus.Experimental +public interface CustomArgumentType extends ArgumentType { + + /** -+ * Parses the argument using the native argument type. Keep in mind ++ * Parses the argument into the custom type ({@code T}). Keep in mind + * that this parsing will be done on the server. This means that if + * you throw a {@link CommandSyntaxException} during parsing, this -+ * will only show on the server after the user has executed the command -+ * not while they are still typing it in. ++ * will only show up to the user after the user has executed the command ++ * not while they are still entering it. + * -+ * @param reader string reader -+ * @return value ++ * @param reader string reader input ++ * @return parsed value + * @throws CommandSyntaxException if an error occurs while parsing + */ + @Override @@ -764,7 +763,7 @@ index 0000000000000000000000000000000000000000..5d33e1e04b1f279d6ad6371d0cfd9f12 + + /** + * Gets the native type that this argument uses, -+ * or the type that is sent to the client. ++ * the type that is sent to the client. + * + * @return native argument type + */ @@ -798,15 +797,14 @@ index 0000000000000000000000000000000000000000..5d33e1e04b1f279d6ad6371d0cfd9f12 + + /** + * An argument type that wraps around a native-to-vanilla argument type. -+ * This argument is special in that the underlying native argument type -+ * will be sent to the client. ++ * This argument receives special handling in that the native argument type will ++ * be sent to the client for possible client-side completions and syntax validation. + *

-+ * The parsed native type will be converted via the implementation of -+ * {@link #convert(Object)}. Use {@link CustomArgumentType} if you want -+ * to handle parsing the type yourself. ++ * The parsed native type will be converted via {@link #convert(Object)}. ++ * Implement {@link CustomArgumentType} if you want to handle parsing the type manually. + * + * @param custom type -+ * @param native type (has an argument native to vanilla Minecraft). ++ * @param type with an argument native to vanilla Minecraft (from {@link ArgumentTypes}) + */ + @ApiStatus.Experimental + interface Converted extends CustomArgumentType { @@ -818,7 +816,7 @@ index 0000000000000000000000000000000000000000..5d33e1e04b1f279d6ad6371d0cfd9f12 + } + + /** -+ * Converts the value from the native type to this argument type. ++ * Converts the value from the native type to the custom argument type. + * + * @param nativeType native argument provided value + * @return converted value diff --git a/patches/server/1046-Brigadier-based-command-API.patch b/patches/server/1046-Brigadier-based-command-API.patch index 26b28ea734..135b77849f 100644 --- a/patches/server/1046-Brigadier-based-command-API.patch +++ b/patches/server/1046-Brigadier-based-command-API.patch @@ -94,10 +94,10 @@ index dd6012b6a097575b2d1471be5069eccee4537c0a..00000000000000000000000000000000 -} diff --git a/src/main/java/io/papermc/paper/command/brigadier/ApiMirrorRootNode.java b/src/main/java/io/papermc/paper/command/brigadier/ApiMirrorRootNode.java new file mode 100644 -index 0000000000000000000000000000000000000000..7c7a281ec145c9ffdc8a16739579435f3899f33a +index 0000000000000000000000000000000000000000..fdca7b774e3465bd8625cb4129ddaedfa75ab28c --- /dev/null +++ b/src/main/java/io/papermc/paper/command/brigadier/ApiMirrorRootNode.java -@@ -0,0 +1,251 @@ +@@ -0,0 +1,256 @@ +package io.papermc.paper.command.brigadier; + +import com.google.common.collect.Collections2; @@ -169,44 +169,49 @@ index 0000000000000000000000000000000000000000..7c7a281ec145c9ffdc8a16739579435f + * This logic is responsible for unwrapping an API node to be supported by NMS. + * See the method implementation for detailed steps. + * -+ * @param wrapped api provided node / node to be "wrapped" ++ * @param maybeWrappedNode api provided node / node to be "wrapped" + * @return wrapped node + */ + @SuppressWarnings({"rawtypes", "unchecked"}) -+ private @NotNull CommandNode unwrapNode(CommandNode wrapped) { ++ private @NotNull CommandNode unwrapNode(final CommandNode maybeWrappedNode) { + /* + If the type is a shadow node we can assume that the type that it represents is an already supported NMS node. + This is because these are typically minecraft command nodes. + */ -+ if (wrapped instanceof ShadowBrigNode shadowBrigNode) { ++ if (maybeWrappedNode instanceof final ShadowBrigNode shadowBrigNode) { + return (CommandNode) shadowBrigNode.getHandle(); + } + + /* + This node already has had an unwrapped node created, so we can assume that it's safe to reuse that cached copy. + */ -+ if (wrapped.unwrappedCached != null) { -+ return wrapped.unwrappedCached; ++ if (maybeWrappedNode.unwrappedCached != null) { ++ return maybeWrappedNode.unwrappedCached; + } + ++ // convert the pure brig node into one compatible with the nms dispatcher ++ return this.convertFromPureBrigNode(maybeWrappedNode); ++ } ++ ++ private @NotNull CommandNode convertFromPureBrigNode(final CommandNode pureNode) { + /* -+ Logic for wrapping each node. ++ Logic for converting a node. + */ -+ CommandNode unwrapped; -+ if (wrapped instanceof LiteralCommandNode node) { ++ final CommandNode converted; ++ if (pureNode instanceof final LiteralCommandNode node) { + /* + Remap the literal node, we only have to account + for the redirect in this case. + */ -+ unwrapped = this.simpleUnwrap(node); -+ } else if (wrapped instanceof ArgumentCommandNode original) { -+ ArgumentType unwrappedArgType = original.getType(); ++ converted = this.simpleUnwrap(node); ++ } else if (pureNode instanceof final ArgumentCommandNode pureArgumentNode) { ++ final ArgumentType pureArgumentType = pureArgumentNode.getType(); + /* + Check to see if this argument type is a wrapped type, if so we know that + we can unwrap the node to get an NMS type. + */ -+ if (unwrappedArgType instanceof CustomArgumentType customArgumentType) { -+ final SuggestionProvider suggestionProvider; ++ if (pureArgumentType instanceof final CustomArgumentType customArgumentType) { ++ final SuggestionProvider suggestionProvider; + try { + final Method listSuggestions = customArgumentType.getClass().getMethod("listSuggestions", CommandContext.class, SuggestionsBuilder.class); + if (listSuggestions.getDeclaringClass() != CustomArgumentType.class) { @@ -218,22 +223,22 @@ index 0000000000000000000000000000000000000000..7c7a281ec145c9ffdc8a16739579435f + throw new IllegalStateException("Could not determine if the custom argument type " + customArgumentType + " overrides listSuggestions", ex); + } + -+ unwrapped = this.unwrapArgumentWrapper(original, customArgumentType, customArgumentType.getNativeType(), suggestionProvider); -+ } else if (unwrappedArgType instanceof VanillaArgumentProviderImpl.NativeWrapperArgumentType nativeWrapperArgumentType) { -+ unwrapped = this.unwrapArgumentWrapper(original, nativeWrapperArgumentType, nativeWrapperArgumentType, null); // "null" for suggestion provider so it uses the argument type's suggestion provider ++ converted = this.unwrapArgumentWrapper(pureArgumentNode, customArgumentType, customArgumentType.getNativeType(), suggestionProvider); ++ } else if (pureArgumentType instanceof final VanillaArgumentProviderImpl.NativeWrapperArgumentType nativeWrapperArgumentType) { ++ converted = this.unwrapArgumentWrapper(pureArgumentNode, nativeWrapperArgumentType, nativeWrapperArgumentType, null); // "null" for suggestion provider so it uses the argument type's suggestion provider + + /* + If it's not a wrapped type, it either has to be a primitive or an already + defined NMS type. + This method allows us to check if this is recognized by vanilla. + */ -+ } else if (ArgumentTypeInfos.isClassRecognized(unwrappedArgType.getClass())) { -+ if (ARGUMENT_WHITELIST.contains(unwrappedArgType.getClass())) { ++ } else if (ArgumentTypeInfos.isClassRecognized(pureArgumentType.getClass())) { ++ if (ARGUMENT_WHITELIST.contains(pureArgumentType.getClass())) { + // If this argument is whitelisted simply unwrap it and ignore the argument type. -+ unwrapped = this.simpleUnwrap(original); ++ converted = this.simpleUnwrap(pureArgumentNode); + } else { + // If this was an NMS type but not a primitive -+ throw new IllegalArgumentException("NMS argument type was passed (%s), should be wrapped inside an CustomArgumentType. Don't add NMS args here!".formatted(unwrappedArgType)); ++ throw new IllegalArgumentException("NMS argument type was passed (%s), should be wrapped inside an CustomArgumentType. Don't add NMS args here!".formatted(pureArgumentType)); + } + } else { + // Unknown argument type was passed @@ -246,14 +251,14 @@ index 0000000000000000000000000000000000000000..7c7a281ec145c9ffdc8a16739579435f + /* + Add the children to the node, unwrapping each child in the process. + */ -+ for (CommandNode child : wrapped.getChildren()) { -+ unwrapped.addChild(this.unwrapNode(child)); ++ for (final CommandNode child : pureNode.getChildren()) { ++ converted.addChild(this.unwrapNode(child)); + } + -+ unwrapped.wrappedCached = wrapped; -+ wrapped.unwrappedCached = unwrapped; ++ converted.wrappedCached = pureNode; ++ pureNode.unwrappedCached = converted; + -+ return unwrapped; ++ return converted; + } + + /** @@ -268,7 +273,7 @@ index 0000000000000000000000000000000000000000..7c7a281ec145c9ffdc8a16739579435f + * @param unwrapped argument node + * @return wrapped node + */ -+ private @Nullable CommandNode wrapNode(@Nullable CommandNode unwrapped) { ++ private @Nullable CommandNode wrapNode(@Nullable final CommandNode unwrapped) { + if (unwrapped == null) { + return null; + } @@ -332,17 +337,17 @@ index 0000000000000000000000000000000000000000..7c7a281ec145c9ffdc8a16739579435f + } + + @SuppressWarnings({"rawtypes", "unchecked"}) -+ private CommandNode unwrapArgumentWrapper(final ArgumentCommandNode node, final ArgumentType wrappedArgumentType, final ArgumentType possiblyWrappedNativeArgumentType, @Nullable SuggestionProvider argumentTypeSuggestionProvider) { ++ private CommandNode unwrapArgumentWrapper(final ArgumentCommandNode pureNode, final ArgumentType pureArgumentType, final ArgumentType possiblyWrappedNativeArgumentType, @Nullable SuggestionProvider argumentTypeSuggestionProvider) { + validatePrimitiveType(possiblyWrappedNativeArgumentType); -+ final CommandNode redirectNode = node.getRedirect() == null ? null : this.unwrapNode(node.getRedirect()); ++ final CommandNode redirectNode = pureNode.getRedirect() == null ? null : this.unwrapNode(pureNode.getRedirect()); + // If there is already a custom suggestion provider, ignore the suggestion provider from the argument type -+ final SuggestionProvider suggestionProvider = node.getCustomSuggestions() != null ? node.getCustomSuggestions() : argumentTypeSuggestionProvider; ++ final SuggestionProvider suggestionProvider = pureNode.getCustomSuggestions() != null ? pureNode.getCustomSuggestions() : argumentTypeSuggestionProvider; + -+ ArgumentType nativeArgumentType = possiblyWrappedNativeArgumentType instanceof VanillaArgumentProviderImpl.NativeWrapperArgumentType nativeWrapperArgumentType ? nativeWrapperArgumentType.nativeNmsArgumentType() : possiblyWrappedNativeArgumentType; -+ return new WrappedArgumentCommandNode<>(node.getName(), wrappedArgumentType, nativeArgumentType, node.getCommand(), node.getRequirement(), redirectNode, node.getRedirectModifier(), node.isFork(), suggestionProvider); ++ final ArgumentType nativeArgumentType = possiblyWrappedNativeArgumentType instanceof final VanillaArgumentProviderImpl.NativeWrapperArgumentType nativeWrapperArgumentType ? nativeWrapperArgumentType.nativeNmsArgumentType() : possiblyWrappedNativeArgumentType; ++ return new WrappedArgumentCommandNode<>(pureNode.getName(), pureArgumentType, nativeArgumentType, pureNode.getCommand(), pureNode.getRequirement(), redirectNode, pureNode.getRedirectModifier(), pureNode.isFork(), suggestionProvider); + } + -+ private CommandNode simpleUnwrap(CommandNode node) { ++ private CommandNode simpleUnwrap(final CommandNode node) { + return node.createBuilder() + .redirect(node.getRedirect() == null ? null : this.unwrapNode(node.getRedirect())) + .build(); @@ -377,7 +382,7 @@ index 0000000000000000000000000000000000000000..0b33c6cf2366568641e6f2fd7f74fb74 +} diff --git a/src/main/java/io/papermc/paper/command/brigadier/PaperBrigadier.java b/src/main/java/io/papermc/paper/command/brigadier/PaperBrigadier.java new file mode 100644 -index 0000000000000000000000000000000000000000..82a57ffc048454fbc4c705adbac83d16c44c5054 +index 0000000000000000000000000000000000000000..44715db12d6be06a7655f1bbb5ebb35ea904eb3b --- /dev/null +++ b/src/main/java/io/papermc/paper/command/brigadier/PaperBrigadier.java @@ -0,0 +1,56 @@ @@ -398,7 +403,7 @@ index 0000000000000000000000000000000000000000..82a57ffc048454fbc4c705adbac83d16 + +import java.util.Map; + -+public class PaperBrigadier { ++public final class PaperBrigadier { + + @SuppressWarnings({"unchecked", "rawtypes"}) + public static Command wrapNode(CommandNode node) { @@ -1187,10 +1192,10 @@ index 0000000000000000000000000000000000000000..5f4af57f2054aa278fcc34697fefa0ed +} diff --git a/src/main/java/io/papermc/paper/command/brigadier/argument/WrappedArgumentCommandNode.java b/src/main/java/io/papermc/paper/command/brigadier/argument/WrappedArgumentCommandNode.java new file mode 100644 -index 0000000000000000000000000000000000000000..7a838bab16b33025b9a2eae8325f353ad9689e1b +index 0000000000000000000000000000000000000000..c59bbd90fdf04db837366218b312e7fb80366707 --- /dev/null +++ b/src/main/java/io/papermc/paper/command/brigadier/argument/WrappedArgumentCommandNode.java -@@ -0,0 +1,45 @@ +@@ -0,0 +1,55 @@ +package io.papermc.paper.command.brigadier.argument; + +import com.mojang.brigadier.Command; @@ -1213,23 +1218,33 @@ index 0000000000000000000000000000000000000000..7a838bab16b33025b9a2eae8325f353a + */ +public class WrappedArgumentCommandNode extends ArgumentCommandNode { + -+ private final ArgumentType argument; ++ private final ArgumentType pureArgumentType; + -+ public WrappedArgumentCommandNode(String name, ArgumentType argument, ArgumentType nms, Command command, Predicate requirement, CommandNode redirect, RedirectModifier modifier, boolean forks, SuggestionProvider customSuggestions) { -+ super(name, nms, command, requirement, redirect, modifier, forks, customSuggestions); -+ if (!ArgumentTypeInfos.isClassRecognized(nms.getClass())) { ++ public WrappedArgumentCommandNode( ++ final String name, ++ final ArgumentType pureArgumentType, ++ final ArgumentType nmsNativeType, ++ final Command command, ++ final Predicate requirement, ++ final CommandNode redirect, ++ final RedirectModifier modifier, ++ final boolean forks, ++ final SuggestionProvider customSuggestions ++ ) { ++ super(name, nmsNativeType, command, requirement, redirect, modifier, forks, customSuggestions); ++ if (!ArgumentTypeInfos.isClassRecognized(nmsNativeType.getClass())) { + // Is this argument an NMS argument? -+ throw new IllegalArgumentException("Unexpected argument type was passed. This should be an NMS type!"); ++ throw new IllegalArgumentException("Unexpected argument type was passed: " + nmsNativeType.getClass() + ". This should be an NMS type!"); + } + -+ this.argument = argument; ++ this.pureArgumentType = pureArgumentType; + } + + // See ArgumentCommandNode#parse + @Override -+ public void parse(StringReader reader, CommandContextBuilder contextBuilder) throws CommandSyntaxException { ++ public void parse(final StringReader reader, final CommandContextBuilder contextBuilder) throws CommandSyntaxException { + final int start = reader.getCursor(); -+ API result = this.argument.parse(reader); // Use the api argument parser ++ final API result = this.pureArgumentType.parse(reader); // Use the api argument parser + final ParsedArgument parsed = new ParsedArgument<>(start, reader.getCursor(), result); // Return an API parsed argument instead. + + contextBuilder.withArgument(this.getName(), parsed); @@ -1238,7 +1253,7 @@ index 0000000000000000000000000000000000000000..7a838bab16b33025b9a2eae8325f353a +} diff --git a/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitBrigForwardingMap.java b/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitBrigForwardingMap.java new file mode 100644 -index 0000000000000000000000000000000000000000..685b3da3f294d8c6ab0fe74d1485a81b03f3215a +index 0000000000000000000000000000000000000000..f0cc27640bb3db275295a298d608c9d9f88df617 --- /dev/null +++ b/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitBrigForwardingMap.java @@ -0,0 +1,332 @@ @@ -1305,8 +1320,8 @@ index 0000000000000000000000000000000000000000..685b3da3f294d8c6ab0fe74d1485a81b + } + + @Override -+ public boolean containsValue(Object value) { -+ if (value == null) { ++ public boolean containsValue(@Nullable final Object value) { ++ if (!(value instanceof Command)) { + return false; + } +