Skip to content

Command build rewrite #602

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 43 commits into
base: dev/dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
a70b3c7
Initial rewrite of command building system
willkroboth Sep 2, 2023
c7a1e85
Disable broken test: `OptionalArgumentTests.kt#executionTestWithComma…
willkroboth Sep 2, 2023
c7fce4b
Initial rewrite of optional Arguments
willkroboth Oct 14, 2023
d0a7083
Remove { } from KotlinDSL inline if-else's
willkroboth Oct 14, 2023
21eb5af
Remove optional arguments from CommandTrees
willkroboth Oct 14, 2023
ace1b89
Give default value for `block` in DSL's `CommandAPICommand.addArgumen…
willkroboth Oct 14, 2023
eac4f1c
Address some SonarCloud code smells
willkroboth Oct 14, 2023
fa5905e
Remove unused `AbstractArgument#unpackCombinedArguments`
willkroboth Oct 14, 2023
f34f65b
Update tests added to `dev/command-build-rewrite` from `dev/dev`
willkroboth Oct 15, 2023
a3aae7b
Expand command-building test coverage
willkroboth Oct 15, 2023
f193c4a
Extract logic for generating the SuggestionsProvider for an Argument …
willkroboth Oct 15, 2023
ace4942
Fix MultiLiteralArguments - give nodes multiple parents instead of us…
willkroboth Dec 24, 2023
e77649c
Initial implementation of `FlagsArgument` (and other changes)
willkroboth Dec 27, 2023
964f80b
Fix `CommandNamespaceTests`
willkroboth Feb 28, 2024
765a8e4
Update `dev/command-build-rewrite` after rebasing #509 and #526
willkroboth Mar 19, 2024
ca103e8
Re-implement command conflict detection
willkroboth Apr 3, 2024
6133057
Add tests for `CommandConflictException`
willkroboth Apr 4, 2024
37ebf73
Extract common node stacking logic
willkroboth Apr 4, 2024
b373534
Add tests for `FlagsArgument`
willkroboth Apr 8, 2024
48bae7f
Rewrite `RegisteredCommand`
willkroboth Apr 29, 2024
ba8e9d1
Fix & update `Previewable` arguments
willkroboth Apr 30, 2024
42ea240
Help topic rewrite
willkroboth May 13, 2024
3302ed3
Address a few SonarCloud code smells
willkroboth May 13, 2024
2b940bd
Executor Rewrite
willkroboth Jun 3, 2024
fc5c1ec
Update CommandExecutionTests after rebasing `dev/command-build-rewrite`
willkroboth Jun 3, 2024
d894090
Fully split converted arguments
willkroboth Jun 6, 2024
18b7211
Split CommandRegistrationTests into separate classes for each exception
willkroboth Jun 9, 2024
1ae584e
Add ArgumentListabilityTests
willkroboth Jun 17, 2024
4cb1de0
Implement `DynamicMultiLiteralArgument`
willkroboth Jun 20, 2024
54b692b
Add FlagsArgument to Velocity (and other changes)
willkroboth Jul 4, 2024
efd8c5b
Clean up files (unused imports and spaces when other lines have tabs)
willkroboth Aug 26, 2024
54f0bf8
Address some SonarCloud issues
willkroboth Aug 27, 2024
8fce5c4
Add serializers for custom CommandNodes
willkroboth Aug 30, 2024
0b2ab36
Make `CommandAPI#unregister` remove commands from `CommandAPIHandler.…
willkroboth Aug 31, 2024
249d408
Add tests for `DynamicMultiLiteralArgument`
willkroboth Sep 1, 2024
e24939b
Remove test commands
willkroboth Sep 1, 2024
00768ab
Fix proxy senders
willkroboth Sep 1, 2024
29d3e37
Fix Brigadier node serialization on Bukkit 1.16.5 and 1.17
willkroboth Sep 2, 2024
abd0cd8
Resolve https://github.com/JorelAli/CommandAPI/issues/310
willkroboth Sep 2, 2024
3eff7d9
Update NMS_1_21_R2 with `dev/command-build-rewrite` changes
willkroboth Oct 26, 2024
695881a
Update NMS_1_21_R3 with dev/command-build-rewrite changes
willkroboth Feb 2, 2025
04ea561
Update test-toolkit after rebasing `dev/command-build-rewrite`
willkroboth Feb 2, 2025
8ce32d7
Improve DynamicMultiLiteralArgument on Spigot
willkroboth Feb 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package dev.jorel.commandapi;

import com.mojang.brigadier.tree.CommandNode;
import dev.jorel.commandapi.arguments.AbstractArgument;
import dev.jorel.commandapi.arguments.AbstractArgument.NodeInformation;
import dev.jorel.commandapi.arguments.AbstractArgument.TerminalNodeModifier;
import dev.jorel.commandapi.exceptions.MissingCommandExecutorException;

import java.util.ArrayList;
import java.util.Arrays;
Expand All @@ -22,19 +26,19 @@ public abstract class AbstractArgumentTree<Impl
/// @endcond
, CommandSender> extends Executable<Impl, CommandSender> {

final List<AbstractArgumentTree<?, Argument, CommandSender>> arguments = new ArrayList<>();
final Argument argument;
private final Argument argument;
private List<AbstractArgumentTree<?, Argument, CommandSender>> arguments = new ArrayList<>();

/**
* Instantiates an {@link AbstractArgumentTree}. This can only be called if the class
* that extends this is an {@link AbstractArgument}
*/
@SuppressWarnings("unchecked")
protected AbstractArgumentTree() {
if (this instanceof AbstractArgument<?, ?, Argument, CommandSender>) {
if (this instanceof AbstractArgument<?, ?, ?, ?>) {
this.argument = (Argument) this;
} else {
throw new IllegalArgumentException("Implicit inherited constructor must be from Argument");
throw new IllegalArgumentException("Implicit inherited constructor must be from AbstractArgument");
}
}

Expand All @@ -50,6 +54,10 @@ protected AbstractArgumentTree(final Argument argument) {
this.executor = argument.executor;
}

/////////////////////
// Builder methods //
/////////////////////

/**
* Create a child branch on this node
*
Expand Down Expand Up @@ -96,19 +104,84 @@ public final Impl thenNested(final AbstractArgumentTree<?, Argument, CommandSend
return thenNested(Arrays.asList(trees));
}

List<Execution<CommandSender, Argument>> getExecutions() {
List<Execution<CommandSender, Argument>> executions = new ArrayList<>();
// If this is executable, add its execution
if (this.executor.hasAnyExecutors()) {
executions.add(new Execution<>(List.of(this.argument), this.executor));
/////////////////////////
// Getters and setters //
/////////////////////////

/**
* @return The child branches added to this tree by {@link #then(AbstractArgumentTree)}.
*/
public List<AbstractArgumentTree<?, Argument, CommandSender>> getArguments() {
return arguments;
}

/**
* Sets the child branches that this node has
*
* @param arguments A new list of branches for this node
*/
public void setArguments(List<AbstractArgumentTree<?, Argument, CommandSender>> arguments) {
this.arguments = arguments;
}

//////////////////
// Registration //
//////////////////
/**
* Builds the Brigadier {@link CommandNode} structure for this argument tree.
*
* @param previousNodeInformation The {@link NodeInformation} of the argument this argument is being added to.
* @param previousArguments A List of CommandAPI arguments that came before this argument tree.
* @param previousArgumentNames A List of Strings containing the node names that came before this argument.
* @param <Source> The Brigadier Source object for running commands.
*/
public <Source> void buildBrigadierNode(
NodeInformation<CommandSender, Source> previousNodeInformation,
List<Argument> previousArguments, List<String> previousArgumentNames
) {
CommandAPIHandler<Argument, CommandSender, Source> handler = CommandAPIHandler.getInstance();

// Check preconditions
if (!executor.hasAnyExecutors() && arguments.isEmpty()) {
// If we don't have any executors then no branches is bad because this path can't be run at all
throw new MissingCommandExecutorException(previousArguments, argument);
}
// Add all executions from all arguments
for (AbstractArgumentTree<?, Argument, CommandSender> tree : arguments) {
for (Execution<CommandSender, Argument> execution : tree.getExecutions()) {
// Prepend this argument to the arguments of the executions
executions.add(execution.prependedBy(this.argument));

// Create executor, if it exists
TerminalNodeModifier<Argument, CommandSender, Source> terminalNodeModifier = (builder, args) -> {
if (executor.hasAnyExecutors()) {
builder.executes(handler.generateBrigadierCommand(args, executor));
}

return builder.build();
};

// Create node for this argument
previousNodeInformation = argument.addArgumentNodes(
previousNodeInformation,
previousArguments, previousArgumentNames,
terminalNodeModifier
);

// Collect children into our own list
List<RegisteredCommand.Node<CommandSender>> childrenNodeInformation = new ArrayList<>();

// Add our branches as children to the node
for (AbstractArgumentTree<?, Argument, CommandSender> child : arguments) {
// Collect children into our own list
NodeInformation<CommandSender, Source> newPreviousNodeInformation = new NodeInformation<>(
previousNodeInformation.lastCommandNodes(),
childrenNodeInformation::addAll
);

// We need a new list so each branch acts independently
List<Argument> newPreviousArguments = new ArrayList<>(previousArguments);
List<String> newPreviousArgumentNames = new ArrayList<>(previousArgumentNames);

child.buildBrigadierNode(newPreviousNodeInformation, newPreviousArguments, newPreviousArgumentNames);
}
return executions;

// Create registered nodes now that all children are generated
previousNodeInformation.childrenConsumer().createNodeWithChildren(childrenNodeInformation);
}
}
Loading
Loading