From 3c7aa7f36f03badb3e04e9f20a4b9a3290f5237b Mon Sep 17 00:00:00 2001 From: DerEchtePilz Date: Thu, 8 Jun 2023 19:29:08 +0200 Subject: [PATCH 01/28] Add the option to retrieve raw arguments --- .../jorel/commandapi/CommandAPIHandler.java | 35 ++++++-- .../arguments/AbstractArgument.java | 26 ++++++ .../executors/CommandArguments.java | 79 ++++++++++++++++++- .../commandapi-bukkit-test-impl/pom.xml | 2 +- 4 files changed, 132 insertions(+), 10 deletions(-) diff --git a/commandapi-core/src/main/java/dev/jorel/commandapi/CommandAPIHandler.java b/commandapi-core/src/main/java/dev/jorel/commandapi/CommandAPIHandler.java index 163b2074f1..4730bd7e68 100644 --- a/commandapi-core/src/main/java/dev/jorel/commandapi/CommandAPIHandler.java +++ b/commandapi-core/src/main/java/dev/jorel/commandapi/CommandAPIHandler.java @@ -223,7 +223,7 @@ public AbstractCommandSender senderWrapper() { @Override public CommandArguments args() { - return new CommandArguments(result, new LinkedHashMap<>(), "/" + cmdCtx.getInput()); + return new CommandArguments(result, new LinkedHashMap<>(), result, new LinkedHashMap<>(), "/" + cmdCtx.getInput()); } }; @@ -274,16 +274,28 @@ CommandArguments argsToCommandArgs(CommandContext cmdCtx, Argument[] arg // LinkedHashMap for arguments for executor Map argsMap = new LinkedHashMap<>(); + // List for raw arguments + List rawArguments = new ArrayList<>(); + + // LinkedHashMap for raw arguments + Map rawArgumentsMap = new LinkedHashMap<>(); + // Populate array for (Argument argument : args) { if (argument.isListed()) { - Object parsedArgument = parseArgument(cmdCtx, argument.getNodeName(), argument, new CommandArguments(argList.toArray(), argsMap, "/" + cmdCtx.getInput())); + Object parsedArgument = parseArgument(cmdCtx, argument.getNodeName(), argument, new CommandArguments(argList.toArray(), argsMap, rawArguments.toArray(String[]::new), rawArgumentsMap, "/" + cmdCtx.getInput())); + + // Add the parsed argument argList.add(parsedArgument); argsMap.put(argument.getNodeName(), parsedArgument); + + // Add the raw argument + rawArguments.add(argument.getRawArgumentString()); // Should exist; argument was already parsed which is when the raw argument String is saved + rawArgumentsMap.put(argument.getNodeName(), argument.getRawArgumentString()); } } - return new CommandArguments(argList.toArray(), argsMap, "/" + cmdCtx.getInput()); + return new CommandArguments(argList.toArray(), argsMap, rawArguments.toArray(String[]::new), rawArgumentsMap, "/" + cmdCtx.getInput()); } /** @@ -297,7 +309,7 @@ CommandArguments argsToCommandArgs(CommandContext cmdCtx, Argument[] arg */ Object parseArgument(CommandContext cmdCtx, String key, Argument value, CommandArguments previousArgs) throws CommandSyntaxException { if (value.isListed()) { - return value.parseArgument(cmdCtx, key, previousArgs); + return value.getRawStringAndParseArgument(cmdCtx, key, previousArgs); } else { return null; } @@ -809,6 +821,12 @@ CommandArguments generatePreviousArguments(CommandContext context, Argum // LinkedHashMap for arguments Map argsMap = new LinkedHashMap<>(); + // List for raw arguments + List rawArguments = new ArrayList<>(); + + // LinkedHashMap for raw arguments + Map rawArgumentsMap = new LinkedHashMap<>(); + for (Argument arg : args) { if (arg.getNodeName().equals(nodeName) && !(arg instanceof Literal)) { break; @@ -816,7 +834,7 @@ CommandArguments generatePreviousArguments(CommandContext context, Argum Object result; try { - result = parseArgument(context, arg.getNodeName(), arg, new CommandArguments(previousArguments.toArray(), argsMap, "/" + context.getInput())); + result = parseArgument(context, arg.getNodeName(), arg, new CommandArguments(previousArguments.toArray(), argsMap, rawArguments.toArray(String[]::new), rawArgumentsMap, "/" + context.getInput())); } catch (IllegalArgumentException e) { /* * Redirected commands don't parse previous arguments properly. Simplest way to @@ -829,11 +847,16 @@ CommandArguments generatePreviousArguments(CommandContext context, Argum result = null; } if (arg.isListed()) { + // Add the parsed argument previousArguments.add(result); argsMap.put(arg.getNodeName(), result); + + // Add the raw argument + rawArguments.add(arg.getRawArgumentString()); // Should exist; argument was already parsed which is when the raw argument String is saved + rawArgumentsMap.put(arg.getNodeName(), arg.getRawArgumentString()); } } - return new CommandArguments(previousArguments.toArray(), argsMap, "/" + context.getInput()); + return new CommandArguments(previousArguments.toArray(), argsMap, rawArguments.toArray(String[]::new), rawArgumentsMap, "/" + context.getInput()); } SuggestionProvider toSuggestions(Argument theArgument, Argument[] args, diff --git a/commandapi-core/src/main/java/dev/jorel/commandapi/arguments/AbstractArgument.java b/commandapi-core/src/main/java/dev/jorel/commandapi/arguments/AbstractArgument.java index 5cd0cd3d59..98607eeab6 100644 --- a/commandapi-core/src/main/java/dev/jorel/commandapi/arguments/AbstractArgument.java +++ b/commandapi-core/src/main/java/dev/jorel/commandapi/arguments/AbstractArgument.java @@ -24,6 +24,7 @@ import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.exceptions.CommandSyntaxException; import dev.jorel.commandapi.AbstractArgumentTree; +import dev.jorel.commandapi.CommandAPIHandler; import dev.jorel.commandapi.CommandPermission; import dev.jorel.commandapi.executors.CommandArguments; @@ -72,6 +73,7 @@ public abstract class AbstractArgument rawType; + private String rawArgumentString = ""; /** * Constructs an argument with a given NMS/brigadier type. @@ -102,6 +104,30 @@ public final String getNodeName() { return this.nodeName; } + /** + * Returns the raw String which is retrieved in {@link AbstractArgument#getRawStringAndParseArgument(CommandContext, String, CommandArguments)} + * + * @return the raw String which is retrieved in {@link AbstractArgument#getRawStringAndParseArgument(CommandContext, String, CommandArguments)} + */ + public final String getRawArgumentString() { + return this.rawArgumentString; + } + + /** + * Saves the String of this argument as typed when executing the command and parses the argument + * + * @param the command source type + * @param cmdCtx the context which ran this command + * @param key the name of the argument node + * @param previousArgs a {@link CommandArguments} object holding previous parsed arguments + * @return the parsed object represented by this argument + * @throws CommandSyntaxException if parsing fails + */ + public T getRawStringAndParseArgument(CommandContext cmdCtx, String key, CommandArguments previousArgs) throws CommandSyntaxException { + this.rawArgumentString = CommandAPIHandler.getRawArgumentInput(cmdCtx, key); + return parseArgument(cmdCtx, key, previousArgs); + } + /** * Parses an argument, returning the specific Bukkit object that the argument * represents. This is intended for use by the internals of the CommandAPI and diff --git a/commandapi-core/src/main/java/dev/jorel/commandapi/executors/CommandArguments.java b/commandapi-core/src/main/java/dev/jorel/commandapi/executors/CommandArguments.java index 67d4293dce..7e2be57762 100644 --- a/commandapi-core/src/main/java/dev/jorel/commandapi/executors/CommandArguments.java +++ b/commandapi-core/src/main/java/dev/jorel/commandapi/executors/CommandArguments.java @@ -14,19 +14,25 @@ public class CommandArguments { private final Object[] args; + private final String[] rawArgs; private final Map argsMap; + private final Map rawArgsMap; private final String fullInput; /** * Constructs a new CommandArguments instance * * @param args The arguments for this command - * @param argsMap The arguments for this command mapped to the node names. This is an ordered map + * @param argsMap The arguments for this command mapped to their node names. This is an ordered map + * @param rawArgs The raw arguments for this command. + * @param rawArgsMap The raw arguments for this command mapped to their node names. This is an ordered map * @param fullInput The raw command a player has entered */ - public CommandArguments(Object[] args, Map argsMap, String fullInput) { + public CommandArguments(Object[] args, Map argsMap, String[] rawArgs, Map rawArgsMap, String fullInput) { this.args = args; + this.rawArgs = rawArgs; this.argsMap = argsMap; + this.rawArgsMap = rawArgsMap; this.fullInput = fullInput; } @@ -38,7 +44,14 @@ public CommandArguments(Object[] args, Map argsMap, String fullI public Object[] args() { return args; } - + + /** + * @return The complete raw argument array of this command + */ + public String[] rawArgs() { + return rawArgs; + } + /** * @return An unmodifiable clone of the mapping of node names to argument values */ @@ -46,6 +59,13 @@ public Map argsMap() { return Collections.unmodifiableMap(argsMap); } + /** + * @return An unmodifiable clone of the mapping of node names to raw arguments + */ + public Map rawArgsMap() { + return Collections.unmodifiableMap(rawArgsMap); + } + /** * @return The number of arguments in this object */ @@ -84,6 +104,32 @@ public Object get(String nodeName) { return argsMap.get(nodeName); } + /** + * Returns a raw argument by its position + * + * @param index The position of this argument + * @return An argument which is placed at the given index, or {@code null} if the provided index does not point to an argument. + */ + @Nullable + public String getRaw(int index) { + if (args.length <= index) { + return null; + } else { + return rawArgs[index]; + } + } + + /** + * Returns a raw argument by its node name + * + * @param nodeName The node name of this argument. This was set when initializing an argument + * @return An argument which has the given node name. Can be null if nodeName was not found. + */ + @Nullable + public String getRaw(String nodeName) { + return rawArgsMap.get(nodeName); + } + /** * This returns the raw command string a player has entered * @@ -179,6 +225,33 @@ public Optional getOptional(String nodeName) { } return Optional.of(argsMap.get(nodeName)); } + + /** + * Returns an Optional holding the raw argument by its index + * + * @param index The position of this argument + * @return An optional holding the raw argument which is placed at the given index, or an empty optional if index is invalid + */ + public Optional getRawOptional(int index) { + if (args.length <= index) { + return Optional.empty(); + } else { + return Optional.of(rawArgs[index]); + } + } + + /** + * Returns an argument by its node name + * + * @param nodeName The node name of this argument. This was set when initializing an argument + * @return An optional holding the argument with the specified node name or an empty optional if the node name was not found + */ + public Optional getRawOptional(String nodeName) { + if (!argsMap.containsKey(nodeName)) { + return Optional.empty(); + } + return Optional.of(rawArgsMap.get(nodeName)); + } /** Unchecked methods. These are the same as the methods above, but use * unchecked generics to conform to the type they are declared as. In Java, diff --git a/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-test/commandapi-bukkit-test-impl/pom.xml b/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-test/commandapi-bukkit-test-impl/pom.xml index a067e47208..94118df6c2 100644 --- a/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-test/commandapi-bukkit-test-impl/pom.xml +++ b/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-test/commandapi-bukkit-test-impl/pom.xml @@ -25,7 +25,7 @@ commandapi-bukkit-test dev.jorel - 9.0.2 + 9.0.3 4.0.0 From 4baa0a468d844124436987a379137765d6424d2a Mon Sep 17 00:00:00 2001 From: DerEchtePilz Date: Thu, 8 Jun 2023 19:44:12 +0200 Subject: [PATCH 02/28] Fix SuggestionsBranch.java. Change String[]::new to new String[0] --- .../main/java/dev/jorel/commandapi/CommandAPIHandler.java | 8 ++++---- .../dev/jorel/commandapi/arguments/SuggestionsBranch.java | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/commandapi-core/src/main/java/dev/jorel/commandapi/CommandAPIHandler.java b/commandapi-core/src/main/java/dev/jorel/commandapi/CommandAPIHandler.java index 4730bd7e68..64346f9c28 100644 --- a/commandapi-core/src/main/java/dev/jorel/commandapi/CommandAPIHandler.java +++ b/commandapi-core/src/main/java/dev/jorel/commandapi/CommandAPIHandler.java @@ -283,7 +283,7 @@ CommandArguments argsToCommandArgs(CommandContext cmdCtx, Argument[] arg // Populate array for (Argument argument : args) { if (argument.isListed()) { - Object parsedArgument = parseArgument(cmdCtx, argument.getNodeName(), argument, new CommandArguments(argList.toArray(), argsMap, rawArguments.toArray(String[]::new), rawArgumentsMap, "/" + cmdCtx.getInput())); + Object parsedArgument = parseArgument(cmdCtx, argument.getNodeName(), argument, new CommandArguments(argList.toArray(), argsMap, rawArguments.toArray(new String[0]), rawArgumentsMap, "/" + cmdCtx.getInput())); // Add the parsed argument argList.add(parsedArgument); @@ -295,7 +295,7 @@ CommandArguments argsToCommandArgs(CommandContext cmdCtx, Argument[] arg } } - return new CommandArguments(argList.toArray(), argsMap, rawArguments.toArray(String[]::new), rawArgumentsMap, "/" + cmdCtx.getInput()); + return new CommandArguments(argList.toArray(), argsMap, rawArguments.toArray(new String[0]), rawArgumentsMap, "/" + cmdCtx.getInput()); } /** @@ -834,7 +834,7 @@ CommandArguments generatePreviousArguments(CommandContext context, Argum Object result; try { - result = parseArgument(context, arg.getNodeName(), arg, new CommandArguments(previousArguments.toArray(), argsMap, rawArguments.toArray(String[]::new), rawArgumentsMap, "/" + context.getInput())); + result = parseArgument(context, arg.getNodeName(), arg, new CommandArguments(previousArguments.toArray(), argsMap, rawArguments.toArray(new String[0]), rawArgumentsMap, "/" + context.getInput())); } catch (IllegalArgumentException e) { /* * Redirected commands don't parse previous arguments properly. Simplest way to @@ -856,7 +856,7 @@ CommandArguments generatePreviousArguments(CommandContext context, Argum rawArgumentsMap.put(arg.getNodeName(), arg.getRawArgumentString()); } } - return new CommandArguments(previousArguments.toArray(), argsMap, rawArguments.toArray(String[]::new), rawArgumentsMap, "/" + context.getInput()); + return new CommandArguments(previousArguments.toArray(), argsMap, rawArguments.toArray(new String[0]), rawArgumentsMap, "/" + context.getInput()); } SuggestionProvider toSuggestions(Argument theArgument, Argument[] args, diff --git a/commandapi-core/src/main/java/dev/jorel/commandapi/arguments/SuggestionsBranch.java b/commandapi-core/src/main/java/dev/jorel/commandapi/arguments/SuggestionsBranch.java index 413b341062..452fc7603e 100644 --- a/commandapi-core/src/main/java/dev/jorel/commandapi/arguments/SuggestionsBranch.java +++ b/commandapi-core/src/main/java/dev/jorel/commandapi/arguments/SuggestionsBranch.java @@ -79,7 +79,7 @@ private ArgumentSuggestions getNextSuggestion(CommandSender sende if (currentSuggestion != null) { // Validate argument on the path - SuggestionInfo info = new SuggestionInfo<>(sender, new CommandArguments(processedArguments.toArray(), new HashMap<>(), currentInput.toString()), currentInput.toString(), ""); + SuggestionInfo info = new SuggestionInfo<>(sender, new CommandArguments(processedArguments.toArray(), new HashMap<>(), processedArguments.toArray(new String[0]), new LinkedHashMap<>(), currentInput.toString()), currentInput.toString(), ""); SuggestionsBuilder builder = new SuggestionsBuilder(currentInput.toString(), currentInput.length()); currentSuggestion.suggest(info, builder); if (builder.build().getList().stream().map(Suggestion::getText).noneMatch(currentArgument::equals)) { @@ -184,7 +184,7 @@ private EnforceReplacementsResult enforceReplacements(CommandSender sender, Stri if (currentSuggestion != null) { // Validate argument on the path - SuggestionInfo info = new SuggestionInfo<>(sender, new CommandArguments(processedArguments.toArray(), new HashMap<>(), currentInput.toString()), currentInput.toString(), ""); + SuggestionInfo info = new SuggestionInfo<>(sender, new CommandArguments(processedArguments.toArray(), new HashMap<>(), processedArguments.toArray(new String[0]), new LinkedHashMap<>(), currentInput.toString()), currentInput.toString(), ""); SuggestionsBuilder builder = new SuggestionsBuilder(currentInput.toString(), currentInput.length()); try { currentSuggestion.suggest(info, builder); From b186494389a20be564b7f874e5065baf8e406225 Mon Sep 17 00:00:00 2001 From: DerEchtePilz Date: Thu, 8 Jun 2023 19:55:25 +0200 Subject: [PATCH 03/28] Fix CommandArgument.java --- .../java/dev/jorel/commandapi/arguments/CommandArgument.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-core/src/main/java/dev/jorel/commandapi/arguments/CommandArgument.java b/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-core/src/main/java/dev/jorel/commandapi/arguments/CommandArgument.java index 96ac03848d..e0b53d2ba1 100644 --- a/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-core/src/main/java/dev/jorel/commandapi/arguments/CommandArgument.java +++ b/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-core/src/main/java/dev/jorel/commandapi/arguments/CommandArgument.java @@ -18,6 +18,7 @@ import java.util.Arrays; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; /** @@ -55,7 +56,7 @@ private void applySuggestions() { // Suggesting command name ArgumentSuggestions replacement = replacements.getNextSuggestion(sender); if (replacement != null) { - return replacement.suggest(new SuggestionInfo<>(sender, new CommandArguments(new Object[0], new HashMap<>(), info.currentInput()), command, command), builder); + return replacement.suggest(new SuggestionInfo<>(sender, new CommandArguments(new Object[0], new HashMap<>(), new String[0], new LinkedHashMap<>(), info.currentInput()), command, command), builder); } List results = commandMap.tabComplete(sender, command); @@ -101,7 +102,7 @@ private void applySuggestions() { String[] previousArguments = Arrays.copyOf(arguments, lastIndex); ArgumentSuggestions replacement = replacements.getNextSuggestion(sender, previousArguments); if (replacement != null) { - return replacement.suggest(new SuggestionInfo<>(sender, new CommandArguments(previousArguments, new HashMap<>(), info.currentInput()), command, arguments[lastIndex]), builder); + return replacement.suggest(new SuggestionInfo<>(sender, new CommandArguments(previousArguments, new HashMap<>(), previousArguments, new LinkedHashMap<>(), info.currentInput()), command, arguments[lastIndex]), builder); } // Remove command name from arguments for normal tab-completion From 8981a2a72cee072cf9decf2f3337ad128910d98d Mon Sep 17 00:00:00 2001 From: DerEchtePilz Date: Thu, 15 Jun 2023 15:56:03 +0200 Subject: [PATCH 04/28] Add tests for retrieving raw arguments --- .../test/CommandArgumentsTests.java | 146 ++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 commandapi-platforms/commandapi-bukkit/commandapi-bukkit-test/commandapi-bukkit-test-tests/src/test/java/dev/jorel/commandapi/test/CommandArgumentsTests.java diff --git a/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-test/commandapi-bukkit-test-tests/src/test/java/dev/jorel/commandapi/test/CommandArgumentsTests.java b/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-test/commandapi-bukkit-test-tests/src/test/java/dev/jorel/commandapi/test/CommandArgumentsTests.java new file mode 100644 index 0000000000..c36ee65638 --- /dev/null +++ b/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-test/commandapi-bukkit-test-tests/src/test/java/dev/jorel/commandapi/test/CommandArgumentsTests.java @@ -0,0 +1,146 @@ +package dev.jorel.commandapi.test; + +import be.seeseemelk.mockbukkit.entity.PlayerMock; +import dev.jorel.commandapi.CommandAPICommand; +import dev.jorel.commandapi.arguments.*; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class CommandArgumentsTests extends TestBase { + + /********* + * Setup * + *********/ + + @BeforeEach + public void setUp() { + super.setUp(); + } + + @AfterEach + public void tearDown() { + super.tearDown(); + } + + /********* + * Tests * + *********/ + + @Test + public void executionTestForRawArgumentsWithOnlyOneArgumentAndRequiredArgumentOnly() { + Mut results = Mut.of(); + + new CommandAPICommand("test") + .withArguments(new EntitySelectorArgument.ManyEntities("entities")) + .executesPlayer(info -> { + results.set(info.args().getRaw("entities")); + }) + .register(); + + PlayerMock player = server.addPlayer(); + + server.dispatchCommand(player, "test @e"); + assertEquals("@e", results.get()); + + server.dispatchCommand(player, "test @a"); + assertEquals("@a", results.get()); + + assertNoMoreResults(results); + } + + @Test + public void executionTestForRawArgumentsWithMultipleArgumentsAndRequiredArgumentsOnly() { + Mut results = Mut.of(); + + new CommandAPICommand("test") + .withArguments(new DoubleArgument("double")) + .withArguments(new TextArgument("text")) + .executesPlayer(info -> { + results.set(info.args().getRaw("double")); + results.set(info.args().getRaw("text")); + }) + .register(); + + PlayerMock player = server.addPlayer(); + + server.dispatchCommand(player, "test 15.34 \"This is interesting text\""); + assertEquals("15.34", results.get()); + assertEquals("\"This is interesting text\"", results.get()); + + assertNoMoreResults(results); + } + + @Test + public void executionTestForRawArgumentsWithMultipleArgumentsWithMultipleRequiredAndOneOptionalArguments() { + Mut results = Mut.of(); + + new CommandAPICommand("test") + .withArguments(new DoubleArgument("double")) + .withArguments(new TextArgument("text")) + .withOptionalArguments(new EntitySelectorArgument.ManyEntities("entities")) + .executesPlayer(info -> { + results.set(info.args().getRaw("double")); + results.set(info.args().getRaw("text")); + results.set(info.args().getRawOptional("entities").orElse("")); + }) + .register(); + + PlayerMock player = server.addPlayer(); + + server.dispatchCommand(player, "test 15.34 \"This is interesting text\""); + assertEquals("15.34", results.get()); + assertEquals("\"This is interesting text\"", results.get()); + assertEquals("", results.get()); + + server.dispatchCommand(player, "test 15.34 \"This is interesting text\" @e"); + assertEquals("15.34", results.get()); + assertEquals("\"This is interesting text\"", results.get()); + assertEquals("@e", results.get()); + + assertNoMoreResults(results); + } + + @Test + public void executionTestForRawArgumentsWithMultipleArgumentsWithMultipleRequiredAndMultipleOptionalArguments() { + Mut results = Mut.of(); + + new CommandAPICommand("test") + .withArguments(new DoubleArgument("double")) + .withArguments(new TextArgument("text")) + .withOptionalArguments(new EntitySelectorArgument.ManyEntities("entities")) + .withOptionalArguments(new GreedyStringArgument("message")) + .executesPlayer(info -> { + results.set(info.args().getRaw("double")); + results.set(info.args().getRaw("text")); + results.set(info.args().getRawOptional("entities").orElse("")); + results.set(info.args().getRawOptional("message").orElse("")); + }) + .register(); + + PlayerMock player = server.addPlayer(); + + server.dispatchCommand(player, "test 15.34 \"This is interesting text\""); + assertEquals("15.34", results.get()); + assertEquals("\"This is interesting text\"", results.get()); + assertEquals("", results.get()); + assertEquals("", results.get()); + + server.dispatchCommand(player, "test 15.34 \"This is interesting text\" @e"); + assertEquals("15.34", results.get()); + assertEquals("\"This is interesting text\"", results.get()); + assertEquals("@e", results.get()); + assertEquals("", results.get()); + + server.dispatchCommand(player, "test 15.34 \"This is interesting text\" @e Hello, everyone! This is a test which passes and doesn't throw any error!"); + assertEquals("15.34", results.get()); + assertEquals("\"This is interesting text\"", results.get()); + assertEquals("@e", results.get()); + assertEquals("Hello, everyone! This is a test which passes and doesn't throw any error!", results.get()); + + assertNoMoreResults(results); + } + +} From 6cf237dcccb5aef40d64359362d58abc51af4416 Mon Sep 17 00:00:00 2001 From: DerEchtePilz Date: Thu, 15 Jun 2023 20:34:02 +0200 Subject: [PATCH 05/28] Move raw argument creation into CommandAPIHandler --- .../jorel/commandapi/CommandAPIHandler.java | 18 ++++++++------ .../arguments/AbstractArgument.java | 24 ------------------- 2 files changed, 11 insertions(+), 31 deletions(-) diff --git a/commandapi-core/src/main/java/dev/jorel/commandapi/CommandAPIHandler.java b/commandapi-core/src/main/java/dev/jorel/commandapi/CommandAPIHandler.java index 64346f9c28..0e6a4d916c 100644 --- a/commandapi-core/src/main/java/dev/jorel/commandapi/CommandAPIHandler.java +++ b/commandapi-core/src/main/java/dev/jorel/commandapi/CommandAPIHandler.java @@ -102,8 +102,8 @@ public static String getRawArgumentInput(CommandContext parsedArgument = commandContextArguments.get(cmdCtx).get(key); // TODO: Issue #310: Parsing this argument via /execute run doesn't have the value in - // the arguments for this command context (most likely because it's a redirected command). - // We need to figure out how to handle this case. + // the arguments for this command context (most likely because it's a redirected command). + // We need to figure out how to handle this case. if(parsedArgument != null) { StringRange range = parsedArgument.getRange(); return cmdCtx.getInput().substring(range.getStart(), range.getEnd()); @@ -290,8 +290,10 @@ CommandArguments argsToCommandArgs(CommandContext cmdCtx, Argument[] arg argsMap.put(argument.getNodeName(), parsedArgument); // Add the raw argument - rawArguments.add(argument.getRawArgumentString()); // Should exist; argument was already parsed which is when the raw argument String is saved - rawArgumentsMap.put(argument.getNodeName(), argument.getRawArgumentString()); + String rawArgumentString = getRawArgumentInput(cmdCtx, argument.getNodeName()); + + rawArguments.add(rawArgumentString); + rawArgumentsMap.put(argument.getNodeName(), rawArgumentString); } } @@ -309,7 +311,7 @@ CommandArguments argsToCommandArgs(CommandContext cmdCtx, Argument[] arg */ Object parseArgument(CommandContext cmdCtx, String key, Argument value, CommandArguments previousArgs) throws CommandSyntaxException { if (value.isListed()) { - return value.getRawStringAndParseArgument(cmdCtx, key, previousArgs); + return value.parseArgument(cmdCtx, key, previousArgs); } else { return null; } @@ -852,8 +854,10 @@ CommandArguments generatePreviousArguments(CommandContext context, Argum argsMap.put(arg.getNodeName(), result); // Add the raw argument - rawArguments.add(arg.getRawArgumentString()); // Should exist; argument was already parsed which is when the raw argument String is saved - rawArgumentsMap.put(arg.getNodeName(), arg.getRawArgumentString()); + String rawArgumentString = getRawArgumentInput(context, arg.getNodeName()); + + rawArguments.add(rawArgumentString); + rawArgumentsMap.put(arg.getNodeName(), rawArgumentString); } } return new CommandArguments(previousArguments.toArray(), argsMap, rawArguments.toArray(new String[0]), rawArgumentsMap, "/" + context.getInput()); diff --git a/commandapi-core/src/main/java/dev/jorel/commandapi/arguments/AbstractArgument.java b/commandapi-core/src/main/java/dev/jorel/commandapi/arguments/AbstractArgument.java index 98607eeab6..c2c08420a5 100644 --- a/commandapi-core/src/main/java/dev/jorel/commandapi/arguments/AbstractArgument.java +++ b/commandapi-core/src/main/java/dev/jorel/commandapi/arguments/AbstractArgument.java @@ -104,30 +104,6 @@ public final String getNodeName() { return this.nodeName; } - /** - * Returns the raw String which is retrieved in {@link AbstractArgument#getRawStringAndParseArgument(CommandContext, String, CommandArguments)} - * - * @return the raw String which is retrieved in {@link AbstractArgument#getRawStringAndParseArgument(CommandContext, String, CommandArguments)} - */ - public final String getRawArgumentString() { - return this.rawArgumentString; - } - - /** - * Saves the String of this argument as typed when executing the command and parses the argument - * - * @param the command source type - * @param cmdCtx the context which ran this command - * @param key the name of the argument node - * @param previousArgs a {@link CommandArguments} object holding previous parsed arguments - * @return the parsed object represented by this argument - * @throws CommandSyntaxException if parsing fails - */ - public T getRawStringAndParseArgument(CommandContext cmdCtx, String key, CommandArguments previousArgs) throws CommandSyntaxException { - this.rawArgumentString = CommandAPIHandler.getRawArgumentInput(cmdCtx, key); - return parseArgument(cmdCtx, key, previousArgs); - } - /** * Parses an argument, returning the specific Bukkit object that the argument * represents. This is intended for use by the internals of the CommandAPI and From c24d0848d822be9aa310b55cf9aa853597641d2c Mon Sep 17 00:00:00 2001 From: Jorel Ali Date: Thu, 15 Jun 2023 21:50:30 +0100 Subject: [PATCH 06/28] Fix raw argument tests failing when using the ChatComponentArgument or AdventureChatComponentArgument --- .../main/java/dev/jorel/commandapi/CommandAPIHandler.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/commandapi-core/src/main/java/dev/jorel/commandapi/CommandAPIHandler.java b/commandapi-core/src/main/java/dev/jorel/commandapi/CommandAPIHandler.java index 0e6a4d916c..ac678bfc77 100644 --- a/commandapi-core/src/main/java/dev/jorel/commandapi/CommandAPIHandler.java +++ b/commandapi-core/src/main/java/dev/jorel/commandapi/CommandAPIHandler.java @@ -104,9 +104,13 @@ public static String getRawArgumentInput(CommandContext doesn't have the value in // the arguments for this command context (most likely because it's a redirected command). // We need to figure out how to handle this case. - if(parsedArgument != null) { + if (parsedArgument != null) { + // Sanity check: See https://github.com/JorelAli/CommandAPI/wiki/Implementation-details#chatcomponentargument-raw-arguments StringRange range = parsedArgument.getRange(); - return cmdCtx.getInput().substring(range.getStart(), range.getEnd()); + if (range.getEnd() > cmdCtx.getInput().length()) { + range = StringRange.between(range.getStart(), cmdCtx.getInput().length()); + } + return range.get(cmdCtx.getInput()); } else { return ""; } From 46deb774048b2dab6cc23acb1fe6559b1b1c7d7b Mon Sep 17 00:00:00 2001 From: DerEchtePilz Date: Sat, 17 Jun 2023 23:52:05 +0200 Subject: [PATCH 07/28] Add empty documentation page --- docssrc/src/commandarguments.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docssrc/src/commandarguments.md diff --git a/docssrc/src/commandarguments.md b/docssrc/src/commandarguments.md new file mode 100644 index 0000000000..e69de29bb2 From bafaacf0d6a098c9a268b0d85f6f6ffb863b2120 Mon Sep 17 00:00:00 2001 From: DerEchtePilz Date: Fri, 23 Jun 2023 14:03:47 +0200 Subject: [PATCH 08/28] Add documentation (1) --- docssrc/src/commandarguments.md | 134 ++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/docssrc/src/commandarguments.md b/docssrc/src/commandarguments.md index e69de29bb2..17667f5972 100644 --- a/docssrc/src/commandarguments.md +++ b/docssrc/src/commandarguments.md @@ -0,0 +1,134 @@ +# CommandArguments + +The `CommandArguments` class was introduced in CommandAPI 9.0.0 and provides a much more powerful way of accessing arguments than just an array of arguments which existed until 9.0.0. + +While the argument array just gives the possibility to access the arguments via the array notation (`args[0]`), the `CommandArguments` class offers much more, including: + +- [Access the inner structure directly](#access-the-inner-structure-directly) +- [What terms are used?](#what-terms-are-used) + - [`nodeName`](#nodename) + - [`raw argument`](#raw-argument) + - [`unsafe argument`](#unsafe-argument) +- [Access arguments](#access-arguments) + - [Access arguments by node name](#access-arguments-by-node-name) + - [Access arguments by index](#access-arguments-by-index) +- [Access raw arguments](#access-raw-arguments) + - [Access raw arguments by node name](#access-raw-arguments-by-node-name) + - [Access raw arguments by index](#access-raw-arguments-by-index) +- [Access unsafe arguments](#access-unsafe-arguments) + - [Access arguments by node name](#access-arguments-by-node-name-1) + - [Access arguments by index](#access-arguments-by-index-1) + + +ATTENTION!!!!! Every executable and generated documentation has to be deleted before committing anything! + +----- + +## Access the inner structure directly +To provide arguments, the `CommandArguments` class stores: +- a `Object[]` of parsed arguments +- a `Map` of parsed arguments mapped to their node names +- a `String[]` of raw arguments +- a `Map` of raw arguments mapped to their node names +- a `String` which holds the full input + +Although not recommended, it is possible to access these fields directly with methods the `CommandArguments` class provides: + +```java +Object[] args(); // Returns the argument array +Map argsMap(); // Returns an unmodifiable map containing the arguments mapped to their node names +String[] rawArgs(); // Returns the raw argument array +Map rawArgsMap(); // Returns an unmodifiable map containing the raw arguments mapped to their node names +String fullInput(); // Returns the full command string (including the /) +``` + +Additionally, the `CommandArguments` class has one more method that isn't directly backed by a field and returns the amount of arguments for a command: + +```java +int count(); +``` + +While these methods can be used to access arguments, it may be safer to use the other methods the `CommandArguments` class provides to access arguments. + +----- + +## What terms are used? +Throughout this page, multiple terms are used that may need an explanation. + +### `nodeName` +The `nodeName` is set when initializing an argument. For example: + +```java +new StringArgument("string") +``` + +The `nodeName` here would be `string`. + +### `raw argument` +A "raw argument" is the `String` form of an argument as written in a command. For example: + +A user defines a command `/mycommand` that accepts a `double` as the first argument and an entity selector as the second argument. It could be executed with the values `15.3` as the `double` value and `@e` as the entity selector: + +```mccmd +/mycommand 15.3 @e +``` + +When [accessing the raw arguments](#access-raw-arguments) of this command there are `15.3` and `@e` available as `String`s. + +However, when [accessing the arguments](#access-arguments) of this command there is `15.3` available as `double` and `@e` available as `Collection`. + +### `unsafe argument` +When [accessing arguments](#access-arguments) you need to cast the `Object` returned by these methods to the type the argument returns. More about casting arguments [here](./arguments.md#argument-casting). + +However, the `CommandArguments` class provides a way to remove the need to cast the arguments which is referred to as `unsafe arguments` in this page. + +----- + +## Access arguments +The `CommandArguments` class provides its arguments in a way similar to how a `List` or `Map` let you access their contents. When using these methods, you need to cast the arguments to their respective type. The `CommandArguments` class also provides a way to [access unsafe arguments](#access-unsafe-arguments). + +You can choose to access arguments by their node name or by their index. + +### Access arguments by node name +Accessing arguments by their node name is the recommended way of accessing arguments. + +There are two methods you can use to access arguments by their node name: + +```java +Object get(String nodeName); +Optional getOptional(String nodeName); +``` + +There is no downside of using one method over the other but the `CommandArguments#getOptional(String)` method is especially great when you have an optional argument in your command. + +### Access arguments by index +Accessing arguments by their index as the original way of accessing arguments. However, we recommend to [access arguments by node name](#access-arguments-by-node-name). + +Similar to the two methods of accessing arguments by their node name, there also are two methods you can use to access arguments by their index: + +```java +Object get(int index); +Optional getOptional(int index); +``` + +
+ +### Example - Access arguments by node name and index + +
+ +----- + +## Access raw arguments + +### Access raw arguments by node name + +### Access raw arguments by index + +----- + +## Access unsafe arguments + +### Access arguments by node name + +### Access arguments by index \ No newline at end of file From ff7fcc1798e059296c2e4fe4e429fa20435c75ec Mon Sep 17 00:00:00 2001 From: DerEchtePilz Date: Tue, 27 Jun 2023 11:50:17 +0200 Subject: [PATCH 09/28] Add documentation (2) --- docssrc/src/SUMMARY.md | 1 + docssrc/src/commandarguments.md | 74 +++++++++++++++++++++++++++------ 2 files changed, 63 insertions(+), 12 deletions(-) diff --git a/docssrc/src/SUMMARY.md b/docssrc/src/SUMMARY.md index 0eaad72b37..a55be10bf1 100644 --- a/docssrc/src/SUMMARY.md +++ b/docssrc/src/SUMMARY.md @@ -32,6 +32,7 @@ - [Resulting command executors](./resultingcommandexecutors.md) - [Handling command failures](./commandfailures.md) - [Command arguments](./arguments.md) + - [CommandArguments](./commandarguments.md) - [Optional arguments](./optional_arguments.md) - [Listed arguments](./listed.md) - [Argument suggestions](./argumentsuggestions.md) diff --git a/docssrc/src/commandarguments.md b/docssrc/src/commandarguments.md index 17667f5972..4f5d90a77d 100644 --- a/docssrc/src/commandarguments.md +++ b/docssrc/src/commandarguments.md @@ -6,18 +6,18 @@ While the argument array just gives the possibility to access the arguments via - [Access the inner structure directly](#access-the-inner-structure-directly) - [What terms are used?](#what-terms-are-used) - - [`nodeName`](#nodename) - - [`raw argument`](#raw-argument) - - [`unsafe argument`](#unsafe-argument) + - [`nodeName`](#nodename) + - [`raw argument`](#raw-argument) + - [`unsafe argument`](#unsafe-argument) - [Access arguments](#access-arguments) - - [Access arguments by node name](#access-arguments-by-node-name) - - [Access arguments by index](#access-arguments-by-index) + - [Access arguments by node name](#access-arguments-by-node-name) + - [Access arguments by index](#access-arguments-by-index) - [Access raw arguments](#access-raw-arguments) - - [Access raw arguments by node name](#access-raw-arguments-by-node-name) - - [Access raw arguments by index](#access-raw-arguments-by-index) + - [Access raw arguments by node name](#access-raw-arguments-by-node-name) + - [Access raw arguments by index](#access-raw-arguments-by-index) - [Access unsafe arguments](#access-unsafe-arguments) - - [Access arguments by node name](#access-arguments-by-node-name-1) - - [Access arguments by index](#access-arguments-by-index-1) + - [Access arguments by node name](#access-arguments-by-node-name-1) + - [Access arguments by index](#access-arguments-by-index-1) ATTENTION!!!!! Every executable and generated documentation has to be deleted before committing anything! @@ -99,10 +99,10 @@ Object get(String nodeName); Optional getOptional(String nodeName); ``` -There is no downside of using one method over the other but the `CommandArguments#getOptional(String)` method is especially great when you have an optional argument in your command. +There is no downside of using one method over the other but the `CommandArguments#getOptional(String)` method is especially great when you have optional arguments in your command. ### Access arguments by index -Accessing arguments by their index as the original way of accessing arguments. However, we recommend to [access arguments by node name](#access-arguments-by-node-name). +Accessing arguments by their index is the original way of accessing arguments. However, we recommend to [access arguments by node name](#access-arguments-by-node-name). Similar to the two methods of accessing arguments by their node name, there also are two methods you can use to access arguments by their index: @@ -120,15 +120,65 @@ Optional getOptional(int index); ----- ## Access raw arguments +Raw arguments are accessed basically the same way you would [access arguments](#access-arguments). You can access them by their node name and their index in the argument array. ### Access raw arguments by node name +Accessing raw arguments by their node name is the recommended way of doing it. + +To access raw arguments by their node name, you can use these methods: + +```java +String getRaw(String nodeName); +Optional getRawOptional(String nodeName); +``` ### Access raw arguments by index +Of course, if you don't want to access raw arguments by their node name, we also provide the option to access them by index with these methods: + +```java +String getRaw(int index); +Optional getRawOptional(int index); +``` + +
+ +### Example - Access raw arguments by node name and index + +
----- ## Access unsafe arguments +Accessing unsafe arguments is a nice way to shorten your code as you do not need to cast the argument to its corresponding type. + +Here, you might notice the usage of several `getOrDefaultUnchecked` methods and not the `getOptionalUnchecked` methods you might have expected. +This is the case because Java's type inference only goes one level deep which cases issues when calling a method on the `Optional` that is returned to provide a default value. +That is not a problem when [accessing arguments](#access-arguments) because here you are expected to cast the argument anyway but if you used the `getOptionalUnchecked` method you still would have to provide a type which is not ideal when you don't want to cast arguments. + +Unsafe arguments can also be accessed by their node names and their indices. ### Access arguments by node name +Unsafe arguments can also be accessed by node name which, again, is the recommended way of doing it. -### Access arguments by index \ No newline at end of file +In the case of unsafe arguments, the CommandAPI doesn't provide two but instead three methods to access them: + +```java +T getUnchecked(String nodeName); +T getOrDefaultUnchecked(String nodeName, T defaultValue); +T getOrDefaultUnchecked(String nodeName, Supplier defaultValue); +``` + +### Access arguments by index +If you want to access unsafe arguments by index, you can do that by using these methods: + +```java +T getUnchecked(int nodeName); +T getOrDefaultUnchecked(int nodeName, T defaultValue); +T getOrDefaultUnchecked(int nodeName, Supplier defaultValue); +``` + +
+ +### Example - Access unsafe arguments by node name and index + +
From a0cfc2dbe60c7d78cb1c769d5787b5de3ac072b6 Mon Sep 17 00:00:00 2001 From: DerEchtePilz Date: Wed, 28 Jun 2023 10:54:36 +0200 Subject: [PATCH 10/28] Modify CommandArguments to remove deprecations and add getOrDefault methods for raw arguments --- .../jorel/commandapi/CommandAPIHandler.java | 2 - .../arguments/AbstractArgument.java | 1 - .../executors/CommandArguments.java | 142 +++++++++++------- 3 files changed, 89 insertions(+), 56 deletions(-) diff --git a/commandapi-core/src/main/java/dev/jorel/commandapi/CommandAPIHandler.java b/commandapi-core/src/main/java/dev/jorel/commandapi/CommandAPIHandler.java index ac678bfc77..47730718c6 100644 --- a/commandapi-core/src/main/java/dev/jorel/commandapi/CommandAPIHandler.java +++ b/commandapi-core/src/main/java/dev/jorel/commandapi/CommandAPIHandler.java @@ -23,8 +23,6 @@ import java.awt.Component; import java.io.File; import java.io.IOException; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.VarHandle; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; diff --git a/commandapi-core/src/main/java/dev/jorel/commandapi/arguments/AbstractArgument.java b/commandapi-core/src/main/java/dev/jorel/commandapi/arguments/AbstractArgument.java index c2c08420a5..721e0b437c 100644 --- a/commandapi-core/src/main/java/dev/jorel/commandapi/arguments/AbstractArgument.java +++ b/commandapi-core/src/main/java/dev/jorel/commandapi/arguments/AbstractArgument.java @@ -24,7 +24,6 @@ import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.exceptions.CommandSyntaxException; import dev.jorel.commandapi.AbstractArgumentTree; -import dev.jorel.commandapi.CommandAPIHandler; import dev.jorel.commandapi.CommandPermission; import dev.jorel.commandapi.executors.CommandArguments; diff --git a/commandapi-core/src/main/java/dev/jorel/commandapi/executors/CommandArguments.java b/commandapi-core/src/main/java/dev/jorel/commandapi/executors/CommandArguments.java index 7e2be57762..b7ecfa61ed 100644 --- a/commandapi-core/src/main/java/dev/jorel/commandapi/executors/CommandArguments.java +++ b/commandapi-core/src/main/java/dev/jorel/commandapi/executors/CommandArguments.java @@ -35,7 +35,7 @@ public CommandArguments(Object[] args, Map argsMap, String[] raw this.rawArgsMap = rawArgsMap; this.fullInput = fullInput; } - + // Access the inner structure directly /** @@ -66,6 +66,15 @@ public Map rawArgsMap() { return Collections.unmodifiableMap(rawArgsMap); } + /** + * This returns the raw command string a player has entered + * + * @return The raw command string a player has entered + */ + public String getFullInput() { + return fullInput; + } + /** * @return The number of arguments in this object */ @@ -104,50 +113,13 @@ public Object get(String nodeName) { return argsMap.get(nodeName); } - /** - * Returns a raw argument by its position - * - * @param index The position of this argument - * @return An argument which is placed at the given index, or {@code null} if the provided index does not point to an argument. - */ - @Nullable - public String getRaw(int index) { - if (args.length <= index) { - return null; - } else { - return rawArgs[index]; - } - } - - /** - * Returns a raw argument by its node name - * - * @param nodeName The node name of this argument. This was set when initializing an argument - * @return An argument which has the given node name. Can be null if nodeName was not found. - */ - @Nullable - public String getRaw(String nodeName) { - return rawArgsMap.get(nodeName); - } - - /** - * This returns the raw command string a player has entered - * - * @return The raw command string a player has entered - */ - public String getFullInput() { - return fullInput; - } - /** * Returns an argument by its index * * @param index The position of this argument * @param defaultValue The Object returned if the argument is not existent - * @deprecated This method has been deprecated! Please use {@link CommandArguments#getOptional(int)} * @return An argument which is placed at the given index, or the provided default value */ - @Deprecated(since = "9.0.1", forRemoval = true) public Object getOrDefault(int index, Object defaultValue) { if (args.length <= index) { return defaultValue; @@ -161,10 +133,8 @@ public Object getOrDefault(int index, Object defaultValue) { * * @param nodeName The node name of this argument. This was set when initializing an argument * @param defaultValue The Object returned if the argument was not found. - * @deprecated This method has been deprecated! Please use {@link CommandArguments#getOptional(String)} * @return The argument with the specified node name or the provided default value */ - @Deprecated(since = "9.0.1", forRemoval = true) public Object getOrDefault(String nodeName, Object defaultValue) { return argsMap.getOrDefault(nodeName, defaultValue); } @@ -174,10 +144,8 @@ public Object getOrDefault(String nodeName, Object defaultValue) { * * @param index The position of this argument * @param defaultValue The Object returned if the argument is not existent - * @deprecated This method has been deprecated! Please use {@link CommandArguments#getOptional(int)} * @return An argument which is placed at the given index, or the provided default value */ - @Deprecated(since = "9.0.1", forRemoval = true) public Object getOrDefault(int index, Supplier defaultValue) { if (args.length <= index) { return defaultValue.get(); @@ -191,10 +159,8 @@ public Object getOrDefault(int index, Supplier defaultValue) { * * @param nodeName The node name of this argument. This was set when initializing an argument * @param defaultValue The Object returned if the argument was not found. - * @deprecated This method has been deprecated! Please use {@link CommandArguments#getOptional(String)} * @return The argument with the specified node name or the provided default value */ - @Deprecated(since = "9.0.1", forRemoval = true) public Object getOrDefault(String nodeName, Supplier defaultValue) { return argsMap.getOrDefault(nodeName, defaultValue.get()); } @@ -226,6 +192,84 @@ public Optional getOptional(String nodeName) { return Optional.of(argsMap.get(nodeName)); } + /** + * Returns a raw argument by its position + * + * @param index The position of this argument + * @return An argument which is placed at the given index, or {@code null} if the provided index does not point to an argument. + */ + @Nullable + public String getRaw(int index) { + if (rawArgs.length <= index) { + return null; + } else { + return rawArgs[index]; + } + } + + /** + * Returns a raw argument by its node name + * + * @param nodeName The node name of this argument. This was set when initializing an argument + * @return A raw argument which has the given node name. Can be null if nodeName was not found. + */ + @Nullable + public String getRaw(String nodeName) { + return rawArgsMap.get(nodeName); + } + + /** + * Returns a raw argument by its index + * + * @param index The position of this argument + * @param defaultValue The String returned if the raw argument is not existent + * @return A raw argument which is placed at the given index, or the provided default value + */ + public String getOrDefaultRaw(int index, String defaultValue) { + if (rawArgs.length <= index) { + return defaultValue; + } else { + return rawArgs[index]; + } + } + + /** + * Returns a raw argument by its node name + * + * @param nodeName The node name of this argument. This was set when initializing an argument + * @param defaultValue The String returned if the raw argument was not found. + * @return A raw argument with the specified node name or the provided default value + */ + public String getOrDefaultRaw(String nodeName, String defaultValue) { + return rawArgsMap.getOrDefault(nodeName, defaultValue); + } + + /** + * Returns a raw argument by its index + * + * @param index The position of this argument + * @param defaultValue The String returned if the raw argument is not existent + * @return A raw argument which is placed at the given index, or the provided default value + */ + public String getOrDefaultRaw(int index, Supplier defaultValue) { + if (rawArgs.length <= index) { + return defaultValue.get(); + } else { + return rawArgs[index]; + } + } + + /** + * Returns a raw argument by its node name + * + * @param nodeName The node name of this raw argument. This was set when initializing an argument + * @param defaultValue The String returned if the raw argument was not found. + * @return A raw argument with the specified node name or the provided default value + */ + public String getOrDefaultRaw(String nodeName, Supplier defaultValue) { + return rawArgsMap.getOrDefault(nodeName, defaultValue.get()); + } + /** * Returns an Optional holding the raw argument by its index * @@ -233,7 +277,7 @@ public Optional getOptional(String nodeName) { * @return An optional holding the raw argument which is placed at the given index, or an empty optional if index is invalid */ public Optional getRawOptional(int index) { - if (args.length <= index) { + if (rawArgs.length <= index) { return Optional.empty(); } else { return Optional.of(rawArgs[index]); @@ -302,10 +346,8 @@ public T getUnchecked(String nodeName) { * * @param index The position of this argument * @param defaultValue The Object returned if the argument is not existent - * @deprecated This method has been deprecated! Please use {@link CommandArguments#getOptionalUnchecked(int)} * @return An argument which is placed at the given index, or the provided default value */ - @Deprecated(since = "9.0.1", forRemoval = true) public T getOrDefaultUnchecked(int index, T defaultValue) { return (T) getOrDefault(index, defaultValue); } @@ -315,10 +357,8 @@ public T getOrDefaultUnchecked(int index, T defaultValue) { * * @param nodeName The node name of this argument. This was set when initializing an argument * @param defaultValue The Object returned if the argument was not found. - * @deprecated This method has been deprecated! Please use {@link CommandArguments#getOptionalUnchecked(String)} * @return The argument with the specified node name or the provided default value */ - @Deprecated(since = "9.0.1", forRemoval = true) public T getOrDefaultUnchecked(String nodeName, T defaultValue) { return (T) getOrDefault(nodeName, defaultValue); } @@ -328,10 +368,8 @@ public T getOrDefaultUnchecked(String nodeName, T defaultValue) { * * @param index The position of this argument * @param defaultValue The Object returned if the argument is not existent - * @deprecated This method has been deprecated! Please use {@link CommandArguments#getOptionalUnchecked(int)} * @return An argument which is placed at the given index, or the provided default value */ - @Deprecated(since = "9.0.1", forRemoval = true) public T getOrDefaultUnchecked(int index, Supplier defaultValue) { return (T) getOrDefault(index, defaultValue); } @@ -341,10 +379,8 @@ public T getOrDefaultUnchecked(int index, Supplier defaultValue) { * * @param nodeName The node name of this argument. This was set when initializing an argument * @param defaultValue The Object returned if the argument was not found. - * @deprecated This method has been deprecated! Please use {@link CommandArguments#getOptionalUnchecked(String)} * @return The argument with the specified node name or the provided default value */ - @Deprecated(since = "9.0.1", forRemoval = true) public T getOrDefaultUnchecked(String nodeName, Supplier defaultValue) { return (T) getOrDefault(nodeName, defaultValue); } From eb431b0fb2ef3988d487412e23d27be57badc4c7 Mon Sep 17 00:00:00 2001 From: DerEchtePilz Date: Fri, 30 Jun 2023 17:06:22 +0200 Subject: [PATCH 11/28] Address some code review --- .../java/dev/jorel/commandapi/arguments/AbstractArgument.java | 1 - .../dev/jorel/commandapi/arguments/SuggestionsBranch.java | 4 ++-- .../java/dev/jorel/commandapi/executors/CommandArguments.java | 2 +- .../java/dev/jorel/commandapi/arguments/CommandArgument.java | 4 ++-- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/commandapi-core/src/main/java/dev/jorel/commandapi/arguments/AbstractArgument.java b/commandapi-core/src/main/java/dev/jorel/commandapi/arguments/AbstractArgument.java index 721e0b437c..5cd0cd3d59 100644 --- a/commandapi-core/src/main/java/dev/jorel/commandapi/arguments/AbstractArgument.java +++ b/commandapi-core/src/main/java/dev/jorel/commandapi/arguments/AbstractArgument.java @@ -72,7 +72,6 @@ public abstract class AbstractArgument rawType; - private String rawArgumentString = ""; /** * Constructs an argument with a given NMS/brigadier type. diff --git a/commandapi-core/src/main/java/dev/jorel/commandapi/arguments/SuggestionsBranch.java b/commandapi-core/src/main/java/dev/jorel/commandapi/arguments/SuggestionsBranch.java index 452fc7603e..27a8810f46 100644 --- a/commandapi-core/src/main/java/dev/jorel/commandapi/arguments/SuggestionsBranch.java +++ b/commandapi-core/src/main/java/dev/jorel/commandapi/arguments/SuggestionsBranch.java @@ -79,7 +79,7 @@ private ArgumentSuggestions getNextSuggestion(CommandSender sende if (currentSuggestion != null) { // Validate argument on the path - SuggestionInfo info = new SuggestionInfo<>(sender, new CommandArguments(processedArguments.toArray(), new HashMap<>(), processedArguments.toArray(new String[0]), new LinkedHashMap<>(), currentInput.toString()), currentInput.toString(), ""); + SuggestionInfo info = new SuggestionInfo<>(sender, new CommandArguments(processedArguments.toArray(), new LinkedHashMap<>(), processedArguments.toArray(new String[0]), new LinkedHashMap<>(), currentInput.toString()), currentInput.toString(), ""); SuggestionsBuilder builder = new SuggestionsBuilder(currentInput.toString(), currentInput.length()); currentSuggestion.suggest(info, builder); if (builder.build().getList().stream().map(Suggestion::getText).noneMatch(currentArgument::equals)) { @@ -184,7 +184,7 @@ private EnforceReplacementsResult enforceReplacements(CommandSender sender, Stri if (currentSuggestion != null) { // Validate argument on the path - SuggestionInfo info = new SuggestionInfo<>(sender, new CommandArguments(processedArguments.toArray(), new HashMap<>(), processedArguments.toArray(new String[0]), new LinkedHashMap<>(), currentInput.toString()), currentInput.toString(), ""); + SuggestionInfo info = new SuggestionInfo<>(sender, new CommandArguments(processedArguments.toArray(), new LinkedHashMap<>(), processedArguments.toArray(new String[0]), new LinkedHashMap<>(), currentInput.toString()), currentInput.toString(), ""); SuggestionsBuilder builder = new SuggestionsBuilder(currentInput.toString(), currentInput.length()); try { currentSuggestion.suggest(info, builder); diff --git a/commandapi-core/src/main/java/dev/jorel/commandapi/executors/CommandArguments.java b/commandapi-core/src/main/java/dev/jorel/commandapi/executors/CommandArguments.java index b7ecfa61ed..81cc9cacd6 100644 --- a/commandapi-core/src/main/java/dev/jorel/commandapi/executors/CommandArguments.java +++ b/commandapi-core/src/main/java/dev/jorel/commandapi/executors/CommandArguments.java @@ -291,7 +291,7 @@ public Optional getRawOptional(int index) { * @return An optional holding the argument with the specified node name or an empty optional if the node name was not found */ public Optional getRawOptional(String nodeName) { - if (!argsMap.containsKey(nodeName)) { + if (!rawArgsMap.containsKey(nodeName)) { return Optional.empty(); } return Optional.of(rawArgsMap.get(nodeName)); diff --git a/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-core/src/main/java/dev/jorel/commandapi/arguments/CommandArgument.java b/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-core/src/main/java/dev/jorel/commandapi/arguments/CommandArgument.java index e0b53d2ba1..faf0543255 100644 --- a/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-core/src/main/java/dev/jorel/commandapi/arguments/CommandArgument.java +++ b/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-core/src/main/java/dev/jorel/commandapi/arguments/CommandArgument.java @@ -56,7 +56,7 @@ private void applySuggestions() { // Suggesting command name ArgumentSuggestions replacement = replacements.getNextSuggestion(sender); if (replacement != null) { - return replacement.suggest(new SuggestionInfo<>(sender, new CommandArguments(new Object[0], new HashMap<>(), new String[0], new LinkedHashMap<>(), info.currentInput()), command, command), builder); + return replacement.suggest(new SuggestionInfo<>(sender, new CommandArguments(new Object[0], new LinkedHashMap<>(), new String[0], new LinkedHashMap<>(), info.currentInput()), command, command), builder); } List results = commandMap.tabComplete(sender, command); @@ -102,7 +102,7 @@ private void applySuggestions() { String[] previousArguments = Arrays.copyOf(arguments, lastIndex); ArgumentSuggestions replacement = replacements.getNextSuggestion(sender, previousArguments); if (replacement != null) { - return replacement.suggest(new SuggestionInfo<>(sender, new CommandArguments(previousArguments, new HashMap<>(), previousArguments, new LinkedHashMap<>(), info.currentInput()), command, arguments[lastIndex]), builder); + return replacement.suggest(new SuggestionInfo<>(sender, new CommandArguments(previousArguments, new LinkedHashMap<>(), previousArguments, new LinkedHashMap<>(), info.currentInput()), command, arguments[lastIndex]), builder); } // Remove command name from arguments for normal tab-completion From 9fe5879d991dbc1f9b8cd5c2bc79f7f36fa8a5b2 Mon Sep 17 00:00:00 2001 From: DerEchtePilz Date: Fri, 30 Jun 2023 17:08:44 +0200 Subject: [PATCH 12/28] Fix markdownlint issues --- docssrc/src/commandarguments.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/docssrc/src/commandarguments.md b/docssrc/src/commandarguments.md index 4f5d90a77d..b37f7e5c60 100644 --- a/docssrc/src/commandarguments.md +++ b/docssrc/src/commandarguments.md @@ -19,13 +19,14 @@ While the argument array just gives the possibility to access the arguments via - [Access arguments by node name](#access-arguments-by-node-name-1) - [Access arguments by index](#access-arguments-by-index-1) - ATTENTION!!!!! Every executable and generated documentation has to be deleted before committing anything! ----- ## Access the inner structure directly + To provide arguments, the `CommandArguments` class stores: + - a `Object[]` of parsed arguments - a `Map` of parsed arguments mapped to their node names - a `String[]` of raw arguments @@ -53,9 +54,11 @@ While these methods can be used to access arguments, it may be safer to use the ----- ## What terms are used? + Throughout this page, multiple terms are used that may need an explanation. ### `nodeName` + The `nodeName` is set when initializing an argument. For example: ```java @@ -65,6 +68,7 @@ new StringArgument("string") The `nodeName` here would be `string`. ### `raw argument` + A "raw argument" is the `String` form of an argument as written in a command. For example: A user defines a command `/mycommand` that accepts a `double` as the first argument and an entity selector as the second argument. It could be executed with the values `15.3` as the `double` value and `@e` as the entity selector: @@ -78,6 +82,7 @@ When [accessing the raw arguments](#access-raw-arguments) of this command there However, when [accessing the arguments](#access-arguments) of this command there is `15.3` available as `double` and `@e` available as `Collection`. ### `unsafe argument` + When [accessing arguments](#access-arguments) you need to cast the `Object` returned by these methods to the type the argument returns. More about casting arguments [here](./arguments.md#argument-casting). However, the `CommandArguments` class provides a way to remove the need to cast the arguments which is referred to as `unsafe arguments` in this page. @@ -85,11 +90,13 @@ However, the `CommandArguments` class provides a way to remove the need to cast ----- ## Access arguments + The `CommandArguments` class provides its arguments in a way similar to how a `List` or `Map` let you access their contents. When using these methods, you need to cast the arguments to their respective type. The `CommandArguments` class also provides a way to [access unsafe arguments](#access-unsafe-arguments). You can choose to access arguments by their node name or by their index. ### Access arguments by node name + Accessing arguments by their node name is the recommended way of accessing arguments. There are two methods you can use to access arguments by their node name: @@ -102,6 +109,7 @@ Optional getOptional(String nodeName); There is no downside of using one method over the other but the `CommandArguments#getOptional(String)` method is especially great when you have optional arguments in your command. ### Access arguments by index + Accessing arguments by their index is the original way of accessing arguments. However, we recommend to [access arguments by node name](#access-arguments-by-node-name). Similar to the two methods of accessing arguments by their node name, there also are two methods you can use to access arguments by their index: @@ -120,9 +128,11 @@ Optional getOptional(int index); ----- ## Access raw arguments + Raw arguments are accessed basically the same way you would [access arguments](#access-arguments). You can access them by their node name and their index in the argument array. ### Access raw arguments by node name + Accessing raw arguments by their node name is the recommended way of doing it. To access raw arguments by their node name, you can use these methods: @@ -133,6 +143,7 @@ Optional getRawOptional(String nodeName); ``` ### Access raw arguments by index + Of course, if you don't want to access raw arguments by their node name, we also provide the option to access them by index with these methods: ```java @@ -149,6 +160,7 @@ Optional getRawOptional(int index); ----- ## Access unsafe arguments + Accessing unsafe arguments is a nice way to shorten your code as you do not need to cast the argument to its corresponding type. Here, you might notice the usage of several `getOrDefaultUnchecked` methods and not the `getOptionalUnchecked` methods you might have expected. @@ -158,6 +170,7 @@ That is not a problem when [accessing arguments](#access-arguments) because here Unsafe arguments can also be accessed by their node names and their indices. ### Access arguments by node name + Unsafe arguments can also be accessed by node name which, again, is the recommended way of doing it. In the case of unsafe arguments, the CommandAPI doesn't provide two but instead three methods to access them: @@ -169,6 +182,7 @@ T getOrDefaultUnchecked(String nodeName, Supplier defaultValue); ``` ### Access arguments by index + If you want to access unsafe arguments by index, you can do that by using these methods: ```java From d0b59d3899c1324339bfb3e5144914d02c83a23e Mon Sep 17 00:00:00 2001 From: DerEchtePilz Date: Fri, 30 Jun 2023 17:32:21 +0200 Subject: [PATCH 13/28] Make sure commandarguments.md lists every method --- docssrc/src/commandarguments.md | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/docssrc/src/commandarguments.md b/docssrc/src/commandarguments.md index b37f7e5c60..56a0f13535 100644 --- a/docssrc/src/commandarguments.md +++ b/docssrc/src/commandarguments.md @@ -40,7 +40,7 @@ Object[] args(); // Returns the argument array Map argsMap(); // Returns an unmodifiable map containing the arguments mapped to their node names String[] rawArgs(); // Returns the raw argument array Map rawArgsMap(); // Returns an unmodifiable map containing the raw arguments mapped to their node names -String fullInput(); // Returns the full command string (including the /) +String getFullInput(); // Returns the full command string (including the /) ``` Additionally, the `CommandArguments` class has one more method that isn't directly backed by a field and returns the amount of arguments for a command: @@ -99,23 +99,25 @@ You can choose to access arguments by their node name or by their index. Accessing arguments by their node name is the recommended way of accessing arguments. -There are two methods you can use to access arguments by their node name: +There are four methods you can use to access arguments by their node name: ```java Object get(String nodeName); +Object getOrDefault(String nodeName, Object defaultValue); +Object getOrDefault(String nodeName, Supplier defaultValue); Optional getOptional(String nodeName); ``` -There is no downside of using one method over the other but the `CommandArguments#getOptional(String)` method is especially great when you have optional arguments in your command. - ### Access arguments by index Accessing arguments by their index is the original way of accessing arguments. However, we recommend to [access arguments by node name](#access-arguments-by-node-name). -Similar to the two methods of accessing arguments by their node name, there also are two methods you can use to access arguments by their index: +Similar to the four methods of accessing arguments by their node name, there also are four methods you can use to access arguments by their index: ```java Object get(int index); +Object getOrDefault(int index, Object defaultValue); +Object getOrDefault(int index, Supplier defaultValue); Optional getOptional(int index); ``` @@ -139,6 +141,8 @@ To access raw arguments by their node name, you can use these methods: ```java String getRaw(String nodeName); +String getOrDefaultRaw(String nodeName, String defaultValue); +String getOrDefaultRaw(String nodeName, Supplier defaultValue); Optional getRawOptional(String nodeName); ``` @@ -148,6 +152,8 @@ Of course, if you don't want to access raw arguments by their node name, we also ```java String getRaw(int index); +String getOrDefaultRaw(int index, String defaultValue); +String getOrDefaultRaw(int index, Supplier defaultValue); Optional getRawOptional(int index); ``` @@ -163,22 +169,19 @@ Optional getRawOptional(int index); Accessing unsafe arguments is a nice way to shorten your code as you do not need to cast the argument to its corresponding type. -Here, you might notice the usage of several `getOrDefaultUnchecked` methods and not the `getOptionalUnchecked` methods you might have expected. -This is the case because Java's type inference only goes one level deep which cases issues when calling a method on the `Optional` that is returned to provide a default value. -That is not a problem when [accessing arguments](#access-arguments) because here you are expected to cast the argument anyway but if you used the `getOptionalUnchecked` method you still would have to provide a type which is not ideal when you don't want to cast arguments. - Unsafe arguments can also be accessed by their node names and their indices. ### Access arguments by node name Unsafe arguments can also be accessed by node name which, again, is the recommended way of doing it. -In the case of unsafe arguments, the CommandAPI doesn't provide two but instead three methods to access them: +Use these methods when accessing unsafe arguments by their node name: ```java T getUnchecked(String nodeName); T getOrDefaultUnchecked(String nodeName, T defaultValue); T getOrDefaultUnchecked(String nodeName, Supplier defaultValue); +Optional getOptionalUnchecked(String nodeName); ``` ### Access arguments by index @@ -186,9 +189,10 @@ T getOrDefaultUnchecked(String nodeName, Supplier defaultValue); If you want to access unsafe arguments by index, you can do that by using these methods: ```java -T getUnchecked(int nodeName); -T getOrDefaultUnchecked(int nodeName, T defaultValue); -T getOrDefaultUnchecked(int nodeName, Supplier defaultValue); +T getUnchecked(int index); +T getOrDefaultUnchecked(int index, T defaultValue); +T getOrDefaultUnchecked(int index, Supplier defaultValue); +Optional getOptionalUnchecked(int index); ```
From 3af41ab3b03f02f7888658a4f3d9e3764da6630a Mon Sep 17 00:00:00 2001 From: DerEchtePilz Date: Fri, 30 Jun 2023 17:50:00 +0200 Subject: [PATCH 14/28] Link CommandArguments references to commandarguments.md --- docssrc/src/argument_entities.md | 2 +- docssrc/src/argument_literal.md | 2 +- docssrc/src/argument_multiliteral.md | 4 ++-- docssrc/src/arguments.md | 4 ++-- docssrc/src/listed.md | 8 ++++---- docssrc/src/normalexecutors.md | 2 +- docssrc/src/optional_arguments.md | 2 +- docssrc/src/stringargumentsuggestions.md | 2 +- docssrc/src/upgrading.md | 4 ++-- 9 files changed, 15 insertions(+), 15 deletions(-) diff --git a/docssrc/src/argument_entities.md b/docssrc/src/argument_entities.md index 986a6cf3d8..58fb0bd5df 100644 --- a/docssrc/src/argument_entities.md +++ b/docssrc/src/argument_entities.md @@ -13,7 +13,7 @@ There are four `EntitySelectorArgument` subclasses that determine what type of d - `EntitySelectorArgument.OnePlayer` - A single player, which returns a `Player` object. - `EntitySelectorArgument.ManyPlayers` - A collection of players, which returns a `Collection` object. -The return type is the type to be cast when retrieved from the `CommandArguments args` in the command declaration. +The return type is the type to be cast when retrieved from the [`CommandArguments args`](./commandarguments.md) in the command declaration.
diff --git a/docssrc/src/argument_literal.md b/docssrc/src/argument_literal.md index eb9d984703..2e2436068b 100644 --- a/docssrc/src/argument_literal.md +++ b/docssrc/src/argument_literal.md @@ -30,7 +30,7 @@ There is a simpler alternative to the `LiteralArgument` class! Instead of having ## Literal arguments vs regular arguments -Unlike regular arguments that are shown in this chapter, the literal argument is _technically_ not an argument. Due to this fact, literal arguments are [unlisted](./listed.md) by default. In other words, **the literal argument is not present in the `CommandArguments args` for the command declaration.** +Unlike regular arguments that are shown in this chapter, the literal argument is _technically_ not an argument. Due to this fact, literal arguments are [unlisted](./listed.md) by default. In other words, **the literal argument is not present in the [`CommandArguments args`](./commandarguments.md) for the command declaration.**
diff --git a/docssrc/src/argument_multiliteral.md b/docssrc/src/argument_multiliteral.md index f3059eea50..8ab85e6be3 100644 --- a/docssrc/src/argument_multiliteral.md +++ b/docssrc/src/argument_multiliteral.md @@ -1,8 +1,8 @@ # Multi literal arguments -So far, we've described normal arguments and literal arguments. We've described the nuances with literal arguments and how they're not really "arguments", so they don't appear in the `CommandArguments args` for commands. +So far, we've described normal arguments and literal arguments. We've described the nuances with literal arguments and how they're not really "arguments", so they don't appear in the [`CommandArguments args`](./commandarguments.md) for commands. -Now forget all of that. Multi literal arguments are the same as literal arguments but they _do_ appear in the `CommandArguments args` for commands (i.e. they are [listed](./listed.md)). Multi literal arguments are just a way better alternative to literal arguments. The multi literal argument constructor allows you to provide a `String nodeName` and a `String... literals` of possible values which you can use for your command declaration. +Now forget all of that. Multi literal arguments are the same as literal arguments but they _do_ appear in the [`CommandArguments args`](./commandarguments.md) for commands (i.e. they are [listed](./listed.md)). Multi literal arguments are just a way better alternative to literal arguments. The multi literal argument constructor allows you to provide a `String nodeName` and a `String... literals` of possible values which you can use for your command declaration. The multi literal argument has all of the same benefits of a regular literal argument - they are hardcoded options that the user must enter - they don't allow other values. diff --git a/docssrc/src/arguments.md b/docssrc/src/arguments.md index 9284f33655..dc8f53ba30 100644 --- a/docssrc/src/arguments.md +++ b/docssrc/src/arguments.md @@ -75,7 +75,7 @@ The CommandAPI is very flexible when it comes to registering arguments, and lets ## Argument Casting -To access arguments, they have to be casted to the type that the argument represents. The order of the arguments in the `CommandArguments args` is the same as the order in which the arguments were declared. +To access arguments, they have to be casted to the type that the argument represents. The order of the arguments in the [`CommandArguments args`](./commandarguments.md) is the same as the order in which the arguments were declared.
@@ -133,7 +133,7 @@ The type to cast each argument (declared in the `dev.jorel.commandapi.arguments` | [`LocationArgument`](./argument_locations.md#location-3d-space) | `org.bukkit.Location` | | [`LongArgument`](./argument_primitives.md#numerical-arguments) | `long` | | [`LootTableArgument`](./argument_loottable.md) | `org.bukkit.loot.LootTable` | - | [`MapArgument`](./argument_map.md) | `java.util.LinkedhashMap` | + | [`MapArgument`](./argument_map.md) | `java.util.LinkedHashMap` | | [`MathOperationArgument`](./argument_mathoperation.md) | `dev.jorel.commandapi.wrappers.MathOperation` | | [`MultiLiteralArgument`](./argument_multiliteral.md) | `String` | | [`NamespacedKeyArgument`](./argument_namespacedkey.md) | `org.bukkit.NamespacedKey` | diff --git a/docssrc/src/listed.md b/docssrc/src/listed.md index 0d3163d161..f40d56bf82 100644 --- a/docssrc/src/listed.md +++ b/docssrc/src/listed.md @@ -1,8 +1,8 @@ # Listed arguments -Arguments have a setting which determine whether or not they are present in the `CommandArguments args` that is populated when executing a command. +Arguments have a setting which determine whether or not they are present in the [`CommandArguments args`](./commandarguments.md) that is populated when executing a command. -By default, the `LiteralArgument` has this setting set to `false`, hence the literal values are _not_ present in the `CommandArguments args`. +By default, the `LiteralArgument` has this setting set to `false`, hence the literal values are _not_ present in the [`CommandArguments args`](commandarguments.md). This flag is set using the following function: @@ -20,7 +20,7 @@ Say we have the following command: /mycommand ``` -Let's also say that in our implementation of this command, we don't actually perform any processing for ``. Hence, listing it in the `CommandArguments args` is unnecessary. +Let's also say that in our implementation of this command, we don't actually perform any processing for ``. Hence, listing it in the [`CommandArguments args`](./commandarguments.md) is unnecessary.
@@ -34,6 +34,6 @@ Let's also say that in our implementation of this command, we don't actually per
-In this scenario, the argument `` is not present in the `CommandArguments args` for the executor. +In this scenario, the argument `` is not present in the [`CommandArguments args`](./commandarguments.md) for the executor.
diff --git a/docssrc/src/normalexecutors.md b/docssrc/src/normalexecutors.md index c2f56ff032..1601ed1824 100644 --- a/docssrc/src/normalexecutors.md +++ b/docssrc/src/normalexecutors.md @@ -1,6 +1,6 @@ # Normal command executors -Command executors are of the following format, where `sender` is a [`CommandSender`](https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/command/CommandSender.html), and `args` is a `CommandArguments` object, which represents arguments which are parsed by the CommandAPI. +Command executors are of the following format, where `sender` is a [`CommandSender`](https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/command/CommandSender.html), and `args` is a [`CommandArguments`](./commandarguments.md) object, which represents arguments which are parsed by the CommandAPI. ```java new CommandAPICommand("...") diff --git a/docssrc/src/optional_arguments.md b/docssrc/src/optional_arguments.md index 1578a57fd3..1c5462abb9 100644 --- a/docssrc/src/optional_arguments.md +++ b/docssrc/src/optional_arguments.md @@ -78,7 +78,7 @@ However, calling `withOptionalArguments` is safer because it makes sure that the ## Avoiding null values -Previously, we've looked at how to handle null values. To make all of this easier, the CommandAPI implements multiple `getOptional()` methods for `CommandArguments`: +Previously, we've looked at how to handle null values. To make all of this easier, the CommandAPI implements multiple `getOptional()` methods for [`CommandArguments`](./commandarguments.md):
diff --git a/docssrc/src/stringargumentsuggestions.md b/docssrc/src/stringargumentsuggestions.md index 3d640d8925..401ea65ae4 100644 --- a/docssrc/src/stringargumentsuggestions.md +++ b/docssrc/src/stringargumentsuggestions.md @@ -104,7 +104,7 @@ This won't work, because we make use of a redirect: \\(\texttt{/execute run} \xrightarrow{redirect} \texttt{mycommand arg1 arg2 arg3}\\) -It is not possible to access the `CommandArguments` of previously declared arguments. **If a command occurs via a redirect, the `CommandArguments` of previously declared arguments will be null**. +It is not possible to access the [`CommandArguments`](./commandarguments.md) of previously declared arguments. **If a command occurs via a redirect, the [`CommandArguments`](./commandarguments.md) of previously declared arguments will be null**.
diff --git a/docssrc/src/upgrading.md b/docssrc/src/upgrading.md index 6b3abd6206..40ba2b5bf9 100644 --- a/docssrc/src/upgrading.md +++ b/docssrc/src/upgrading.md @@ -28,7 +28,7 @@ withArguments(new MultiLiteralArgument("gamemodes", "survival", "creative", "adv ### MultiLiteralArgument and LiteralArgument changes -In previous versions, the ability has been introduced to access arguments by their node names. However, while this was possible for every other argument, it wasn't possible for `MultiLiteralArgument`s. This was now changed because the values from the `MultiLiteralArgument` are included in the `CommandArguments` of a command. +In previous versions, the ability has been introduced to access arguments by their node names. However, while this was possible for every other argument, it wasn't possible for `MultiLiteralArgument`s. This was now changed because the values from the `MultiLiteralArgument` are included in the [`CommandArguments`](./commandarguments.md) of a command. Therefore, the current constructor has been deprecated and the new one should be used: @@ -50,7 +50,7 @@ withArguments(new MultiLiteralArgument("gamemodes", List.of("survival", "creativ
-Because it is possible to list `LiteralArgument`s in the `CommandArguments` of a command, there was also an additional constructor add to the `LiteralArgument` class. The other one is not deprecated. +Because it is possible to list `LiteralArgument`s in the [`CommandArguments`](./commandarguments.md) of a command, there was also an additional constructor add to the `LiteralArgument` class. The other one is not deprecated. Now, the `LiteralArgument` class contains two possible constructors: From 5643f0dca98bdf518d2c410628bbee05d1512127 Mon Sep 17 00:00:00 2001 From: DerEchtePilz Date: Sat, 1 Jul 2023 02:06:23 +0200 Subject: [PATCH 15/28] Update intro.md, optional_arguments.md and upgrading.md --- docssrc/src/intro.md | 1 + docssrc/src/optional_arguments.md | 19 +++++++------------ docssrc/src/upgrading.md | 4 ++++ 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docssrc/src/intro.md b/docssrc/src/intro.md index ac4b8c7a5b..2d296967cb 100644 --- a/docssrc/src/intro.md +++ b/docssrc/src/intro.md @@ -40,6 +40,7 @@ Here's the list of changes to the documentation between each update. You can vie ### Documentation changes 9.0.3 \\(\rightarrow\\) 9.0.4 - Updates [Multi literal arguments](./argument_multiliteral.md) page to mention new `MultiLiteralArgument` constructor +- Adds [CommandArguments](./commandarguments.md) page to explain the `CommandArguments` class introduced in 9.0.0 ### Documentation changes 9.0.2 \\(\rightarrow\\) 9.0.3 diff --git a/docssrc/src/optional_arguments.md b/docssrc/src/optional_arguments.md index 1c5462abb9..ac47fec0b1 100644 --- a/docssrc/src/optional_arguments.md +++ b/docssrc/src/optional_arguments.md @@ -78,24 +78,19 @@ However, calling `withOptionalArguments` is safer because it makes sure that the ## Avoiding null values -Previously, we've looked at how to handle null values. To make all of this easier, the CommandAPI implements multiple `getOptional()` methods for [`CommandArguments`](./commandarguments.md): - -
- -> **Developer's Note:** -> -> For 9.0.1, all `CommandArguments#getOrDefault()` methods have been deprecated and new methods have been added! -> The existing methods will be removed in an upcoming version! -> -> View the new methods below: - -
+Previously, we've looked at how to handle null values. To make all of this easier, the CommandAPI implements multiple additional methods for [`CommandArguments`](./commandarguments.md): ```java +Object getOrDefault(int index, Object defaultValue); +Object getOrDefault(int index, Supplier defaultValue); +Object getOrDefault(String nodeName, Object defaultValue); +Object getOrDefault(String nodeName, Supplier defaultValue); Optional getOptional(int index) Optional getOptional(String nodeName) ``` +The examples will be using the `getOptional` methods but there is no downside of using the `getOrDefault` methods. +
### Example - /sayhi command while using the getOptional method diff --git a/docssrc/src/upgrading.md b/docssrc/src/upgrading.md index 40ba2b5bf9..453f5f593c 100644 --- a/docssrc/src/upgrading.md +++ b/docssrc/src/upgrading.md @@ -24,6 +24,10 @@ withArguments(new MultiLiteralArgument("gamemodes", "survival", "creative", "adv
+### CommandArguments changes + +For 9.0.4 all deprecated methods are no longer deprecated. To learn about all the methods now available, refer to the [CommandArguments](./commandarguments.md) page. + ## From 9.0.1 to 9.0.2 ### MultiLiteralArgument and LiteralArgument changes From 6ebf8e1ec90cc87be0a037fd30bdd6af33132702 Mon Sep 17 00:00:00 2001 From: DerEchtePilz Date: Mon, 3 Jul 2023 17:26:47 +0200 Subject: [PATCH 16/28] Remove 'What terms are used' section, refactor 'Access the inner structure' section --- docssrc/src/commandarguments.md | 90 ++++++++++++++------------------- 1 file changed, 39 insertions(+), 51 deletions(-) diff --git a/docssrc/src/commandarguments.md b/docssrc/src/commandarguments.md index 56a0f13535..8943e41fbe 100644 --- a/docssrc/src/commandarguments.md +++ b/docssrc/src/commandarguments.md @@ -5,19 +5,9 @@ The `CommandArguments` class was introduced in CommandAPI 9.0.0 and provides a m While the argument array just gives the possibility to access the arguments via the array notation (`args[0]`), the `CommandArguments` class offers much more, including: - [Access the inner structure directly](#access-the-inner-structure-directly) -- [What terms are used?](#what-terms-are-used) - - [`nodeName`](#nodename) - - [`raw argument`](#raw-argument) - - [`unsafe argument`](#unsafe-argument) - [Access arguments](#access-arguments) - - [Access arguments by node name](#access-arguments-by-node-name) - - [Access arguments by index](#access-arguments-by-index) - [Access raw arguments](#access-raw-arguments) - - [Access raw arguments by node name](#access-raw-arguments-by-node-name) - - [Access raw arguments by index](#access-raw-arguments-by-index) - [Access unsafe arguments](#access-unsafe-arguments) - - [Access arguments by node name](#access-arguments-by-node-name-1) - - [Access arguments by index](#access-arguments-by-index-1) ATTENTION!!!!! Every executable and generated documentation has to be deleted before committing anything! @@ -25,68 +15,47 @@ ATTENTION!!!!! Every executable and generated documentation has to be deleted be ## Access the inner structure directly -To provide arguments, the `CommandArguments` class stores: +To access the inner structure of the `CommandArguments` class directly, it provides various methods which you can learn about below: -- a `Object[]` of parsed arguments -- a `Map` of parsed arguments mapped to their node names -- a `String[]` of raw arguments -- a `Map` of raw arguments mapped to their node names -- a `String` which holds the full input - -Although not recommended, it is possible to access these fields directly with methods the `CommandArguments` class provides: +**Get the argument array** ```java -Object[] args(); // Returns the argument array -Map argsMap(); // Returns an unmodifiable map containing the arguments mapped to their node names -String[] rawArgs(); // Returns the raw argument array -Map rawArgsMap(); // Returns an unmodifiable map containing the raw arguments mapped to their node names -String getFullInput(); // Returns the full command string (including the /) +Object[] args(); ``` -Additionally, the `CommandArguments` class has one more method that isn't directly backed by a field and returns the amount of arguments for a command: +This returns the array of arguments as defined when creating your command. + +**Get the arguments mapped to their node name** ```java -int count(); +Map argsMap(); ``` -While these methods can be used to access arguments, it may be safer to use the other methods the `CommandArguments` class provides to access arguments. +This returns an unmodifiable map which contains the arguments mapped to their node names. ------ +**Get the raw argument array** -## What terms are used? - -Throughout this page, multiple terms are used that may need an explanation. +```java +String[] rawArgs(); + ``` -### `nodeName` +This returns the array of raw arguments. An explanation of what raw arguments are can be found in the section about [accessing raw arguments](#access-raw-arguments). -The `nodeName` is set when initializing an argument. For example: +**Get the raw arguments mapped to their node name** ```java -new StringArgument("string") +Map rawArgsMap(); ``` -The `nodeName` here would be `string`. +This returns an unmodifiable map which contains the raw arguments mapped to their node names. An explanation of what raw arguments are can be found in the section about [accessing raw arguments](#access-raw-arguments). -### `raw argument` +**Other useful methods** -A "raw argument" is the `String` form of an argument as written in a command. For example: - -A user defines a command `/mycommand` that accepts a `double` as the first argument and an entity selector as the second argument. It could be executed with the values `15.3` as the `double` value and `@e` as the entity selector: - -```mccmd -/mycommand 15.3 @e +```java +String getFullInput(); // Returns the full command input (including the / character) +int count(); // Returns the amount of arguments ``` -When [accessing the raw arguments](#access-raw-arguments) of this command there are `15.3` and `@e` available as `String`s. - -However, when [accessing the arguments](#access-arguments) of this command there is `15.3` available as `double` and `@e` available as `Collection`. - -### `unsafe argument` - -When [accessing arguments](#access-arguments) you need to cast the `Object` returned by these methods to the type the argument returns. More about casting arguments [here](./arguments.md#argument-casting). - -However, the `CommandArguments` class provides a way to remove the need to cast the arguments which is referred to as `unsafe arguments` in this page. - ----- ## Access arguments @@ -131,6 +100,19 @@ Optional getOptional(int index); ## Access raw arguments +A "raw argument" is the `String` form of an argument as written in a command. For example: + +A user defines a command `/mycommand` that accepts a `double` as the first argument and an entity selector as the second argument. It could be executed with the values `15.3` as the `double` value and `@e` as the entity selector: + +```mccmd +/mycommand 15.3 @e +``` + +When [accessing the raw arguments](#access-raw-arguments) of this command there are `15.3` and `@e` available as `String`s. + +However, when [accessing the arguments](#access-arguments) of this command there is `15.3` available as `double` and `@e` available as `Collection`. + + Raw arguments are accessed basically the same way you would [access arguments](#access-arguments). You can access them by their node name and their index in the argument array. ### Access raw arguments by node name @@ -167,8 +149,14 @@ Optional getRawOptional(int index); ## Access unsafe arguments +When [accessing arguments](#access-arguments) you need to cast the `Object` returned by these methods to the type the argument returns. More about casting arguments [here](./arguments.md#argument-casting). + +However, the `CommandArguments` class provides a way to remove the need to cast the arguments which is referred to as `unsafe arguments` in this page. + Accessing unsafe arguments is a nice way to shorten your code as you do not need to cast the argument to its corresponding type. +_insert example of what an unsafe argument is_ + Unsafe arguments can also be accessed by their node names and their indices. ### Access arguments by node name From e2fd959719003adb25c95bfe5a56a118c9806e8d Mon Sep 17 00:00:00 2001 From: DerEchtePilz Date: Tue, 4 Jul 2023 23:03:31 +0200 Subject: [PATCH 17/28] Improve explanation for unsafe arguments --- docssrc/src/commandarguments.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/docssrc/src/commandarguments.md b/docssrc/src/commandarguments.md index 8943e41fbe..25b7fe2e08 100644 --- a/docssrc/src/commandarguments.md +++ b/docssrc/src/commandarguments.md @@ -112,7 +112,6 @@ When [accessing the raw arguments](#access-raw-arguments) of this command there However, when [accessing the arguments](#access-arguments) of this command there is `15.3` available as `double` and `@e` available as `Collection`. - Raw arguments are accessed basically the same way you would [access arguments](#access-arguments). You can access them by their node name and their index in the argument array. ### Access raw arguments by node name @@ -151,11 +150,17 @@ Optional getRawOptional(int index); When [accessing arguments](#access-arguments) you need to cast the `Object` returned by these methods to the type the argument returns. More about casting arguments [here](./arguments.md#argument-casting). -However, the `CommandArguments` class provides a way to remove the need to cast the arguments which is referred to as `unsafe arguments` in this page. +Unsafe arguments provide the ability to access an argument without needing to cast it to the argument's type. When not using unsafe arguments, your code looks like this: + +```java +String name = (String) args.get("name"); +``` -Accessing unsafe arguments is a nice way to shorten your code as you do not need to cast the argument to its corresponding type. +When using unsafe arguments you can make your code look like this: -_insert example of what an unsafe argument is_ +```java +String name = args.getUnchecked("name"); +``` Unsafe arguments can also be accessed by their node names and their indices. From a3db5eae1292efe87503c92b8ff435b961f053ba Mon Sep 17 00:00:00 2001 From: DerEchtePilz Date: Tue, 4 Jul 2023 23:38:12 +0200 Subject: [PATCH 18/28] Add an explanation of raw arguments to the JavaDocs for methods dealing with raw arguments --- .../executors/CommandArguments.java | 65 +++++++++++++++---- 1 file changed, 53 insertions(+), 12 deletions(-) diff --git a/commandapi-core/src/main/java/dev/jorel/commandapi/executors/CommandArguments.java b/commandapi-core/src/main/java/dev/jorel/commandapi/executors/CommandArguments.java index 81cc9cacd6..0994ae7228 100644 --- a/commandapi-core/src/main/java/dev/jorel/commandapi/executors/CommandArguments.java +++ b/commandapi-core/src/main/java/dev/jorel/commandapi/executors/CommandArguments.java @@ -2,6 +2,7 @@ import javax.annotation.Nullable; +import java.util.Collection; import java.util.Collections; import java.util.Map; import java.util.Optional; @@ -106,7 +107,7 @@ public Object get(int index) { * Returns an argument by its node name * * @param nodeName The node name of this argument. This was set when initializing an argument - * @return An argument which has the given node name. Can be null if nodeName was not found. + * @return An argument which has the given node name. Can be {@code null} if nodeName was not found. */ @Nullable public Object get(String nodeName) { @@ -194,6 +195,12 @@ public Optional getOptional(String nodeName) { /** * Returns a raw argument by its position + *

+ * A raw argument is the {@link String} form of an argument as written in a command. For example take this command: + *

+ * {@code /mycommand @e 15.3} + *

+ * When using this method to access these arguments, {@code @e} and {@code 15.3} will be available as {@link String}s and not as a {@link Collection} and {@link Double} * * @param index The position of this argument * @return An argument which is placed at the given index, or {@code null} if the provided index does not point to an argument. @@ -209,9 +216,15 @@ public String getRaw(int index) { /** * Returns a raw argument by its node name + *

+ * A raw argument is the {@link String} form of an argument as written in a command. For example take this command: + *

+ * {@code /mycommand @e 15.3} + *

+ * When using this method to access these arguments, {@code @e} and {@code 15.3} will be available as {@link String}s and not as a {@link Collection} and {@link Double} * * @param nodeName The node name of this argument. This was set when initializing an argument - * @return A raw argument which has the given node name. Can be null if nodeName was not found. + * @return A raw argument which has the given node name. Can be {@code null} if nodeName was not found. */ @Nullable public String getRaw(String nodeName) { @@ -220,6 +233,12 @@ public String getRaw(String nodeName) { /** * Returns a raw argument by its index + *

+ * A raw argument is the {@link String} form of an argument as written in a command. For example take this command: + *

+ * {@code /mycommand @e 15.3} + *

+ * When using this method to access these arguments, {@code @e} and {@code 15.3} will be available as {@link String}s and not as a {@link Collection} and {@link Double} * * @param index The position of this argument * @param defaultValue The String returned if the raw argument is not existent @@ -235,6 +254,12 @@ public String getOrDefaultRaw(int index, String defaultValue) { /** * Returns a raw argument by its node name + *

+ * A raw argument is the {@link String} form of an argument as written in a command. For example take this command: + *

+ * {@code /mycommand @e 15.3} + *

+ * When using this method to access these arguments, {@code @e} and {@code 15.3} will be available as {@link String}s and not as a {@link Collection} and {@link Double} * * @param nodeName The node name of this argument. This was set when initializing an argument * @param defaultValue The String returned if the raw argument was not found. @@ -246,6 +271,12 @@ public String getOrDefaultRaw(String nodeName, String defaultValue) { /** * Returns a raw argument by its index + *

+ * A raw argument is the {@link String} form of an argument as written in a command. For example take this command: + *

+ * {@code /mycommand @e 15.3} + *

+ * When using this method to access these arguments, {@code @e} and {@code 15.3} will be available as {@link String}s and not as a {@link Collection} and {@link Double} * * @param index The position of this argument * @param defaultValue The String returned if the raw argument is not existent @@ -261,6 +292,12 @@ public String getOrDefaultRaw(int index, Supplier defaultValue) { /** * Returns a raw argument by its node name + *

+ * A raw argument is the {@link String} form of an argument as written in a command. For example take this command: + *

+ * {@code /mycommand @e 15.3} + *

+ * When using this method to access these arguments, {@code @e} and {@code 15.3} will be available as {@link String}s and not as a {@link Collection} and {@link Double} * * @param nodeName The node name of this raw argument. This was set when initializing an argument * @param defaultValue The String returned if the raw argument was not found. @@ -271,7 +308,13 @@ public String getOrDefaultRaw(String nodeName, Supplier defaultValue) { } /** - * Returns an Optional holding the raw argument by its index + * Returns an {@link Optional} holding the raw argument by its index + *

+ * A raw argument is the {@link String} form of an argument as written in a command. For example take this command: + *

+ * {@code /mycommand @e 15.3} + *

+ * When using this method to access these arguments, {@code @e} and {@code 15.3} will be available as {@link String}s and not as a {@link Collection} and {@link Double} * * @param index The position of this argument * @return An optional holding the raw argument which is placed at the given index, or an empty optional if index is invalid @@ -285,7 +328,13 @@ public Optional getRawOptional(int index) { } /** - * Returns an argument by its node name + * Returns an {@link Optional} holding the raw argument by its node name + *

+ * A raw argument is the {@link String} form of an argument as written in a command. For example take this command: + *

+ * {@code /mycommand @e 15.3} + *

+ * When using this method to access these arguments, {@code @e} and {@code 15.3} will be available as {@link String}s and not as a {@link Collection} and {@link Double} * * @param nodeName The node name of this argument. This was set when initializing an argument * @return An optional holding the argument with the specified node name or an empty optional if the node name was not found @@ -309,14 +358,6 @@ public Optional getRawOptional(String nodeName) { * CommandArguments args = ...; * String myString = args.getUnchecked("target"); * - * These methods are to be avoided in Kotlin as Kotlin's type inference - * system cannot infer the type variable T by default and would require - * explicit generic type parameters or type declaration, as well as a - * non-null assertion operator: - * - * val args: CommandArguments = ... - * val myString = args.getUnchecked("target")!! // Needs this - * val myString: String = args.getUnchecked(0)!! // Or this */ /** From c8c1de6e31b4d75e42530315b4e7b2fd03db4ec6 Mon Sep 17 00:00:00 2001 From: DerEchtePilz Date: Tue, 4 Jul 2023 23:40:41 +0200 Subject: [PATCH 19/28] Remove unnecessary sentence from commandarguments.md --- docssrc/src/commandarguments.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docssrc/src/commandarguments.md b/docssrc/src/commandarguments.md index 25b7fe2e08..dbb984c249 100644 --- a/docssrc/src/commandarguments.md +++ b/docssrc/src/commandarguments.md @@ -9,8 +9,6 @@ While the argument array just gives the possibility to access the arguments via - [Access raw arguments](#access-raw-arguments) - [Access unsafe arguments](#access-unsafe-arguments) -ATTENTION!!!!! Every executable and generated documentation has to be deleted before committing anything! - ----- ## Access the inner structure directly From 7ff5cf694f3167012c3302526cb7bdd1e6bc2f13 Mon Sep 17 00:00:00 2001 From: DerEchtePilz Date: Wed, 5 Jul 2023 00:00:28 +0200 Subject: [PATCH 20/28] Convert CommandArguments.java into a record --- .../executors/CommandArguments.java | 49 ++++--------------- docssrc/src/commandarguments.md | 2 +- 2 files changed, 11 insertions(+), 40 deletions(-) diff --git a/commandapi-core/src/main/java/dev/jorel/commandapi/executors/CommandArguments.java b/commandapi-core/src/main/java/dev/jorel/commandapi/executors/CommandArguments.java index 0994ae7228..b448b1c30a 100644 --- a/commandapi-core/src/main/java/dev/jorel/commandapi/executors/CommandArguments.java +++ b/commandapi-core/src/main/java/dev/jorel/commandapi/executors/CommandArguments.java @@ -10,49 +10,18 @@ /** * This class stores the arguments for this command + * + * @param args The arguments for this command + * @param argsMap The arguments for this command mapped to their node names. This is an ordered map + * @param rawArgs The raw arguments for this command. + * @param rawArgsMap The raw arguments for this command mapped to their node names. This is an ordered map + * @param fullInput The command string a player has entered (including the /) */ @SuppressWarnings("unchecked") -public class CommandArguments { - - private final Object[] args; - private final String[] rawArgs; - private final Map argsMap; - private final Map rawArgsMap; - private final String fullInput; - - /** - * Constructs a new CommandArguments instance - * - * @param args The arguments for this command - * @param argsMap The arguments for this command mapped to their node names. This is an ordered map - * @param rawArgs The raw arguments for this command. - * @param rawArgsMap The raw arguments for this command mapped to their node names. This is an ordered map - * @param fullInput The raw command a player has entered - */ - public CommandArguments(Object[] args, Map argsMap, String[] rawArgs, Map rawArgsMap, String fullInput) { - this.args = args; - this.rawArgs = rawArgs; - this.argsMap = argsMap; - this.rawArgsMap = rawArgsMap; - this.fullInput = fullInput; - } +public record CommandArguments(Object[] args, Map argsMap, String[] rawArgs, Map rawArgsMap, String fullInput) { // Access the inner structure directly - /** - * @return The complete argument array of this command - */ - public Object[] args() { - return args; - } - - /** - * @return The complete raw argument array of this command - */ - public String[] rawArgs() { - return rawArgs; - } - /** * @return An unmodifiable clone of the mapping of node names to argument values */ @@ -70,14 +39,16 @@ public Map rawArgsMap() { /** * This returns the raw command string a player has entered * + * @deprecated This method has been deprecated in favour of {@link CommandArguments#fullInput()} * @return The raw command string a player has entered */ + @Deprecated(since = "9.0.4", forRemoval = true) public String getFullInput() { return fullInput; } /** - * @return The number of arguments in this object + * @return The number of arguments for this command */ public int count() { return args.length; diff --git a/docssrc/src/commandarguments.md b/docssrc/src/commandarguments.md index dbb984c249..370bfaacc3 100644 --- a/docssrc/src/commandarguments.md +++ b/docssrc/src/commandarguments.md @@ -50,7 +50,7 @@ This returns an unmodifiable map which contains the raw arguments mapped to thei **Other useful methods** ```java -String getFullInput(); // Returns the full command input (including the / character) +String fullInput(); // Returns the full command input (including the / character) int count(); // Returns the amount of arguments ``` From c5916bb17b5285b0084e86a928fb6b306429fdba Mon Sep 17 00:00:00 2001 From: DerEchtePilz Date: Wed, 5 Jul 2023 00:29:20 +0200 Subject: [PATCH 21/28] Replace usage of CommandArguments#getFullInput in CommandAPIExecutor with CommandArguments#fullInput --- .../main/java/dev/jorel/commandapi/CommandAPIExecutor.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/commandapi-core/src/main/java/dev/jorel/commandapi/CommandAPIExecutor.java b/commandapi-core/src/main/java/dev/jorel/commandapi/CommandAPIExecutor.java index 19d45814bf..afa28015e3 100644 --- a/commandapi-core/src/main/java/dev/jorel/commandapi/CommandAPIExecutor.java +++ b/commandapi-core/src/main/java/dev/jorel/commandapi/CommandAPIExecutor.java @@ -83,7 +83,7 @@ public int execute(ExecutionInfo info) throws Comman } catch (WrapperCommandSyntaxException e) { throw e.getException(); } catch (Throwable ex) { - CommandAPI.getLogger().severe("Unhandled exception executing '" + info.args().getFullInput() + "'", ex); + CommandAPI.getLogger().severe("Unhandled exception executing '" + info.args().fullInput() + "'", ex); if (ex instanceof Exception) { throw ex; } else { @@ -97,7 +97,7 @@ public int execute(ExecutionInfo info) throws Comman } catch (WrapperCommandSyntaxException e) { throw e.getException(); } catch (Throwable ex) { - CommandAPI.getLogger().severe("Unhandled exception executing '" + info.args().getFullInput() + "'", ex); + CommandAPI.getLogger().severe("Unhandled exception executing '" + info.args().fullInput() + "'", ex); if (ex instanceof Exception) { throw ex; } else { From b1104a313a41b3674c98f6d3244381fee48731da Mon Sep 17 00:00:00 2001 From: DerEchtePilz Date: Wed, 5 Jul 2023 10:34:17 +0200 Subject: [PATCH 22/28] Make Java examples use the node name to access arguments --- .../commandapi/examples/java/Examples.java | 226 +++++++++--------- 1 file changed, 113 insertions(+), 113 deletions(-) diff --git a/commandapi-documentation-code/src/main/java/dev/jorel/commandapi/examples/java/Examples.java b/commandapi-documentation-code/src/main/java/dev/jorel/commandapi/examples/java/Examples.java index a8de923b2a..d84d06ed66 100644 --- a/commandapi-documentation-code/src/main/java/dev/jorel/commandapi/examples/java/Examples.java +++ b/commandapi-documentation-code/src/main/java/dev/jorel/commandapi/examples/java/Examples.java @@ -104,8 +104,8 @@ void advancementArgument() { .withArguments(new PlayerArgument("player")) .withArguments(new AdvancementArgument("advancement")) .executes((sender, args) -> { - Player target = (Player) args.get(0); - Advancement advancement = (Advancement) args.get(1); + Player target = (Player) args.get("player"); + Advancement advancement = (Advancement) args.get("advancement"); // Award all criteria for the advancement AdvancementProgress progress = target.getAdvancementProgress(advancement); @@ -151,7 +151,7 @@ void argument_angle() { .withArguments(new AngleArgument("amount")) .executesPlayer((player, args) -> { Location newLocation = player.getLocation(); - newLocation.setYaw((float) args.get(0)); + newLocation.setYaw((float) args.get("amount")); player.teleport(newLocation); }) .register(); @@ -163,7 +163,7 @@ void argument_biome() { new CommandAPICommand("setbiome") .withArguments(new BiomeArgument("biome")) .executesPlayer((player, args) -> { - Biome biome = (Biome) args.get(0); + Biome biome = (Biome) args.get("biome"); Chunk chunk = player.getLocation().getChunk(); player.getWorld().setBiome(chunk.getX(), player.getLocation().getBlockY(), chunk.getZ(), biome); @@ -187,10 +187,10 @@ void argument_blockPredicate() { .executesPlayer((player, args) -> { // Parse the arguments - int radius = (int) args.get(0); + int radius = (int) args.get("radius"); @SuppressWarnings("unchecked") - Predicate predicate = (Predicate) args.get(1); - BlockData blockData = (BlockData) args.get(2); + Predicate predicate = (Predicate) args.get("fromBlock"); + BlockData blockData = (BlockData) args.get("toBlock"); // Find a (solid) sphere of blocks around the player with a given radius Location center = player.getLocation(); @@ -220,7 +220,7 @@ void argument_blockState() { new CommandAPICommand("set") .withArguments(new BlockStateArgument("block")) .executesPlayer((player, args) -> { - BlockData blockdata = (BlockData) args.get(0); + BlockData blockdata = (BlockData) args.get("block"); Block targetBlock = player.getTargetBlockExact(256); // Set the block, along with its data @@ -239,10 +239,10 @@ void argument_chatAdventure() { .withArguments(new StringArgument("author")) .withArguments(new AdventureChatComponentArgument("contents")) .executes((sender, args) -> { - Player target = (Player) args.get(0); - String title = (String) args.get(1); - String author = (String) args.get(2); - Component content = (Component) args.get(3); + Player target = (Player) args.get("target"); + String title = (String) args.get("title"); + String author = (String) args.get("author"); + Component content = (Component) args.get("contents"); // Create a book and show it to the user (Requires Paper) Book mybook = Book.book(Component.text(title), Component.text(author), content); @@ -255,7 +255,7 @@ void argument_chatAdventure() { new CommandAPICommand("pbroadcast") .withArguments(new AdventureChatArgument("message")) .executes((sender, args) -> { - Component message = (Component) args.get(0); + Component message = (Component) args.get("message"); // Broadcast the message to everyone with broadcast permissions. Bukkit.getServer().broadcast(message, Server.BROADCAST_CHANNEL_USERS); @@ -271,7 +271,7 @@ void argument_chats(){ new CommandAPICommand("namecolor") .withArguments(new ChatColorArgument("chatcolor")) .executesPlayer((player, args) -> { - ChatColor color = (ChatColor) args.get(0); + ChatColor color = (ChatColor) args.get("chatcolor"); player.setDisplayName(color + player.getName()); }) .register(); @@ -284,8 +284,8 @@ void argument_chatSpigot() { .withArguments(new PlayerArgument("player")) .withArguments(new ChatComponentArgument("contents")) .executes((sender, args) -> { - Player player = (Player) args.get(0); - BaseComponent[] arr = (BaseComponent[]) args.get(1); + Player player = (Player) args.get("player"); + BaseComponent[] arr = (BaseComponent[]) args.get("contents"); // Create book ItemStack is = new ItemStack(Material.WRITTEN_BOOK); @@ -305,7 +305,7 @@ void argument_chatSpigot() { new CommandAPICommand("pbroadcast") .withArguments(new ChatArgument("message")) .executes((sender, args) -> { - BaseComponent[] message = (BaseComponent[]) args.get(0); + BaseComponent[] message = (BaseComponent[]) args.get("message"); // Broadcast the message to everyone on the server Bukkit.getServer().spigot().broadcast(message); @@ -320,8 +320,8 @@ void argument_command() { .withArguments(new PlayerArgument("target")) .withArguments(new CommandArgument("command")) .executes((sender, args) -> { - Player target = (Player) args.get(0); - CommandResult command = (CommandResult) args.get(1); + Player target = (Player) args.get("target"); + CommandResult command = (CommandResult) args.get("command"); command.execute(target); }) @@ -408,7 +408,7 @@ public Argument customWorldArgument(String nodeName) { new CommandAPICommand("tpworld") .withArguments(customWorldArgument("world")) .executesPlayer((player, args) -> { - player.teleport(((World) args.get(0)).getSpawnLocation()); + player.teleport(((World) args.get("world")).getSpawnLocation()); }) .register(); /* ANCHOR_END: argumentCustom2 */ @@ -421,8 +421,8 @@ void argument_enchantment() { .withArguments(new EnchantmentArgument("enchantment")) .withArguments(new IntegerArgument("level", 1, 5)) .executesPlayer((player, args) -> { - Enchantment enchantment = (Enchantment) args.get(0); - int level = (int) args.get(1); + Enchantment enchantment = (Enchantment) args.get("enchantment"); + int level = (int) args.get("level"); // Add the enchantment player.getInventory().getItemInMainHand().addEnchantment(enchantment, level); @@ -439,7 +439,7 @@ void argument_entities() { .executes((sender, args) -> { // Parse the argument as a collection of entities (as stated above in the documentation) @SuppressWarnings("unchecked") - Collection entities = (Collection) args.get(0); + Collection entities = (Collection) args.get("entities"); sender.sendMessage("Removed " + entities.size() + " entities"); for (Entity e : entities) { @@ -454,8 +454,8 @@ void argument_entities() { .withArguments(new EntityTypeArgument("entity")) .withArguments(new IntegerArgument("amount", 1, 100)) // Prevent spawning too many entities .executesPlayer((Player player, CommandArguments args) -> { - for (int i = 0; i < (int) args.get(1); i++) { - player.getWorld().spawnEntity(player.getLocation(), (EntityType) args.get(0)); + for (int i = 0; i < (int) args.get("amount"); i++) { + player.getWorld().spawnEntity(player.getLocation(), (EntityType) args.get("entity")); } }) .register(); @@ -467,7 +467,7 @@ void argument_function() { new CommandAPICommand("runfunction") .withArguments(new FunctionArgument("function")) .executes((sender, args) -> { - FunctionWrapper[] functions = (FunctionWrapper[]) args.get(0); + FunctionWrapper[] functions = (FunctionWrapper[]) args.get("function"); // Run all functions in our FunctionWrapper[] for (FunctionWrapper function : functions) { @@ -481,9 +481,9 @@ void argument_function() { void argument_itemStack() { /* ANCHOR: argumentItemStack1 */ new CommandAPICommand("item") - .withArguments(new ItemStackArgument("itemstack")) + .withArguments(new ItemStackArgument("itemStack")) .executesPlayer((player, args) -> { - player.getInventory().addItem((ItemStack) args.get(0)); + player.getInventory().addItem((ItemStack) args.get("itemStack")); }) .register(); /* ANCHOR_END: argumentItemStack1 */ @@ -498,7 +498,7 @@ void argument_itemStackPredicate() { // Get our predicate @SuppressWarnings("unchecked") - Predicate predicate = (Predicate) args.get(0); + Predicate predicate = (Predicate) args.get("items"); for (ItemStack item : player.getInventory()) { if (predicate.test(item)) { @@ -520,8 +520,8 @@ void argument_list() { .buildGreedy() ) .executesPlayer((player, args) -> { - int amount = (int) args.get(0); - List theList = (List) args.get(1); + int amount = (int) args.get("amount"); + List theList = (List) args.get("materials"); for (Material item : theList) { player.getInventory().addItem(new ItemStack(item, amount)); @@ -592,7 +592,7 @@ void argument_locations() { // We want to target blocks in particular, so use BLOCK_POSITION .withArguments(new LocationArgument("block", LocationType.BLOCK_POSITION)) .executesPlayer((player, args) -> { - Location location = (Location) args.get(0); + Location location = (Location) args.get("block"); location.getBlock().setType(Material.AIR); }) .register(); @@ -602,11 +602,11 @@ void argument_locations() { void argument_lootTable() { /* ANCHOR: argumentLootTable1 */ new CommandAPICommand("giveloottable") - .withArguments(new LootTableArgument("loottable")) + .withArguments(new LootTableArgument("lootTable")) .withArguments(new LocationArgument("location", LocationType.BLOCK_POSITION)) .executes((sender, args) -> { - LootTable lootTable = (LootTable) args.get(0); - Location location = (Location) args.get(1); + LootTable lootTable = (LootTable) args.get("lootTable"); + Location location = (Location) args.get("location"); BlockState state = location.getBlock().getState(); @@ -666,9 +666,9 @@ void argument_mathOperation() { .withArguments(new MathOperationArgument("operation")) .withArguments(new IntegerArgument("value")) .executes((sender, args) -> { - Player target = (Player) args.get(0); - MathOperation op = (MathOperation) args.get(1); - int value = (int) args.get(2); + Player target = (Player) args.get("player"); + MathOperation op = (MathOperation) args.get("operation"); + int value = (int) args.get("value"); target.setLevel(op.apply(target.getLevel(), value)); }) @@ -683,7 +683,7 @@ void argument_multiLiteral() { .withArguments(new MultiLiteralArgument("gamemodes", "adventure", "creative", "spectator", "survival")) .executesPlayer((player, args) -> { // The literal string that the player enters IS available in the args[] - switch((String) args.get(0)) { + switch ((String) args.get("gamemodes")) { case "adventure": player.setGameMode(GameMode.ADVENTURE); break; @@ -697,7 +697,7 @@ void argument_multiLiteral() { player.setGameMode(GameMode.SURVIVAL); break; default: - player.sendMessage("Invalid gamemode: " + args.get(0)); + player.sendMessage("Invalid gamemode: " + args.get("gamemodes")); break; } }) @@ -720,7 +720,7 @@ void argument_nbt2() { new CommandAPICommand("award") .withArguments(new NBTCompoundArgument("nbt")) .executes((sender, args) -> { - NBTContainer nbt = (NBTContainer) args.get(0); + NBTContainer nbt = (NBTContainer) args.get("nbt"); // Do something with "nbt" here... }) @@ -734,7 +734,7 @@ void argument_objectives() { new CommandAPICommand("sidebar") .withArguments(new ObjectiveArgument("objective")) .executes((sender, args) -> { - Objective objective = (Objective) args.get(0); + Objective objective = (Objective) args.get("objective"); // Set display slot objective.setDisplaySlot(DisplaySlot.SIDEBAR); @@ -746,7 +746,7 @@ void argument_objectives() { new CommandAPICommand("unregisterall") .withArguments(new ObjectiveCriteriaArgument("objective criteria")) .executes((sender, args) -> { - String objectiveCriteria = (String) args.get(0); + String objectiveCriteria = (String) args.get("objective criteria"); Set objectives = Bukkit.getScoreboardManager().getMainScoreboard().getObjectivesByCriteria(objectiveCriteria); // Unregister the objectives @@ -764,7 +764,7 @@ void argument_particle() { new CommandAPICommand("showparticle") .withArguments(new ParticleArgument("particle")) .executesPlayer((player, args) -> { - ParticleData particleData = (ParticleData) args.get(0); + ParticleData particleData = (ParticleData) args.get("particle"); player.getWorld().spawnParticle(particleData.particle(), player.getLocation(), 1); }) .register(); @@ -774,7 +774,7 @@ void argument_particle() { new CommandAPICommand("showparticle") .withArguments(new ParticleArgument("particle")) .executesPlayer((player, args) -> { - ParticleData particleData = (ParticleData) args.get(0); + ParticleData particleData = (ParticleData) args.get("particle"); player.getWorld().spawnParticle(particleData.particle(), player.getLocation(), 1, particleData.data()); }) .register(); @@ -790,10 +790,10 @@ void argument_potion() { .withArguments(new TimeArgument("duration")) .withArguments(new IntegerArgument("strength")) .executes((sender, args) -> { - Player target = (Player) args.get(0); - PotionEffectType potion = (PotionEffectType) args.get(1); - int duration = (int) args.get(2); - int strength = (int) args.get(3); + Player target = (Player) args.get("target"); + PotionEffectType potion = (PotionEffectType) args.get("potion"); + int duration = (int) args.get("duration"); + int strength = (int) args.get("strength"); // Add the potion effect to the target player target.addPotionEffect(new PotionEffect(potion, duration, strength)); @@ -814,7 +814,7 @@ void argument_primitives() { .withArguments(new BooleanArgument("value")) .executes((sender, args) -> { // Update the config with the boolean argument - getConfig().set((String) args.get(0), (boolean) args.get(1)); + getConfig().set((String) args.get("config-key"), (boolean) args.get("value")); }) .register(); /* ANCHOR_END: argumentPrimitives1 */ @@ -827,8 +827,8 @@ void argument_range() { .withArguments(new ItemStackArgument("item")) // The item to search for .executesPlayer((player, args) -> { // Retrieve the range from the arguments - IntegerRange range = (IntegerRange) args.get(0); - ItemStack itemStack = (ItemStack) args.get(1); + IntegerRange range = (IntegerRange) args.get("range"); + ItemStack itemStack = (ItemStack) args.get("item"); // Store the locations of chests with certain items List locations = new ArrayList<>(); @@ -878,7 +878,7 @@ void argument_recipe() { new CommandAPICommand("giverecipe") .withArguments(new RecipeArgument("recipe")) .executesPlayer((player, args) -> { - ComplexRecipe recipe = (ComplexRecipe) args.get(0); + ComplexRecipe recipe = (ComplexRecipe) args.get("recipe"); player.getInventory().addItem(recipe.getResult()); }) .register(); @@ -889,8 +889,8 @@ void argument_recipe() { .withArguments(new PlayerArgument("player")) .withArguments(new RecipeArgument("recipe")) .executes((sender, args) -> { - Player target = (Player) args.get(0); - ComplexRecipe recipe = (ComplexRecipe) args.get(1); + Player target = (Player) args.get("player"); + ComplexRecipe recipe = (ComplexRecipe) args.get("recipe"); target.discoverRecipe(recipe.getKey()); }) @@ -904,8 +904,8 @@ void argument_rotation() { .withArguments(new RotationArgument("rotation")) .withArguments(new EntitySelectorArgument.OneEntity("target")) .executes((sender, args) -> { - Rotation rotation = (Rotation) args.get(0); - Entity target = (Entity) args.get(1); + Rotation rotation = (Rotation) args.get("rotation"); + Entity target = (Entity) args.get("target"); if (target instanceof ArmorStand armorStand) { armorStand.setHeadPose(new EulerAngle(Math.toRadians(rotation.getPitch()), Math.toRadians(rotation.getYaw() - 90), 0)); @@ -923,7 +923,7 @@ void argument_scoreboards() { .executes((sender, args) -> { // Get player names by casting to Collection @SuppressWarnings("unchecked") - Collection players = (Collection) args.get(0); + Collection players = (Collection) args.get("players"); for (String playerName : players) { Bukkit.getPlayer(playerName).getInventory().addItem(new ItemStack(Material.DIAMOND, 3)); @@ -937,7 +937,7 @@ void argument_scoreboards() { .withArguments(new ScoreboardSlotArgument("slot")) .executes((sender, args) -> { Scoreboard scoreboard = Bukkit.getScoreboardManager().getMainScoreboard(); - DisplaySlot slot = ((ScoreboardSlot) args.get(0)).getDisplaySlot(); + DisplaySlot slot = ((ScoreboardSlot) args.get("slot")).getDisplaySlot(); scoreboard.clearSlot(slot); }) .register(); @@ -949,7 +949,7 @@ void argument_sound() { new CommandAPICommand("sound") .withArguments(new SoundArgument("sound")) .executesPlayer((player, args) -> { - player.getWorld().playSound(player.getLocation(), (Sound) args.get(0), 100.0f, 1.0f); + player.getWorld().playSound(player.getLocation(), (Sound) args.get("sound"), 100.0f, 1.0f); }) .register(); /* ANCHOR_END: argumentSound1 */ @@ -958,7 +958,7 @@ void argument_sound() { new CommandAPICommand("sound") .withArguments(new SoundArgument.NamespacedKey("sound")) .executesPlayer((player, args) -> { - player.getWorld().playSound(player.getLocation(), ((NamespacedKey) args.get(0)).asString(), 100.0f, 1.0f); + player.getWorld().playSound(player.getLocation(), ((NamespacedKey) args.get("sound")).asString(), 100.0f, 1.0f); }) .register(); /* ANCHOR_END: argumentSound2 */ @@ -970,7 +970,7 @@ void argument_strings() { .withArguments(new PlayerArgument("target")) .withArguments(new GreedyStringArgument("message")) .executes((sender, args) -> { - ((Player) args.get(0)).sendMessage((String) args.get(1)); + ((Player) args.get("target")).sendMessage((String) args.get("message")); }) .register(); /* ANCHOR_END: argumentStrings1 */ @@ -981,7 +981,7 @@ void argument_team() { new CommandAPICommand("togglepvp") .withArguments(new TeamArgument("team")) .executes((sender, args) -> { - Team team = (Team) args.get(0); + Team team = (Team) args.get("team"); // Toggle pvp team.setAllowFriendlyFire(team.allowFriendlyFire()); @@ -998,8 +998,8 @@ void argument_time() { .withArguments(new GreedyStringArgument("message")) .executes((sender, args) -> { // Duration in ticks - int duration = (int) args.get(0); - String message = (String) args.get(1); + int duration = (int) args.get("duration"); + String message = (String) args.get("message"); for (Player player : Bukkit.getOnlinePlayers()) { // Display the message to all players, with the default fade in/out times (10 and 20). @@ -1015,7 +1015,7 @@ void argument_world() { new CommandAPICommand("unloadworld") .withArguments(new WorldArgument("world")) .executes((sender, args) -> { - World world = (World) args.get(0); + World world = (World) args.get("world"); // Unload the world (and save the world's chunks) Bukkit.getServer().unloadWorld(world, true); @@ -1062,9 +1062,9 @@ void arguments() { new CommandAPICommand("cmd") .withArguments(commandArguments) .executes((sender, args) -> { - String stringArg = (String) args.get(0); - PotionEffectType potionArg = (PotionEffectType) args.get(1); - Location locationArg = (Location) args.get(2); + String stringArg = (String) args.get("arg0"); + PotionEffectType potionArg = (PotionEffectType) args.get("arg1"); + Location locationArg = (Location) args.get("arg2"); }) .register(); /* ANCHOR_END: arguments4 */ @@ -1081,8 +1081,8 @@ void asyncSuggestions() { }))) .withArguments(new TextArgument("value")) .executes((sender, args) -> { - String key = (String) args.get(0); - String value = (String) args.get(1); + String key = (String) args.get("key"); + String value = (String) args.get("value"); plugin.getConfig().set(key, value); }) .register(); @@ -1181,7 +1181,7 @@ void brigadierSuggestions() { new CommandAPICommand("emoji") .withArguments(messageArgument) .executes((sender, args) -> { - Bukkit.broadcastMessage((String) args.get(0)); + Bukkit.broadcastMessage((String) args.get("message")); }) .register(); /* ANCHOR_END: brigadierSuggestions1 */ @@ -1234,7 +1234,7 @@ void brigadierSuggestions() { .withArguments(new GreedyStringArgument("command").replaceSuggestions(commandSuggestions)) .executes((sender, args) -> { // Run the command using Bukkit.dispatchCommand() - Bukkit.dispatchCommand(sender, (String) args.get(0)); + Bukkit.dispatchCommand(sender, (String) args.get("command")); }).register(); /* ANCHOR_END: brigadierSuggestions3 */ } @@ -1252,7 +1252,7 @@ void chatPreview() { .executesPlayer((player, args) -> { // The user still entered legacy text. We need to properly convert this // to a BaseComponent[] by converting to plain text then to BaseComponent[] - String plainText = BaseComponent.toPlainText((BaseComponent[]) args.get(0)); + String plainText = BaseComponent.toPlainText((BaseComponent[]) args.get("message")); Bukkit.spigot().broadcast(TextComponent.fromLegacyText(ChatColor.translateAlternateColorCodes('&', plainText))); }) .register(); @@ -1270,7 +1270,7 @@ void chatPreview() { .executesPlayer((player, args) -> { // The user still entered legacy text. We need to properly convert this // to a Component by converting to plain text then to Component - String plainText = PlainTextComponentSerializer.plainText().serialize((Component) args.get(0)); + String plainText = PlainTextComponentSerializer.plainText().serialize((Component) args.get("broadcast")); Bukkit.broadcast(LegacyComponentSerializer.legacyAmpersand().deserialize(plainText)); }) .register(); @@ -1286,7 +1286,7 @@ void chatPreview() { return TextComponent.fromLegacyText(ChatColor.translateAlternateColorCodes('&', plainText)); })) .executesPlayer((player, args) -> { - Bukkit.spigot().broadcast((BaseComponent[]) args.get(0)); + Bukkit.spigot().broadcast((BaseComponent[]) args.get("message")); }) .register(); /* ANCHOR_END: chatPreview3 */ @@ -1301,7 +1301,7 @@ void chatPreview() { return LegacyComponentSerializer.legacyAmpersand().deserialize(plainText); })) .executesPlayer((player, args) -> { - Bukkit.broadcast((Component) args.get(0)); + Bukkit.broadcast((Component) args.get("message")); }) .register(); /* ANCHOR_END: chatPreview4 */ @@ -1316,7 +1316,7 @@ void commandFailures() { new CommandAPICommand("getfruit") .withArguments(new StringArgument("item").replaceSuggestions(ArgumentSuggestions.strings(fruit))) .executes((sender, args) -> { - String inputFruit = (String) args.get(0); + String inputFruit = (String) args.get("item"); if (Arrays.stream(fruit).anyMatch(inputFruit::equals)) { // Do something with inputFruit @@ -1337,7 +1337,7 @@ void commandRegistration() { .withAliases("broadcast", "broadcastmessage") // Command aliases .withPermission(CommandPermission.OP) // Required permissions .executes((sender, args) -> { - String message = (String) args.get(0); + String message = (String) args.get("message"); Bukkit.getServer().broadcastMessage(message); }) .register(); @@ -1366,7 +1366,7 @@ class commandTrees extends JavaPlugin { }) .then(new PlayerArgument("target") .executes((sender, args) -> { - Player target = (Player) args.get(0); + Player target = (Player) args.get("target"); target.sendMessage("Hi"); })) .register(); @@ -1380,8 +1380,8 @@ class commandTrees extends JavaPlugin { .executesPlayer((player, args) -> { // /signedit set Sign sign = getTargetSign(player); - int lineNumber = (int) args.get(0); - String text = (String) args.get(1); + int lineNumber = (int) args.get("line_number"); + String text = (String) args.get("text"); sign.setLine(lineNumber - 1, text); sign.update(true); })))) @@ -1390,7 +1390,7 @@ class commandTrees extends JavaPlugin { .executesPlayer((player, args) -> { // /signedit clear Sign sign = getTargetSign(player); - int lineNumber = (int) args.get(0); + int lineNumber = (int) args.get("line_number"); sign.setLine(lineNumber - 1, ""); sign.update(true); }))) @@ -1399,7 +1399,7 @@ class commandTrees extends JavaPlugin { .executesPlayer((player, args) -> { // /signedit copy Sign sign = getTargetSign(player); - int lineNumber = (int) args.get(0); + int lineNumber = (int) args.get("line_number"); player.setMetadata("copied_sign_text", new FixedMetadataValue(this, sign.getLine(lineNumber - 1))); }))) .then(new LiteralArgument("paste") @@ -1407,7 +1407,7 @@ class commandTrees extends JavaPlugin { .executesPlayer((player, args) -> { // /signedit copy Sign sign = getTargetSign(player); - int lineNumber = (int) args.get(0); + int lineNumber = (int) args.get("line_number"); sign.setLine(lineNumber - 1, player.getMetadata("copied_sign_text").get(0).asString()); sign.update(true); }))) @@ -1493,7 +1493,7 @@ void functionWrapper() { new CommandAPICommand("runfunc") .withArguments(new FunctionArgument("function")) .executes((sender, args) -> { - FunctionWrapper[] functions = (FunctionWrapper[]) args.get(0); + FunctionWrapper[] functions = (FunctionWrapper[]) args.get("function"); for (FunctionWrapper function : functions) { function.run(); // The command executor in this case is 'sender' } @@ -1531,8 +1531,8 @@ void listed() { .withArguments(new GreedyStringArgument("message")) .executes((sender, args) -> { // args == [player, message] - Player player = (Player) args.get(0); - String message = (String) args.get(1); // Note that this is args.get(1) and NOT args.get(2) + Player player = (Player) args.get("player"); + String message = (String) args.get("message"); // Note that the IntegerArgument is not available in the CommandArguments player.sendMessage(message); }) .register(); @@ -1560,7 +1560,7 @@ void normalExecutors() { .withAliases("broadcast", "broadcastmessage") // Command aliases .withPermission(CommandPermission.OP) // Required permissions .executes((sender, args) -> { - String message = (String) args.get(0); + String message = (String) args.get("message"); Bukkit.getServer().broadcastMessage(message); }) .register(); @@ -1690,7 +1690,7 @@ void permissions() { new CommandAPICommand("kill") .withArguments(new PlayerArgument("target").withPermission(CommandPermission.OP)) .executesPlayer((player, args) -> { - ((Player) args.get(0)).setHealth(0); + ((Player) args.get("target")).setHealth(0); }) .register(); /* ANCHOR_END: permissions4 */ @@ -1709,9 +1709,9 @@ void permissions() { .withPermission("economy.other") // The important part of this example .withArguments(new PlayerArgument("target")) .executesPlayer((player, args) -> { - Player target = (Player) args.get(0); + Player target = (Player) args.get("target"); - // Send a message to the executor with the the target's balance + // Send a message to the executor with the target's balance player.sendMessage(target.getName() + "'s balance: " + Economy.getBalance(target)); }) .register(); @@ -1722,8 +1722,8 @@ void permissions() { .withArguments(new PlayerArgument("target")) .withArguments(new DoubleArgument("amount")) .executesPlayer((player, args) -> { - Player target = (Player) args.get(0); - double amount = (Double) args.get(1); + Player target = (Player) args.get("target"); + double amount = (Double) args.get("amount"); // Update the target player's balance Economy.updateBalance(target, amount); @@ -1735,7 +1735,7 @@ void permissions() { .withPermission("economy.admin.reset") // The important part of this example .withArguments(new PlayerArgument("target")) .executesPlayer((player, args) -> { - Player target = (Player) args.get(0); + Player target = (Player) args.get("target"); // Reset target balance here Economy.resetBalance(target); @@ -1847,7 +1847,7 @@ void requirements() { .executesPlayer((player, args) -> { // Get the name of the party to create - String partyName = (String) args.get(0); + String partyName = (String) args.get("partyName"); partyMembers.put(player.getUniqueId(), partyName); }) @@ -1894,7 +1894,7 @@ void requirements() { new CommandAPICommand("party") .withArguments(arguments) .executesPlayer((player, args) -> { - Player target = (Player) args.get(0); + Player target = (Player) args.get("player"); player.teleport(target); }) .register(); @@ -1906,7 +1906,7 @@ void requirements() { .executesPlayer((player, args) -> { // Get the name of the party to create - String partyName = (String) args.get(0); + String partyName = (String) args.get("partyName"); partyMembers.put(player.getUniqueId(), partyName); @@ -1950,7 +1950,7 @@ void resultingCommandExecutors() { new CommandAPICommand("givereward") .withArguments(new EntitySelectorArgument.OnePlayer("target")) .executes((sender, args) -> { - Player player = (Player) args.get(0); + Player player = (Player) args.get("target"); player.getInventory().addItem(new ItemStack(Material.DIAMOND, 64)); Bukkit.broadcastMessage(player.getName() + " won a rare 64 diamonds from a loot box!"); }) @@ -1993,7 +1993,7 @@ void safeArgumentSuggestions() { new CommandAPICommand("giverecipe") .withArguments(arguments) .executesPlayer((player, args) -> { - Recipe recipe = (Recipe) args.get(0); + Recipe recipe = (Recipe) args.get("recipe"); player.getInventory().addItem(recipe.getResult()); }) .register(); @@ -2024,7 +2024,7 @@ void safeArgumentSuggestions() { new CommandAPICommand("spawnmob") .withArguments(safeArguments) .executesPlayer((player, args) -> { - EntityType entityType = (EntityType) args.get(0); + EntityType entityType = (EntityType) args.get("mob"); player.getWorld().spawnEntity(player.getLocation(), entityType); }) .register(); @@ -2049,8 +2049,8 @@ void safeArgumentSuggestions() { new CommandAPICommand("removeeffect") .withArguments(safeArgs) .executesPlayer((player, args) -> { - Player target = (Player) args.get(0); - PotionEffectType potionEffect = (PotionEffectType) args.get(1); + Player target = (Player) args.get("target"); + PotionEffectType potionEffect = (PotionEffectType) args.get("potionEffect"); target.removePotionEffect(potionEffect); }) .register(); @@ -2108,7 +2108,7 @@ class stringArgumentSuggestions { new CommandAPICommand("warp") .withArguments(arguments) .executesPlayer((player, args) -> { - String warp = (String) args.get(0); + String warp = (String) args.get("world"); player.teleport(warps.get(warp)); // Look up the warp in a map, for example }) .register(); @@ -2141,7 +2141,7 @@ public static String[] getFriends(CommandSender sender) { new CommandAPICommand("friendtp") .withArguments(arguments) .executesPlayer((player, args) -> { - Player target = (Player) args.get(0); + Player target = (Player) args.get("friend"); player.teleport(target); }) .register(); @@ -2158,7 +2158,7 @@ public static String[] getFriends(CommandSender sender) { commandArgs.add(new PlayerArgument("target").replaceSuggestions(ArgumentSuggestions.strings(info -> { // Cast the first argument (radius, which is an IntegerArgument) to get its value - int radius = (int) info.previousArgs().get(0); + int radius = (int) info.previousArgs().get("radius"); // Get nearby entities within the provided radius Player player = (Player) info.sender(); @@ -2176,8 +2176,8 @@ public static String[] getFriends(CommandSender sender) { new CommandAPICommand("localmsg") .withArguments(commandArgs) .executesPlayer((player, args) -> { - Player target = (Player) args.get(1); - String message = (String) args.get(2); + Player target = (Player) args.get("target"); + String message = (String) args.get("message"); target.sendMessage(message); }) .register(); @@ -2272,10 +2272,10 @@ class tooltips { new CommandAPICommand("emote") .withArguments(arguments) .executesPlayer((player, args) -> { - String emote = (String) args.get(0); - Player target = (Player) args.get(1); + String emote = (String) args.get("emote"); + Player target = (Player) args.get("target"); - switch(emote) { + switch (emote) { case "wave": target.sendMessage(player.getName() + " waves at you!"); break; @@ -2341,7 +2341,7 @@ public Message getTooltip() { new CommandAPICommand("giveitem") .withArguments(new StringArgument("item").replaceSuggestions(ArgumentSuggestions.stringsWithTooltips(customItems))) // We use customItems[] as the input for our suggestions with tooltips .executesPlayer((player, args) -> { - String itemName = (String) args.get(0); + String itemName = (String) args.get("item"); // Give them the item for (CustomItem item : customItems) { @@ -2372,7 +2372,7 @@ public Message getTooltip() { new CommandAPICommand("warp") .withArguments(arguments) .executesPlayer((player, args) -> { - player.teleport((Location) args.get(0)); + player.teleport((Location) args.get("location")); }) .register(); /* ANCHOR_END: tooltips6 */ From 3f096b882b5811273546fe2e1f6cf9aeaf0ec8fd Mon Sep 17 00:00:00 2001 From: DerEchtePilz Date: Wed, 5 Jul 2023 11:02:50 +0200 Subject: [PATCH 23/28] Make Kotlin examples use the node name to access arguments --- .../commandapi/examples/java/Examples.java | 2 +- .../commandapi/examples/kotlin/Examples.kt | 226 +++++++++--------- .../commandapi-bukkit-core/pom.xml | 12 +- 3 files changed, 120 insertions(+), 120 deletions(-) diff --git a/commandapi-documentation-code/src/main/java/dev/jorel/commandapi/examples/java/Examples.java b/commandapi-documentation-code/src/main/java/dev/jorel/commandapi/examples/java/Examples.java index d84d06ed66..3418857c92 100644 --- a/commandapi-documentation-code/src/main/java/dev/jorel/commandapi/examples/java/Examples.java +++ b/commandapi-documentation-code/src/main/java/dev/jorel/commandapi/examples/java/Examples.java @@ -2050,7 +2050,7 @@ void safeArgumentSuggestions() { .withArguments(safeArgs) .executesPlayer((player, args) -> { Player target = (Player) args.get("target"); - PotionEffectType potionEffect = (PotionEffectType) args.get("potionEffect"); + PotionEffectType potionEffect = (PotionEffectType) args.get("potioneffect"); target.removePotionEffect(potionEffect); }) .register(); diff --git a/commandapi-documentation-code/src/main/kotlin/dev/jorel/commandapi/examples/kotlin/Examples.kt b/commandapi-documentation-code/src/main/kotlin/dev/jorel/commandapi/examples/kotlin/Examples.kt index 8e87a3bb85..a6fc04e18e 100644 --- a/commandapi-documentation-code/src/main/kotlin/dev/jorel/commandapi/examples/kotlin/Examples.kt +++ b/commandapi-documentation-code/src/main/kotlin/dev/jorel/commandapi/examples/kotlin/Examples.kt @@ -60,8 +60,8 @@ CommandAPICommand("award") .withArguments(PlayerArgument("player")) .withArguments(AdvancementArgument("advancement")) .executes(CommandExecutor { _, args -> - val target = args[0] as Player - val advancement = args[1] as Advancement + val target = args["player"] as Player + val advancement = args["advancement"] as Advancement // Award all criteria for the advancement val progress = target.getAdvancementProgress(advancement) @@ -101,7 +101,7 @@ CommandAPICommand("yaw") .withArguments(AngleArgument("amount")) .executesPlayer(PlayerCommandExecutor { player, args -> val newLocation = player.location - newLocation.yaw = args[0] as Float + newLocation.yaw = args["amount"] as Float player.teleport(newLocation) }) .register() @@ -113,7 +113,7 @@ fun argument_biome() { CommandAPICommand("setbiome") .withArguments(BiomeArgument("biome")) .executesPlayer(PlayerCommandExecutor { player, args -> - val biome = args[0] as Biome + val biome = args["biome"] as Biome val chunk = player.location.chunk player.world.setBiome(chunk.x, player.location.blockY, chunk.z, biome) @@ -137,9 +137,9 @@ CommandAPICommand("replace") .executesPlayer(PlayerCommandExecutor { player, args -> // Parse the arguments - val radius = args[0] as Int - val predicate = args[1] as Predicate - val blockData = args[2] as BlockData + val radius = args["radius"] as Int + val predicate = args["fromBlock"] as Predicate + val blockData = args["toBlock"] as BlockData // Find a (solid) sphere of blocks around the player with a given radius val center = player.location // for (i in 1 until 11) { } @@ -168,7 +168,7 @@ fun argument_blockState() { CommandAPICommand("set") .withArguments(BlockStateArgument("block")) .executesPlayer(PlayerCommandExecutor { player, args -> - val blockdata = args[0] as BlockData + val blockdata = args["block"] as BlockData val targetBlock = player.getTargetBlockExact(256) // Set the block, along with its data @@ -187,10 +187,10 @@ CommandAPICommand("showbook") .withArguments(StringArgument("author")) .withArguments(AdventureChatComponentArgument("contents")) .executes(CommandExecutor { _, args -> - val target = args[0] as Player - val title = args[1] as String - val author = args[2] as String - val content = args[3] as Component + val target = args["target"] as Player + val title = args["title"] as String + val author = args["author"] as String + val content = args["contents"] as Component // Create a book and show it to the user (Requires Paper) val mybook = Book.book(Component.text(title), Component.text(author), content) @@ -203,7 +203,7 @@ CommandAPICommand("showbook") CommandAPICommand("pbroadcast") .withArguments(AdventureChatArgument("message")) .executes(CommandExecutor { _, args -> - val message = args[0] as Component + val message = args["message"] as Component // Broadcast the message to everyone with broadcast permissions. Bukkit.getServer().broadcast(message, Server.BROADCAST_CHANNEL_USERS) @@ -216,9 +216,9 @@ CommandAPICommand("pbroadcast") fun argument_chats() { /* ANCHOR: argumentChats1 */ CommandAPICommand("namecolor") - .withArguments(ChatColorArgument("chatcolor")) + .withArguments(ChatColorArgument("chatColor")) .executesPlayer(PlayerCommandExecutor { player, args -> - val color = args[0] as ChatColor + val color = args["chatColor"] as ChatColor player.setDisplayName("$color${player.name}") }) .register() @@ -231,8 +231,8 @@ CommandAPICommand("makebook") .withArguments(PlayerArgument("player")) .withArguments(ChatComponentArgument("contents")) .executes(CommandExecutor { _, args -> - val player = args[0] as Player - val arr = args[1] as Array + val player = args["player"] as Player + val arr = args["contents"] as Array // Create book val item = ItemStack(Material.WRITTEN_BOOK) @@ -252,7 +252,7 @@ CommandAPICommand("makebook") CommandAPICommand("pbroadcast") .withArguments(ChatArgument("message")) .executes(CommandExecutor { _, args -> - val message = args[0] as Array + val message = args["message"] as Array // Broadcast the message to everyone on the server Bukkit.getServer().spigot().broadcast(*message) @@ -267,8 +267,8 @@ CommandAPICommand("sudo") .withArguments(PlayerArgument("target")) .withArguments(CommandArgument("command")) .executes(CommandExecutor { _, args -> - val target = args[0] as Player - val command = args[1] as CommandResult + val target = args["target"] as Player + val command = args["command"] as CommandResult command.execute(target) }) @@ -353,7 +353,7 @@ fun argumentCustom2() { CommandAPICommand("tpworld") .withArguments(worldArgument("world")) .executesPlayer(PlayerCommandExecutor { player, args -> - player.teleport((args[0] as World).spawnLocation) + player.teleport((args["world"] as World).spawnLocation) }) .register() /* ANCHOR_END: argumentCustom2 */ @@ -366,8 +366,8 @@ CommandAPICommand("enchantitem") .withArguments(EnchantmentArgument("enchantment")) .withArguments(IntegerArgument("level", 1, 5)) .executesPlayer(PlayerCommandExecutor { player, args -> - val enchantment = args[0] as Enchantment - val level = args[1] as Int + val enchantment = args["enchantment"] as Enchantment + val level = args["level"] as Int // Add the enchantment player.inventory.itemInMainHand.addEnchantment(enchantment, level) @@ -383,7 +383,7 @@ CommandAPICommand("remove") .withArguments(EntitySelectorArgument.ManyEntities("entities")) .executes(CommandExecutor { sender, args -> // Parse the argument as a collection of entities (as stated above in the documentation) - val entities = args[0] as Collection + val entities = args["entities"] as Collection sender.sendMessage("Removed ${entities.size} entities") for (e in entities) { @@ -398,8 +398,8 @@ CommandAPICommand("spawnmob") .withArguments(EntityTypeArgument("entity")) .withArguments(IntegerArgument("amount", 1, 100)) // Prevent spawning too many entities .executesPlayer(PlayerCommandExecutor { player, args -> - for (i in 0 until args[1] as Int) { - player.world.spawnEntity(player.location, args[0] as EntityType) + for (i in 0 until args["amount"] as Int) { + player.world.spawnEntity(player.location, args["entity"] as EntityType) } }) .register() @@ -411,7 +411,7 @@ fun argument_function() { CommandAPICommand("runfunction") .withArguments(FunctionArgument("function")) .executes(CommandExecutor { _, args -> - val functions = args[0] as Array + val functions = args["function"] as Array // Run all functions in our FunctionWrapper[] for (function in functions) { @@ -425,9 +425,9 @@ CommandAPICommand("runfunction") fun argument_itemStack() { /* ANCHOR: argumentItemStack1 */ CommandAPICommand("item") - .withArguments(ItemStackArgument("itemstack")) + .withArguments(ItemStackArgument("itemStack")) .executesPlayer(PlayerCommandExecutor { player, args -> - player.inventory.addItem(args[0] as ItemStack) + player.inventory.addItem(args["itemStack"] as ItemStack) }) .register() /* ANCHOR_END: argumentItemStack1 */ @@ -441,7 +441,7 @@ CommandAPICommand("rem") .executesPlayer(PlayerCommandExecutor { player, args -> // Get our predicate - val predicate = args[0] as Predicate + val predicate = args["items"] as Predicate for (item in player.inventory) { if (predicate.test(item)) { @@ -463,8 +463,8 @@ CommandAPICommand("multigive") .buildGreedy() ) .executesPlayer(PlayerCommandExecutor { player, args -> - val amount = args[0] as Int - val theList = args[1] as List + val amount = args["amount"] as Int + val theList = args["materials"] as List for (item in theList) { player.inventory.addItem(ItemStack(item, amount)) @@ -534,7 +534,7 @@ CommandAPICommand("break") // We want to target blocks in particular, so use BLOCK_POSITION .withArguments(LocationArgument("block", LocationType.BLOCK_POSITION)) .executesPlayer(PlayerCommandExecutor { _, args -> - (args[0] as Location).block.type = Material.AIR + (args["block"] as Location).block.type = Material.AIR }) .register() /* ANCHOR_END: argumentLocations1 */ @@ -543,11 +543,11 @@ CommandAPICommand("break") fun argument_lootTable() { /* ANCHOR: argumentLootTable1 */ CommandAPICommand("giveloottable") - .withArguments(LootTableArgument("loottable")) + .withArguments(LootTableArgument("lootTable")) .withArguments(LocationArgument("location", LocationType.BLOCK_POSITION)) .executes(CommandExecutor { _, args -> - val lootTable = args[0] as LootTable - val location = args[1] as Location + val lootTable = args["lootTable"] as LootTable + val location = args["location"] as Location val state = location.block.state @@ -605,9 +605,9 @@ CommandAPICommand("changelevel") .withArguments(MathOperationArgument("operation")) .withArguments(IntegerArgument("value")) .executes(CommandExecutor { _, args -> - val target = args[0] as Player - val op = args[1] as MathOperation - val value = args[2] as Int + val target = args["player"] as Player + val op = args["operation"] as MathOperation + val value = args["value"] as Int target.level = op.apply(target.level, value) }) @@ -621,7 +621,7 @@ CommandAPICommand("gamemode") .withArguments(MultiLiteralArgument("gamemodes", "adventure", "creative", "spectator", "survival")) .executesPlayer(PlayerCommandExecutor { player, args -> // The literal string that the player enters IS available in the args[] - when (args[0] as String) { + when (args["gamemodes"] as String) { "adventure" -> player.gameMode = GameMode.ADVENTURE "creative" -> player.gameMode = GameMode.CREATIVE "spectator" -> player.gameMode = GameMode.SPECTATOR @@ -647,7 +647,7 @@ fun argument_nbt2() { CommandAPICommand("award") .withArguments(NBTCompoundArgument("nbt")) .executes(CommandExecutor { _, args -> - val nbt = args[0] as NBTContainer + val nbt = args["nbt"] as NBTContainer // Do something with "nbt" here... }) @@ -662,10 +662,10 @@ fun argument_objectives() { CommandAPICommand("sidebar") .withArguments(ObjectiveArgument("objective")) .executes(CommandExecutor { _, args -> - val objective = args[0] as Objective + val objective = args["objective"] as Objective // Set display slot - objective?.displaySlot = DisplaySlot.SIDEBAR + objective.displaySlot = DisplaySlot.SIDEBAR }) .register() /* ANCHOR_END: argumentObjectives1 */ @@ -674,7 +674,7 @@ CommandAPICommand("sidebar") CommandAPICommand("unregisterall") .withArguments(ObjectiveCriteriaArgument("objective criteria")) .executes(CommandExecutor { _, args -> - val objectiveCriteria = args[0] as String + val objectiveCriteria = args["objective criteria"] as String val objectives = Bukkit.getScoreboardManager().mainScoreboard.getObjectivesByCriteria(objectiveCriteria) // Unregister the objectives @@ -691,7 +691,7 @@ fun argument_particle() { CommandAPICommand("showparticle") .withArguments(ParticleArgument("particle")) .executesPlayer(PlayerCommandExecutor { player, args -> - val particleData = args[0] as ParticleData + val particleData = args["particle"] as ParticleData player.world.spawnParticle(particleData.particle(), player.location, 1) }) .register() @@ -701,7 +701,7 @@ CommandAPICommand("showparticle") CommandAPICommand("showparticle") .withArguments(ParticleArgument("particle")) .executesPlayer(PlayerCommandExecutor { player, args -> - val particleData = args[0] as ParticleData + val particleData = args["particle"] as ParticleData player.world.spawnParticle(particleData.particle(), player.location, 1, particleData.data()) }) .register() @@ -716,10 +716,10 @@ CommandAPICommand("potion") .withArguments(TimeArgument("duration")) .withArguments(IntegerArgument("strength")) .executes(CommandExecutor { _, args -> - val target = args[0] as Player - val potion = args[1] as PotionEffectType - val duration = args[2] as Int - val strength = args[3] as Int + val target = args["target"] as Player + val potion = args["potion"] as PotionEffectType + val duration = args["duration"] as Int + val strength = args["strength"] as Int // Add the potion effect to the target player target.addPotionEffect(PotionEffect(potion, duration, strength)) @@ -739,7 +739,7 @@ CommandAPICommand("editconfig") .withArguments(BooleanArgument("value")) .executes(CommandExecutor { _, args -> // Update the config with the boolean argument - config.set(args[0] as String, args[1] as Boolean) + config.set(args["config-key"] as String, args["value"] as Boolean) }) .register() /* ANCHOR_END: argumentPrimitives1 */ @@ -752,8 +752,8 @@ CommandAPICommand("searchrange") .withArguments(ItemStackArgument("item")) // The item to search for .executesPlayer(PlayerCommandExecutor { player, args -> // Retrieve the range from the arguments - val range = args[0] as IntegerRange - val itemStack = args[1] as ItemStack + val range = args["range"] as IntegerRange + val itemStack = args["item"] as ItemStack // Store the locations of chests with certain items val locations = mutableListOf() @@ -800,7 +800,7 @@ fun argument_recipe() { CommandAPICommand("giverecipe") .withArguments(RecipeArgument("recipe")) .executesPlayer(PlayerCommandExecutor { player, args -> - val recipe = args[0] as ComplexRecipe + val recipe = args["recipe"] as ComplexRecipe player.inventory.addItem(recipe.result) }) .register() @@ -811,8 +811,8 @@ CommandAPICommand("unlockrecipe") .withArguments(PlayerArgument("player")) .withArguments(RecipeArgument("recipe")) .executes(CommandExecutor { _, args -> - val target = args[0] as Player - val recipe = args[1] as ComplexRecipe + val target = args["player"] as Player + val recipe = args["recipe"] as ComplexRecipe target.discoverRecipe(recipe.key) }) @@ -826,8 +826,8 @@ CommandAPICommand("rotate") .withArguments(RotationArgument("rotation")) .withArguments(EntitySelectorArgument.OneEntity("target")) .executes(CommandExecutor { _, args -> - val rotation = args[0] as Rotation - val target = args[1] as Entity + val rotation = args["rotation"] as Rotation + val target = args["target"] as Entity if (target is ArmorStand) { target.headPose = EulerAngle(Math.toRadians(rotation.pitch.toDouble()), Math.toRadians(rotation.yaw.toDouble() - 90), 0.0) @@ -844,7 +844,7 @@ CommandAPICommand("reward") .withArguments(ScoreHolderArgument.Multiple("players")) .executes(CommandExecutor { _, args -> // Get player names by casting to Collection - val players = args[0] as Collection + val players = args["players"] as Collection for (playerName in players) { Bukkit.getPlayer(playerName)?.inventory!!.addItem(ItemStack(Material.DIAMOND, 3)) @@ -858,7 +858,7 @@ CommandAPICommand("clearobjectives") .withArguments(ScoreboardSlotArgument("slot")) .executes(CommandExecutor { _, args -> val scoreboard = Bukkit.getScoreboardManager().mainScoreboard - val slot = (args[0] as ScoreboardSlot).displaySlot + val slot = (args["slot"] as ScoreboardSlot).displaySlot scoreboard.clearSlot(slot) }) .register() @@ -870,7 +870,7 @@ fun argument_sound() { CommandAPICommand("sound") .withArguments(SoundArgument("sound")) .executesPlayer(PlayerCommandExecutor { player, args -> - player.world.playSound(player.location, args[0] as Sound, 100.0f, 1.0f) + player.world.playSound(player.location, args["sound"] as Sound, 100.0f, 1.0f) }) .register() /* ANCHOR_END: argumentSound1 */ @@ -879,7 +879,7 @@ CommandAPICommand("sound") CommandAPICommand("sound") .withArguments(SoundArgument.NamespacedKey("sound")) .executesPlayer(PlayerCommandExecutor { player, args -> - player.world.playSound(player.location, (args[0] as NamespacedKey).asString(), 100.0f, 1.0f) + player.world.playSound(player.location, (args["sound"] as NamespacedKey).asString(), 100.0f, 1.0f) }) .register() /* ANCHOR_END: argumentSound2 */ @@ -891,7 +891,7 @@ CommandAPICommand("message") .withArguments(PlayerArgument("target")) .withArguments(GreedyStringArgument("message")) .executes(CommandExecutor { _, args -> - (args[0] as Player).sendMessage(args[1] as String) + (args["target"] as Player).sendMessage(args["message"] as String) }) .register() /* ANCHOR_END: argumentStrings1 */ @@ -902,7 +902,7 @@ fun argument_team() { CommandAPICommand("togglepvp") .withArguments(TeamArgument("team")) .executes(CommandExecutor { _, args -> - val team = args[0] as Team + val team = args["team"] as Team // Toggle pvp team.setAllowFriendlyFire(team.allowFriendlyFire()) @@ -918,8 +918,8 @@ CommandAPICommand("bigmsg") .withArguments(GreedyStringArgument("message")) .executes(CommandExecutor { _, args -> // Duration in ticks - val duration = args[0] as Int - val message = args[1] as String + val duration = args["duration"] as Int + val message = args["message"] as String for (player in Bukkit.getOnlinePlayers()) { // Display the message to all players, with the default fade in/out times (10 and 20). @@ -935,7 +935,7 @@ fun argument_world() { CommandAPICommand("unloadworld") .withArguments(WorldArgument("world")) .executes(CommandExecutor { sender, args -> - val world = args[0] as World + val world = args["world"] as World // Unload the world (and save the world's chunks) Bukkit.getServer().unloadWorld(world, true) @@ -983,9 +983,9 @@ val commandArguments = listOf( CommandAPICommand("cmd") .withArguments(commandArguments) .executes(CommandExecutor { _, args -> - val stringArg = args[0] as String - val potionArg = args[1] as PotionEffectType - val locationArg = args[2] as Location + val stringArg = args["arg0"] as String + val potionArg = args["arg1"] as PotionEffectType + val locationArg = args["arg2"] as Location }) .register() /* ANCHOR_END: arguments4 */ @@ -1000,8 +1000,8 @@ CommandAPICommand("setconfig") } )) .withArguments(TextArgument("value")) .executes(CommandExecutor { _, args -> - val key = args[0] as String - val value = args[1] as String + val key = args["key"] as String + val value = args["value"] as String plugin.config.set(key, value) }) .register() @@ -1098,7 +1098,7 @@ val messageArgument = GreedyStringArgument("message") CommandAPICommand("emoji") .withArguments(messageArgument) .executes(CommandExecutor { _, args -> - Bukkit.broadcastMessage(args[0] as String) + Bukkit.broadcastMessage(args["message"] as String) }) .register() /* ANCHOR_END: brigadierSuggestions1 */ @@ -1146,7 +1146,7 @@ CommandAPICommand("commandargument") .withArguments(GreedyStringArgument("command").replaceSuggestions(commandSuggestions)) .executes(CommandExecutor { sender, args -> // Run the command using Bukkit.dispatchCommand() - Bukkit.dispatchCommand(sender, args[0] as String) + Bukkit.dispatchCommand(sender, args["command"] as String) }) .register() /* ANCHOR_END: brigadierSuggestions3 */ @@ -1165,7 +1165,7 @@ CommandAPICommand("broadcast") .executesPlayer(PlayerCommandExecutor { _, args -> // The user still entered legacy text. We need to properly convert this // to a BaseComponent[] by converting to plain text then to BaseComponent[] - val plainText: String = BaseComponent.toPlainText(*args[0] as Array) + val plainText: String = BaseComponent.toPlainText(*args["message"] as Array) val baseComponents: Array = TextComponent.fromLegacyText(ChatColor.translateAlternateColorCodes('&', plainText)) Bukkit.spigot().broadcast(*baseComponents) }) @@ -1184,7 +1184,7 @@ CommandAPICommand("broadcast") .executesPlayer(PlayerCommandExecutor { _, args -> // The user still entered legacy text. We need to properly convert this // to a Component by converting to plain text then to Component - val plainText: String = PlainTextComponentSerializer.plainText().serialize(args[0] as Component) + val plainText: String = PlainTextComponentSerializer.plainText().serialize(args["message"] as Component) Bukkit.broadcast(LegacyComponentSerializer.legacyAmpersand().deserialize(plainText)) }) .register() @@ -1200,7 +1200,7 @@ CommandAPICommand("broadcast") TextComponent.fromLegacyText(ChatColor.translateAlternateColorCodes('&', plainText)) } ) .executesPlayer(PlayerCommandExecutor { _, args -> - Bukkit.spigot().broadcast(*args[0] as Array) + Bukkit.spigot().broadcast(*args["message"] as Array) }) .register() /* ANCHOR_END: chatPreview3 */ @@ -1215,7 +1215,7 @@ CommandAPICommand("broadcast") LegacyComponentSerializer.legacyAmpersand().deserialize(plainText) } ) .executesPlayer(PlayerCommandExecutor { _, args -> - Bukkit.broadcast(args[0] as Component) + Bukkit.broadcast(args["message"] as Component) }) .register() /* ANCHOR_END: chatPreview4 */ @@ -1230,7 +1230,7 @@ val fruit = listOf("banana", "apple", "orange") CommandAPICommand("getfruit") .withArguments(StringArgument("item").replaceSuggestions(ArgumentSuggestions.strings(fruit))) .executes(CommandExecutor { _, args -> - val inputFruit = args[0] as String + val inputFruit = args["item"] as String if(fruit.any { it == inputFruit }) { // Do something with inputFruit @@ -1251,7 +1251,7 @@ CommandAPICommand("broadcastmsg") .withAliases("broadcast", "broadcastmessage") // Command aliases .withPermission(CommandPermission.OP) // Required permissions .executes(CommandExecutor { sender, args -> - val message = args[0] as String + val message = args["message"] as String Bukkit.getServer().broadcastMessage(message) }) .register() @@ -1280,7 +1280,7 @@ CommandTree("sayhi") }) .then(PlayerArgument("target") .executes(CommandExecutor { _, args -> - val target = args[0] as Player + val target = args["target"] as Player target.sendMessage("Hi") })) .register() @@ -1294,8 +1294,8 @@ CommandTree("signedit") .executesPlayer(PlayerCommandExecutor { player, args -> // /signedit set val sign: Sign = getTargetSign(player) - val line_number = args[0] as Int - val text = args[1] as String + val line_number = args["line_number"] as Int + val text = args["text"] as String sign.setLine(line_number - 1, text) sign.update(true) })))) @@ -1304,7 +1304,7 @@ CommandTree("signedit") .executesPlayer(PlayerCommandExecutor { player, args -> // /signedit clear val sign: Sign = getTargetSign(player) - val line_number = args[0] as Int + val line_number = args["line_number"] as Int sign.setLine(line_number - 1, "") sign.update(true) }))) @@ -1313,7 +1313,7 @@ CommandTree("signedit") .executesPlayer(PlayerCommandExecutor { player, args -> // /signedit copy val sign: Sign = getTargetSign(player) - val line_number = args[0] as Int + val line_number = args["line_number"] as Int player.setMetadata("copied_sign_text", FixedMetadataValue(this, sign.getLine(line_number - 1))) }))) .then(LiteralArgument("paste") @@ -1321,7 +1321,7 @@ CommandTree("signedit") .executesPlayer(PlayerCommandExecutor { player, args -> // /signedit copy val sign: Sign = getTargetSign(player) - val line_number = args[0] as Int + val line_number = args["line_number"] as Int sign.setLine(line_number - 1, player.getMetadata("copied_sign_text")[0].asString()) sign.update(true) }))) @@ -1406,7 +1406,7 @@ fun functionWrapper() { CommandAPICommand("runfunc") .withArguments(FunctionArgument("function")) .executes(CommandExecutor { _, args -> - val functions = args[0] as Array + val functions = args["function"] as Array for (function in functions) { function.run() // The command executor in this case is 'sender' } @@ -1444,8 +1444,8 @@ CommandAPICommand("mycommand") .withArguments(GreedyStringArgument("message")) .executes(CommandExecutor { _, args -> // args == [player, message] - val player = args[0] as Player - val message = args[1] as String // Note that this is args[1] and NOT args[2] + val player = args["player"] as Player + val message = args["message"] as String // Note that the IntegerArgument is not available in the CommandArguments player.sendMessage(message) }) .register() @@ -1471,7 +1471,7 @@ CommandAPICommand("broadcastmsg") .withAliases("broadcast", "broadcastmessage") // Command aliases .withPermission(CommandPermission.OP) // Required permissions .executes(CommandExecutor { _, args -> - val message = args[0] as String + val message = args["message"] as String Bukkit.getServer().broadcastMessage(message) }) .register() @@ -1594,7 +1594,7 @@ CommandAPICommand("kill") CommandAPICommand("kill") .withArguments(PlayerArgument("target").withPermission(CommandPermission.OP)) .executesPlayer(PlayerCommandExecutor { _, args -> - (args[0] as Player).health = 0.0 + (args["target"] as Player).health = 0.0 }) .register() /* ANCHOR_END: permissions4 */ @@ -1613,7 +1613,7 @@ CommandAPICommand("economy") .withPermission("economy.other") // The important part of this example .withArguments(PlayerArgument("target")) .executesPlayer(PlayerCommandExecutor { player, args -> - val target = args[0] as Player + val target = args["target"] as Player // send the executor the targets balance here. }) .register() @@ -1624,8 +1624,8 @@ CommandAPICommand("economy") .withArguments(PlayerArgument("target")) .withArguments(DoubleArgument("amount")) .executesPlayer(PlayerCommandExecutor { player, args -> - val target = args[0] as Player - val amount = args[1] as Double + val target = args["target"] as Player + val amount = args["amount"] as Double // update the targets balance here }) .register() @@ -1635,7 +1635,7 @@ CommandAPICommand("economy") .withPermission("economy.admin.reset") // The important part of this example .withArguments(PlayerArgument("target")) .executesPlayer(PlayerCommandExecutor { player, args -> - val target = args[0] as Player + val target = args["target"] as Player // reset the targets balance here }) .register() @@ -1745,7 +1745,7 @@ CommandAPICommand("party") .executesPlayer(PlayerCommandExecutor { player, args -> // Get the name of the party to create - val partyName = args[0] as String + val partyName = args["partyName"] as String partyMembers[player.uniqueId] = partyName }) @@ -1792,7 +1792,7 @@ arguments.add(PlayerArgument("player") CommandAPICommand("party") .withArguments(arguments) .executesPlayer(PlayerCommandExecutor { player, args -> - val target = args[0] as Player + val target = args["player"] as Player player.teleport(target) }) .register() @@ -1804,7 +1804,7 @@ CommandAPICommand("party") .executesPlayer(PlayerCommandExecutor { player, args -> // Get the name of the party to create - val partyName = args[0] as String + val partyName = args["partyName"] as String partyMembers[player.uniqueId] = partyName @@ -1848,7 +1848,7 @@ CommandAPICommand("randomnumber") CommandAPICommand("givereward") .withArguments(EntitySelectorArgument.OnePlayer("target")) .executes(CommandExecutor { _, args -> - val player = args[0] as Player + val player = args["target"] as Player player.inventory.addItem(ItemStack(Material.DIAMOND, 64)) Bukkit.broadcastMessage("${player.name} won a rare 64 diamonds from a loot box!") }) @@ -1892,7 +1892,7 @@ val arguments = listOf>( CommandAPICommand("giverecipe") .withArguments(arguments) .executesPlayer(PlayerCommandExecutor { player, args -> - val recipe = args[0] as Recipe + val recipe = args["recipe"] as Recipe player.inventory.addItem(recipe.result) }) .register() @@ -1924,7 +1924,7 @@ val safeArguments = listOf>( CommandAPICommand("spawnmob") .withArguments(safeArguments) .executesPlayer(PlayerCommandExecutor { player, args -> - val entityType = args[0] as EntityType + val entityType = args["mob"] as EntityType player.world.spawnEntity(player.location, entityType) }) .register() @@ -1935,7 +1935,7 @@ val safeArgs = mutableListOf>() safeArgs.add(EntitySelectorArgument.OnePlayer("target")) safeArgs.add(PotionEffectArgument("potioneffect").replaceSafeSuggestions(SafeSuggestions.suggest { info -> - val target = info.previousArgs()[0] as Player + val target = info.previousArgs()["target"] as Player // Convert PotionEffect[] into PotionEffectType[] target.activePotionEffects.map{ it.type }.toTypedArray() @@ -1947,8 +1947,8 @@ safeArgs.add(PotionEffectArgument("potioneffect").replaceSafeSuggestions(SafeSug CommandAPICommand("removeeffect") .withArguments(safeArgs) .executesPlayer(PlayerCommandExecutor { _, args -> - val target = args[0] as Player - val potionEffect = args[1] as PotionEffectType + val target = args["target"] as Player + val potionEffect = args["potioneffect"] as PotionEffectType target.removePotionEffect(potionEffect) }) .register() @@ -2004,7 +2004,7 @@ val arguments = listOf>( CommandAPICommand("warp") .withArguments(arguments) .executesPlayer(PlayerCommandExecutor { player, args -> - val warp = args[0] as String + val warp = args["world"] as String player.teleport(warps[warp]!!) // Look up the warp in a map, for example }) .register() @@ -2043,7 +2043,7 @@ val arguments = listOf>( CommandAPICommand("friendtp") .withArguments(arguments) .executesPlayer(PlayerCommandExecutor { player, args -> - val target = args[0] as Player + val target = args["friend"] as Player player.teleport(target) }) .register() @@ -2060,7 +2060,7 @@ commandArgs.add(IntegerArgument("radius")) commandArgs.add(PlayerArgument("target").replaceSuggestions(ArgumentSuggestions.strings { info: SuggestionInfo -> // Cast the first argument (radius, which is an IntegerArgument) to get its value - val radius = (info.previousArgs()[0] as Int).toDouble() + val radius = (info.previousArgs()["radius"] as Int).toDouble() // Get nearby entities within the provided radius val player = info.sender() as Player @@ -2078,8 +2078,8 @@ commandArgs.add(GreedyStringArgument("message")) CommandAPICommand("localmsg") .withArguments(*commandArgs.toTypedArray()) .executesPlayer(PlayerCommandExecutor { _, args -> - val target = args[1] as Player - val message = args[2] as String + val target = args["target"] as Player + val message = args["message"] as String target.sendMessage(message) }) .register() @@ -2175,8 +2175,8 @@ arguments.add(PlayerArgument("target")) CommandAPICommand("emote") .withArguments(*arguments.toTypedArray()) .executesPlayer(PlayerCommandExecutor { player, args -> - val emote = args[0] as String - val target = args[1] as Player + val emote = args["emote"] as String + val target = args["target"] as Player when (emote) { "wave" -> target.sendMessage("${player.name} waves at you!") @@ -2215,7 +2215,7 @@ val customItems = arrayOf( CommandAPICommand("giveitem") .withArguments(StringArgument("item").replaceSuggestions(ArgumentSuggestions.stringsWithTooltips(*customItems))) // We use customItems[] as the input for our suggestions with tooltips .executesPlayer(PlayerCommandExecutor { player, args -> - val itemName = args[0] as String + val itemName = args["item"] as String // Give them the item for (item in customItems) { @@ -2247,7 +2247,7 @@ val arguments = listOf>( CommandAPICommand("warp") .withArguments(arguments) .executesPlayer(PlayerCommandExecutor { player, args -> - player.teleport(args[0] as Location) + player.teleport(args["location"] as Location) }) .register() /* ANCHOR_END: tooltips6 */ diff --git a/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-core/pom.xml b/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-core/pom.xml index 581736e1be..0e446d85c0 100644 --- a/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-core/pom.xml +++ b/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-core/pom.xml @@ -45,18 +45,18 @@ 4.2.0 test - - dev.folia - folia-api - 1.19.4-R0.1-SNAPSHOT - provided - io.papermc.paper paper-api ${paper.version} provided + + dev.folia + folia-api + 1.19.4-R0.1-SNAPSHOT + provided + dev.jorel From cae429832491a412cb54f4f9ea67e15ae5a1fd9d Mon Sep 17 00:00:00 2001 From: DerEchtePilz Date: Wed, 5 Jul 2023 11:14:56 +0200 Subject: [PATCH 24/28] Make Kotlin DSL examples use the node name to access arguments --- .../examples/kotlin/ExamplesKotlinDSL.kt | 164 +++++++++--------- 1 file changed, 82 insertions(+), 82 deletions(-) diff --git a/commandapi-documentation-code/src/main/kotlin/dev/jorel/commandapi/examples/kotlin/ExamplesKotlinDSL.kt b/commandapi-documentation-code/src/main/kotlin/dev/jorel/commandapi/examples/kotlin/ExamplesKotlinDSL.kt index f350a8b441..aa9db80d96 100644 --- a/commandapi-documentation-code/src/main/kotlin/dev/jorel/commandapi/examples/kotlin/ExamplesKotlinDSL.kt +++ b/commandapi-documentation-code/src/main/kotlin/dev/jorel/commandapi/examples/kotlin/ExamplesKotlinDSL.kt @@ -42,8 +42,8 @@ commandAPICommand("award") { playerArgument("player") advancementArgument("advancement") anyExecutor { _, args -> - val target = args[0] as Player - val advancement = args[1] as Advancement + val target = args["player"] as Player + val advancement = args["advancement"] as Advancement // Award all criteria for the advancement val progress = target.getAdvancementProgress(advancement) @@ -81,7 +81,7 @@ commandAPICommand("yaw") { angleArgument("amount") playerExecutor { player, args -> val newLocation = player.location - newLocation.yaw = args[0] as Float + newLocation.yaw = args["amount"] as Float player.teleport(newLocation) } } @@ -93,7 +93,7 @@ fun argument_biome() { commandAPICommand("setbiome") { biomeArgument("biome") playerExecutor { player, args -> - val biome = args[0] as Biome + val biome = args["biome"] as Biome val chunk = player.location.chunk player.world.setBiome(chunk.x, player.location.blockY, chunk.z, biome) @@ -114,9 +114,9 @@ commandAPICommand("replace") { arguments(*arguments) playerExecutor { player, args -> // Parse the arguments - val radius = args[0] as Int - val predicate = args[1] as Predicate - val blockData = args[2] as BlockData + val radius = args["radius"] as Int + val predicate = args["fromBlock"] as Predicate + val blockData = args["toBlock"] as BlockData // Find a (solid) sphere of blocks around the player with a given radius val center = player.location // for (i in 1 until 11) { } @@ -145,7 +145,7 @@ fun argument_blockState() { commandAPICommand("set") { blockStateArgument("block") playerExecutor { player, args -> - val blockdata = args[0] as BlockData + val blockdata = args["block"] as BlockData val targetBlock = player.getTargetBlockExact(256) // Set the block, along with its data @@ -164,10 +164,10 @@ commandAPICommand("showbook") { stringArgument("author") adventureChatComponentArgument("contents") anyExecutor { _, args -> - val target = args[0] as Player - val title = args[1] as String - val author = args[2] as String - val content = args[3] as Component + val target = args["target"] as Player + val title = args["title"] as String + val author = args["author"] as String + val content = args["contents"] as Component // Create a book and show it to the user (Requires Paper) val mybook = Book.book(Component.text(title), Component.text(author), content) @@ -180,7 +180,7 @@ commandAPICommand("showbook") { commandAPICommand("pbroadcast") { adventureChatArgument("message") anyExecutor { _, args -> - val message = args[0] as Component + val message = args["message"] as Component // Broadcast the message to everyone with broadcast permissions. Bukkit.getServer().broadcast(message, Server.BROADCAST_CHANNEL_USERS) @@ -195,7 +195,7 @@ fun argument_chats() { commandAPICommand("namecolor") { chatColorArgument("chatcolor") playerExecutor { player, args -> - val color = args[0] as ChatColor + val color = args["chatcolor"] as ChatColor player.setDisplayName("$color${player.name}") } } @@ -208,8 +208,8 @@ commandAPICommand("makebook") { playerArgument("player") chatComponentArgument("contents") anyExecutor { _, args -> - val player = args[0] as Player - val array = args[1] as Array + val player = args["player"] as Player + val array = args["contents"] as Array // Create book val item = ItemStack(Material.WRITTEN_BOOK) @@ -229,7 +229,7 @@ commandAPICommand("makebook") { commandAPICommand("pbroadcast") { chatArgument("message") anyExecutor { _, args -> - val message = args[0] as Array + val message = args["message"] as Array // Broadcast the message to everyone on the server Bukkit.getServer().spigot().broadcast(*message) @@ -244,8 +244,8 @@ commandAPICommand("sudo") { playerArgument("target") commandArgument("command") anyExecutor { _, args -> - val target = args[0] as Player - val command = args[1] as CommandResult + val target = args["target"] as Player + val command = args["command"] as CommandResult command.execute(target) } @@ -258,7 +258,7 @@ fun argument_custom() { commandAPICommand("tpworld") { worldArgument("world") // This method is actually also built into the Kotlin DSL playerExecutor { player, args -> - player.teleport((args[0] as World).spawnLocation) + player.teleport((args["world"] as World).spawnLocation) } } /* ANCHOR_END: argumentCustom2 */ @@ -270,8 +270,8 @@ commandAPICommand("enchantitem") { enchantmentArgument("enchantment") integerArgument("level", 1, 5) playerExecutor { player, args -> - val enchantment = args[0] as Enchantment - val level = args[1] as Int + val enchantment = args["enchantment"] as Enchantment + val level = args["level"] as Int // Add the enchantment player.inventory.itemInMainHand.addEnchantment(enchantment, level) @@ -287,7 +287,7 @@ commandAPICommand("remove") { entitySelectorArgumentManyEntities("entities") anyExecutor { sender, args -> // Parse the argument as a collection of entities (as stated above in the documentation) - val entities = args[0] as Collection + val entities = args["entities"] as Collection sender.sendMessage("Removed ${entities.size} entities") for (e in entities) { @@ -302,8 +302,8 @@ commandAPICommand("spawnmob") { entityTypeArgument("entity") integerArgument("amount", 1, 100) // Prevent spawning too many entities playerExecutor { player, args -> - for (i in 0 until args[1] as Int) { - player.world.spawnEntity(player.location, args[0] as EntityType) + for (i in 0 until args["amount"] as Int) { + player.world.spawnEntity(player.location, args["entity"] as EntityType) } } } @@ -315,7 +315,7 @@ fun argument_function() { commandAPICommand("runfunction") { functionArgument("function") anyExecutor { _, args -> - val functions = args[0] as Array + val functions = args["function"] as Array // Run all functions in our FunctionWrapper[] for (function in functions) { @@ -331,7 +331,7 @@ fun argument_itemStack() { commandAPICommand("item") { itemStackArgument("itemstack") playerExecutor { player, args -> - player.inventory.addItem(args[0] as ItemStack) + player.inventory.addItem(args["itemstack"] as ItemStack) } } /* ANCHOR_END: argumentItemStack1 */ @@ -344,7 +344,7 @@ commandAPICommand("rem") { itemStackPredicateArgument("items") playerExecutor { player, args -> // Get our predicate - val predicate = args[0] as Predicate + val predicate = args["items"] as Predicate for (item in player.inventory) { if (predicate.test(item)) { @@ -366,8 +366,8 @@ commandAPICommand("multigive") { .buildGreedy() ) playerExecutor { player, args -> - val amount = args[0] as Int - val theList = args[1] as List + val amount = args["amount"] as Int + val theList = args["materials"] as List for (item in theList) { player.inventory.addItem(ItemStack(item, amount)) @@ -438,7 +438,7 @@ commandAPICommand("break") { // We want to target blocks in particular, so use BLOCK_POSITION locationArgument("block", LocationType.BLOCK_POSITION) playerExecutor { _, args -> - (args[0] as Location).block.type = Material.AIR + (args["block"] as Location).block.type = Material.AIR } } /* ANCHOR_END: argumentLocations1 */ @@ -450,8 +450,8 @@ commandAPICommand("giveloottable") { lootTableArgument("loottable") locationArgument("location", LocationType.BLOCK_POSITION) anyExecutor { _, args -> - val lootTable = args[0] as LootTable - val location = args[1] as Location + val lootTable = args["loottable"] as LootTable + val location = args["location"] as Location val state = location.block.state @@ -509,9 +509,9 @@ commandAPICommand("changelevel") { mathOperationArgument("operation") integerArgument("value") anyExecutor { _, args -> - val target = args[0] as Player - val op = args[1] as MathOperation - val value = args[2] as Int + val target = args["player"] as Player + val op = args["operation"] as MathOperation + val value = args["value"] as Int target.level = op.apply(target.level, value) } @@ -525,7 +525,7 @@ commandAPICommand("gamemode") { multiLiteralArgument(nodeName = "gamemodes", "adventure", "creative", "spectator", "survival") // Adding this for now, needed because ambiguous methods exist playerExecutor { player, args -> // The literal string that the player enters IS available in the args[] - when (args[0] as String) { + when (args["gamemodes"] as String) { "adventure" -> player.gameMode = GameMode.ADVENTURE "creative" -> player.gameMode = GameMode.CREATIVE "spectator" -> player.gameMode = GameMode.SPECTATOR @@ -541,7 +541,7 @@ fun argument_nbt() { commandAPICommand("award") { nbtCompoundArgument("nbt") anyExecutor { _, args -> - val nbt = args[0] as NBTContainer + val nbt = args["nbt"] as NBTContainer // Do something with "nbt" here... } @@ -554,10 +554,10 @@ fun argument_objectives() { commandAPICommand("sidebar") { objectiveArgument("objective") anyExecutor { _, args -> - val objective = args[0] as Objective + val objective = args["objective"] as Objective // Set display slot - objective?.displaySlot = DisplaySlot.SIDEBAR + objective.displaySlot = DisplaySlot.SIDEBAR } } /* ANCHOR_END: argumentObjectives1 */ @@ -566,7 +566,7 @@ commandAPICommand("sidebar") { commandAPICommand("unregisterall") { objectiveCriteriaArgument("objective criteria") anyExecutor { _, args -> - val objectiveCriteria = args[0] as String + val objectiveCriteria = args["objective criteria"] as String val objectives = Bukkit.getScoreboardManager().mainScoreboard.getObjectivesByCriteria(objectiveCriteria) // Unregister the objectives @@ -583,7 +583,7 @@ fun argument_particle() { commandAPICommand("showparticle") { particleArgument("particle") playerExecutor { player, args -> - val particleData = args[0] as ParticleData + val particleData = args["particle"] as ParticleData player.world.spawnParticle(particleData.particle(), player.location, 1) } } @@ -593,7 +593,7 @@ commandAPICommand("showparticle") { commandAPICommand("showparticle") { particleArgument("particle") playerExecutor { player, args -> - val particleData = args[0] as ParticleData + val particleData = args["particle"] as ParticleData player.world.spawnParticle(particleData.particle(), player.location, 1, particleData.data()) } } @@ -608,10 +608,10 @@ commandAPICommand("potion") { timeArgument("duration") integerArgument("strength") anyExecutor { _, args -> - val target = args[0] as Player - val potion = args[1] as PotionEffectType - val duration = args[2] as Int - val strength = args[3] as Int + val target = args["target"] as Player + val potion = args["potion"] as PotionEffectType + val duration = args["duration"] as Int + val strength = args["strength"] as Int // Add the potion effect to the target player target.addPotionEffect(PotionEffect(potion, duration, strength)) @@ -631,7 +631,7 @@ commandAPICommand("editconfig") { booleanArgument("value") anyExecutor { _, args -> // Update the config with the boolean argument - getConfig().set(args[0] as String, args[1] as Boolean) + getConfig().set(args["config-key"] as String, args["value"] as Boolean) } } /* ANCHOR_END: argumentPrimitives1 */ @@ -644,8 +644,8 @@ commandAPICommand("searchrange") { itemStackArgument("item") // The item to search for playerExecutor { player, args -> // Retrieve the range from the arguments - val range = args[0] as IntegerRange - val itemStack = args[1] as ItemStack + val range = args["range"] as IntegerRange + val itemStack = args["item"] as ItemStack // Store the locations of chests with certain items val locations = mutableListOf() @@ -692,7 +692,7 @@ fun argument_recipe() { commandAPICommand("giverecipe") { recipeArgument("recipe") playerExecutor { player, args -> - val recipe = args[0] as ComplexRecipe + val recipe = args["recipe"] as ComplexRecipe player.inventory.addItem(recipe.result) } } @@ -703,8 +703,8 @@ commandAPICommand("unlockrecipe") { playerArgument("player") recipeArgument("recipe") anyExecutor { _, args -> - val target = args[0] as Player - val recipe = args[1] as ComplexRecipe + val target = args["player"] as Player + val recipe = args["recipe"] as ComplexRecipe target.discoverRecipe(recipe.key) } @@ -718,8 +718,8 @@ commandAPICommand("rotate") { rotationArgument("rotation") entitySelectorArgumentOneEntity("target") anyExecutor { _, args -> - val rotation = args[0] as Rotation - val target = args[1] as Entity + val rotation = args["rotation"] as Rotation + val target = args["target"] as Entity if (target is ArmorStand) { target.headPose = EulerAngle(Math.toRadians(rotation.pitch.toDouble()), Math.toRadians(rotation.yaw.toDouble() - 90), 0.0) @@ -736,7 +736,7 @@ commandAPICommand("reward") { scoreHolderArgumentMultiple("player") anyExecutor { _, args -> // Get player names by casting to Collection - val players = args[0] as Collection + val players = args["player"] as Collection for (playerName in players) { Bukkit.getPlayer(playerName)?.inventory!!.addItem(ItemStack(Material.DIAMOND, 3)) @@ -750,7 +750,7 @@ commandAPICommand("clearobjectives") { scoreboardSlotArgument("slot") anyExecutor { _, args -> val scoreboard = Bukkit.getScoreboardManager().mainScoreboard - val slot = (args[0] as ScoreboardSlot).displaySlot + val slot = (args["slot"] as ScoreboardSlot).displaySlot scoreboard.clearSlot(slot) } } @@ -762,7 +762,7 @@ fun argument_sound() { commandAPICommand("sound") { soundArgument("sound") playerExecutor { player, args -> - player.world.playSound(player.location, args[0] as Sound, 100.0f, 1.0f) + player.world.playSound(player.location, args["sound"] as Sound, 100.0f, 1.0f) } } /* ANCHOR_END: argumentSound1 */ @@ -771,7 +771,7 @@ commandAPICommand("sound") { commandAPICommand("sound") { soundArgument("sound", true) playerExecutor { player, args -> - player.world.playSound(player.location, (args[0] as NamespacedKey).asString(), 100.0f, 1.0f) + player.world.playSound(player.location, (args["sound"] as NamespacedKey).asString(), 100.0f, 1.0f) } } /* ANCHOR_END: argumentSound2 */ @@ -783,7 +783,7 @@ commandAPICommand("message") { playerArgument("target") greedyStringArgument("message") anyExecutor { _, args -> - (args[0] as Player).sendMessage(args[1] as String) + (args["target"] as Player).sendMessage(args["message"] as String) } } /* ANCHOR_END: argumentStrings1 */ @@ -794,7 +794,7 @@ fun argument_team() { commandAPICommand("togglepvp") { teamArgument("team") anyExecutor { _, args -> - val team = args[0] as Team + val team = args["team"] as Team // Toggle pvp team.setAllowFriendlyFire(team.allowFriendlyFire()) @@ -810,8 +810,8 @@ commandAPICommand("bigmsg") { greedyStringArgument("message") anyExecutor { _, args -> // Duration in ticks - val duration = args[0] as Int - val message = args[1] as String + val duration = args["duration"] as Int + val message = args["message"] as String for (player in Bukkit.getOnlinePlayers()) { // Display the message to all players, with the default fade in/out times (10 and 20). @@ -827,7 +827,7 @@ fun argument_world() { commandAPICommand("unloadworld") { worldArgument("world") anyExecutor { sender, args -> - val world = args[0] as World + val world = args["world"] as World // Unload the world (and save the world's chunks) Bukkit.getServer().unloadWorld(world, true) @@ -878,9 +878,9 @@ val args = listOf( commandAPICommand("cmd") { arguments(*args.toTypedArray()) anyExecutor { _, args -> - val stringArg = args[0] as String - val potionArg = args[1] as PotionEffectType - val locationArg = args[2] as Location + val stringArg = args["arg0"] as String + val potionArg = args["arg1"] as PotionEffectType + val locationArg = args["arg2"] as Location } } /* ANCHOR_END: arguments4 */ @@ -914,8 +914,8 @@ commandTree("sendmessageto") { playerArgument("player") { // Defines a new PlayerArgument("player") greedyStringArgument("msg") { // Defines a new GreedyStringArgument("msg") anyExecutor { _, args -> // Command can be executed by anyone and anything (such as entities, the console, etc.) - val player: Player = args[0] as Player - val message: String = args[1] as String + val player: Player = args["player"] as Player + val message: String = args["msg"] as String player.sendMessage(message) } } @@ -928,8 +928,8 @@ commandAPICommand("sendmessageto") { playerArgument("player") // Defines a new PlayerArgument("player") greedyStringArgument("msg") // Defines a new GreedyStringArgument("msg") anyExecutor { _, args -> // Command can be executed by anyone and anything (such as entities, the console, etc.) - val player: Player = args[0] as Player - val message: String = args[1] as String + val player: Player = args["player"] as Player + val message: String = args["msg"] as String player.sendMessage(message) } } @@ -940,8 +940,8 @@ commandTree("sendMessageTo") { playerArgument("player") { greedyStringArgument("msg") { playerExecutor { _, args -> - val player: Player = args[0] as Player - val message: String = args[1] as String + val player: Player = args["player"] as Player + val message: String = args["msg"] as String player.sendMessage(message) } } @@ -949,7 +949,7 @@ commandTree("sendMessageTo") { requirement(of("broadcast"), { sender: CommandSender -> sender.isOp }) { // Define a new LiteralArgument("broadcast") that requires the CommandSender to be a player who is a server operator greedyStringArgument("msg") { playerExecutor { _, args -> - val message: String = args[0] as String + val message: String = args["msg"] as String Bukkit.broadcastMessage(message) } } @@ -962,8 +962,8 @@ commandAPICommand("sendMessageTo") { playerArgument("player") greedyStringArgument("msg") playerExecutor { _, args -> - val player: Player = args[0] as Player - val message: String = args[1] as String + val player: Player = args["player"] as Player + val message: String = args["msg"] as String player.sendMessage(message) } } @@ -972,7 +972,7 @@ commandAPICommand("sendMessageTo") { requirement(of("broadcast"), { sender: CommandSender -> sender.isOp }) // Define a new LiteralArgument("broadcast") that requires the CommandSender to be a player who is a server operator greedyStringArgument("msg") playerExecutor { _, args -> - val message: String = args[0] as String + val message: String = args["msg"] as String Bukkit.broadcastMessage(message) } } @@ -1003,7 +1003,7 @@ commandTree("optionalArgument") { // This command will let you execute: // "/optionalArgument give minecraft:stick" // "/optionalArgument give minecraft:stick 5" - val itemStack: ItemStack = args[0] as ItemStack + val itemStack: ItemStack = args["item"] as ItemStack val amount: Int = args.getOptional("amount").orElse(1) as Int itemStack.amount = amount player.inventory.addItem(itemStack) @@ -1023,7 +1023,7 @@ commandAPICommand("optionalArgument") { // This command will let you execute: // "/optionalArgument give minecraft:stick" // "/optionalArgument give minecraft:stick 5" - val itemStack: ItemStack = args[0] as ItemStack + val itemStack: ItemStack = args["item"] as ItemStack val amount: Int = args.getOptional("amount").orElse(1) as Int itemStack.amount = amount player.inventory.addItem(itemStack) @@ -1035,7 +1035,7 @@ commandAPICommand("optionalArgument") { commandTree("replaceSuggestions") { argument(StringArgument("strings").replaceSuggestions(ArgumentSuggestions.strings("one", "two", "three"))) { // Implement an argument that has suggestions playerExecutor { player, args -> - player.sendMessage("You chose option ${args[0] as String}!") + player.sendMessage("You chose option ${args["strings"] as String}!") } } } @@ -1045,7 +1045,7 @@ commandTree("replaceSuggestions") { commandAPICommand("replaceSuggestions") { argument(StringArgument("strings").replaceSuggestions(ArgumentSuggestions.strings("one", "two", "three"))) // Implement an argument that has suggestions playerExecutor { player, args -> - player.sendMessage("You chose option ${args[0] as String}!") + player.sendMessage("You chose option ${args["strings"] as String}!") } } /* ANCHOR_END: kotlindsl10 */ @@ -1161,7 +1161,7 @@ commandAPICommand("randomnumber") { commandAPICommand("givereward") { entitySelectorArgumentOnePlayer("target") anyExecutor { _, args -> - val player = args[0] as Player + val player = args["target"] as Player player.inventory.addItem(ItemStack(Material.DIAMOND, 64)) Bukkit.broadcastMessage("${player.name} won a rare 64 diamonds from a loot box!") } From ec80dc5a9385003d60d61d0746b2ab1f8a613276 Mon Sep 17 00:00:00 2001 From: DerEchtePilz Date: Wed, 5 Jul 2023 11:21:31 +0200 Subject: [PATCH 25/28] Fix Bukkit Core dependencies --- .../commandapi-bukkit/commandapi-bukkit-core/pom.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-core/pom.xml b/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-core/pom.xml index 0e446d85c0..581736e1be 100644 --- a/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-core/pom.xml +++ b/commandapi-platforms/commandapi-bukkit/commandapi-bukkit-core/pom.xml @@ -45,18 +45,18 @@ 4.2.0 test - - io.papermc.paper - paper-api - ${paper.version} - provided - dev.folia folia-api 1.19.4-R0.1-SNAPSHOT provided + + io.papermc.paper + paper-api + ${paper.version} + provided + dev.jorel From d05c9eb233b3feb67acaf3a893653ad55a6c457e Mon Sep 17 00:00:00 2001 From: DerEchtePilz Date: Wed, 5 Jul 2023 13:21:19 +0200 Subject: [PATCH 26/28] Add documentation examples --- .../commandapi/examples/java/Examples.java | 43 +++++++++++++ .../commandapi/examples/kotlin/Examples.kt | 44 +++++++++++++ docssrc/src/commandarguments.md | 63 +++++++++++++++++++ pom.xml | 2 +- 4 files changed, 151 insertions(+), 1 deletion(-) diff --git a/commandapi-documentation-code/src/main/java/dev/jorel/commandapi/examples/java/Examples.java b/commandapi-documentation-code/src/main/java/dev/jorel/commandapi/examples/java/Examples.java index 3418857c92..ba15367fc0 100644 --- a/commandapi-documentation-code/src/main/java/dev/jorel/commandapi/examples/java/Examples.java +++ b/commandapi-documentation-code/src/main/java/dev/jorel/commandapi/examples/java/Examples.java @@ -1307,6 +1307,49 @@ void chatPreview() { /* ANCHOR_END: chatPreview4 */ } +void commandArguments() { +/* ANCHOR: commandArguments1 */ +new CommandAPICommand("mycommand") + .withArguments(new StringArgument("name")) + .withArguments(new IntegerArgument("amount")) + .withOptionalArguments(new PlayerArgument("player")) + .withOptionalArguments(new PlayerArgument("target")) + .withOptionalArguments(new GreedyStringArgument("message")) + .executesPlayer((player, args) -> { + String name = (String) args.get(0); // Access arguments by index + int amount = (int) args.get("amount"); // Access arguments by node name + Player p = (Player) args.getOrDefault("player", player); // Access arguments using the getOrDefault(String, Object) method + Player target = (Player) args.getOrDefault("target", () -> player); // Access arguments using the getOrDefault(String, Supplier) method + String message = (String) args.getOptional("message").orElse("Hello!"); // Access arguments using the getOptional(String) method + + // Do whatever with these values + }) + .register(); +/* ANCHOR_END: commandArguments1 */ + +/* ANCHOR: commandArguments2 */ +new CommandAPICommand("mycommand") + .withArguments(new EntitySelectorArgument.ManyEntities("entities")) + .executesPlayer((player, args) -> { + String entitySelector = args.getRaw("entities"); // Access the raw argument with getRaw(String) + + // Do whatever with the entity selector + }) + .register(); +/* ANCHOR_END: commandArguments2 */ + +/* ANCHOR: commandArguments3 */ +new CommandAPICommand("mycommand") + .withArguments(new PlayerArgument("player")) + .executesPlayer((player, args) -> { + Player p = args.getUnchecked("player"); + + // Do whatever with the player + }) + .register(); +/* ANCHOR_END: commandArguments3 */ +} + void commandFailures() { /* ANCHOR: commandFailures1 */ // Array of fruit diff --git a/commandapi-documentation-code/src/main/kotlin/dev/jorel/commandapi/examples/kotlin/Examples.kt b/commandapi-documentation-code/src/main/kotlin/dev/jorel/commandapi/examples/kotlin/Examples.kt index a6fc04e18e..670f0ff2ad 100644 --- a/commandapi-documentation-code/src/main/kotlin/dev/jorel/commandapi/examples/kotlin/Examples.kt +++ b/commandapi-documentation-code/src/main/kotlin/dev/jorel/commandapi/examples/kotlin/Examples.kt @@ -49,6 +49,7 @@ import org.bukkit.util.EulerAngle import java.util.* import java.util.concurrent.CompletableFuture import java.util.function.Predicate +import java.util.function.Supplier import kotlin.collections.LinkedHashMap import kotlin.random.Random @@ -1221,6 +1222,49 @@ CommandAPICommand("broadcast") /* ANCHOR_END: chatPreview4 */ } +fun commandArguments() { +/* ANCHOR: commandArguments1 */ +CommandAPICommand("mycommand") + .withArguments(StringArgument("name")) + .withArguments(IntegerArgument("amount")) + .withOptionalArguments(PlayerArgument("player")) + .withOptionalArguments(PlayerArgument("target")) + .withOptionalArguments(GreedyStringArgument("message")) + .executesPlayer(PlayerCommandExecutor { player, args -> + val name = args[0] as String // Access arguments by index + val amount = args["amount"] as Int // Access arguments by node name + val p = args.getOrDefault("player", player) as Player // Access arguments using the getOrDefault(String, Object) method + val target = args.getOrDefault("target") { player } as Player // Access arguments using the getOrDefault(String, Supplier) method + val message = args.getOptional("message").orElse("Hello!") as String // Access arguments using the getOptional(String) method + + // Do whatever with these values + }) + .register(); +/* ANCHOR_END: commandArguments1 */ + +/* ANCHOR: commandArguments2 */ +CommandAPICommand("mycommand") + .withArguments(EntitySelectorArgument.ManyEntities("entities")) + .executesPlayer(PlayerCommandExecutor { player, args -> + val entitySelector = args.getRaw("entities")!! // Access the raw argument with getRaw(String) + + // Do whatever with the entity selector + }) + .register(); +/* ANCHOR_END: commandArguments2 */ + +/* ANCHOR: commandArguments3 */ +CommandAPICommand("mycommand") + .withArguments(PlayerArgument("player")) + .executesPlayer(PlayerCommandExecutor { player, args -> + val p: Player = args.getUnchecked("player")!! + + // Do whatever with the player + }) + .register(); +/* ANCHOR_END: commandArguments3 */ +} + fun commandFailures() { /* ANCHOR: commandFailures1 */ // List of fruit diff --git a/docssrc/src/commandarguments.md b/docssrc/src/commandarguments.md index 370bfaacc3..a705124846 100644 --- a/docssrc/src/commandarguments.md +++ b/docssrc/src/commandarguments.md @@ -92,6 +92,29 @@ Optional getOptional(int index); ### Example - Access arguments by node name and index +To demonstrate the different ways of accessing arguments, we want to register a command `/mycommand` like this: + +```mccmd +/mycommand +/mycommand +/mycommand +/mycommand +``` + +This is how these commands are implemented: + +
+ +```java,Java +{{#include ../../commandapi-documentation-code/src/main/java/dev/jorel/commandapi/examples/java/Examples.java:commandArguments1}} +``` + +```kotlin,Kotlin +{{#include ../../commandapi-documentation-code/src/main/kotlin/dev/jorel/commandapi/examples/kotlin/Examples.kt:commandArguments1}} +``` + +
+ ----- @@ -140,6 +163,26 @@ Optional getRawOptional(int index); ### Example - Access raw arguments by node name and index +To demonstrate how to access raw arguments, we are going to implement the `/mycommand` again, this time with the following syntax: + +```mccmd +/mycommand +``` + +We want to find out which entity selector is being used when the command is executed. + +
+ +```java,Java +{{#include ../../commandapi-documentation-code/src/main/java/dev/jorel/commandapi/examples/java/Examples.java:commandArguments2}} +``` + +```kotlin,Kotlin +{{#include ../../commandapi-documentation-code/src/main/kotlin/dev/jorel/commandapi/examples/kotlin/Examples.kt:commandArguments2}} +``` + +
+ ----- @@ -190,4 +233,24 @@ Optional getOptionalUnchecked(int index); ### Example - Access unsafe arguments by node name and index +Finally, we want to implement the `/mycommand` again. This time we use this syntax: + +```mccmd +/mycommand +``` + +Here, we don't actually want to cast the argument, so we use unsafe arguments to remove that cast: + +
+ +```java,Java +{{#include ../../commandapi-documentation-code/src/main/java/dev/jorel/commandapi/examples/java/Examples.java:commandArguments3}} +``` + +```kotlin,Kotlin +{{#include ../../commandapi-documentation-code/src/main/kotlin/dev/jorel/commandapi/examples/kotlin/Examples.kt:commandArguments3}} +``` + +
+ diff --git a/pom.xml b/pom.xml index e0a75e3855..f8dc261d2e 100644 --- a/pom.xml +++ b/pom.xml @@ -88,7 +88,7 @@ - 1.19.2-R0.1-SNAPSHOT + 1.19.4-R0.1-SNAPSHOT 1.0.1 From 06416073649a2c2217fc88492152f0333e18e92c Mon Sep 17 00:00:00 2001 From: DerEchtePilz Date: Wed, 5 Jul 2023 17:44:29 +0200 Subject: [PATCH 27/28] Update global changelog --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 0fb22ac219..7e5ba82a71 100644 --- a/README.md +++ b/README.md @@ -375,6 +375,7 @@ This is the current roadmap for the CommandAPI (as of 11th May 2023):
  • Fixed the CommandAPI disabling datapacks on Paper 1.20.1 #40+ because it thought it was running on a Folia server
  • +
  • https://github.com/JorelAli/CommandAPI/pull/459 Added the ability to access raw arguments in the command executor
From 897739d07a028fb5f0a7742c588d855933dc1d27 Mon Sep 17 00:00:00 2001 From: DerEchtePilz Date: Wed, 12 Jul 2023 16:45:33 +0200 Subject: [PATCH 28/28] Add JavaDocs to record parameters --- .../executors/CommandArguments.java | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/commandapi-core/src/main/java/dev/jorel/commandapi/executors/CommandArguments.java b/commandapi-core/src/main/java/dev/jorel/commandapi/executors/CommandArguments.java index b448b1c30a..7fcdcb6519 100644 --- a/commandapi-core/src/main/java/dev/jorel/commandapi/executors/CommandArguments.java +++ b/commandapi-core/src/main/java/dev/jorel/commandapi/executors/CommandArguments.java @@ -18,7 +18,33 @@ * @param fullInput The command string a player has entered (including the /) */ @SuppressWarnings("unchecked") -public record CommandArguments(Object[] args, Map argsMap, String[] rawArgs, Map rawArgsMap, String fullInput) { +public record CommandArguments( + + /** + * @param The arguments for this command + */ + Object[] args, + + /** + * @param The arguments for this command mapped to their node names. This is an ordered map + */ + Map argsMap, + + /** + * @param The raw arguments for this command + */ + String[] rawArgs, + + /** + * @param The raw arguments for this command mapped to their node names. This is an ordered map + */ + Map rawArgsMap, + + /** + * @param The command string a player has entered (including the /) + */ + String fullInput +) { // Access the inner structure directly