Skip to content
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

Add a FlagsArgument #483

Open
willkroboth opened this issue Aug 18, 2023 · 0 comments
Open

Add a FlagsArgument #483

willkroboth opened this issue Aug 18, 2023 · 0 comments
Assignees
Labels
enhancement New feature or request

Comments

@willkroboth
Copy link
Collaborator

Description

This suggestion comes from a common question on the CommandAPI Discord. Most recently, a comment from Lear reminded me of this, but there have also been ideas from TheZequex, Skepter, NextdoorPsycho and probably lots more.

In Vanilla Minecraft, the execute command is very powerful. It has many subcommands that a user can type out in any order, with each subcommand having its own arguments that define how the command's context should be changed. For example, you can type commands like this:

execute as @e if block ~ ~ ~ minecraft:air ...
execute if block ~ ~ ~ minecraft:air as @e ...

Here, the as and if block subcommands can go in any order. as has an EntitySelectorArgument before it loops back, and if block has a LocationArgument followed by a BlockPredicateArgument. You can keep going, adding new subcommands until the run subcommand, which allows you to exit the loop and run any other command.

The Brigadier system handles this by allowing redirects to any other node in the CommandDispatch tree. In /execute's case, each subcommand redirects back to the base execute node to continue the loop.

The CommandAPI can help a little with writing commands like this, as shown by this example in the documentation. However, you still need to import Brigadier and deal with its classes directly. Additionally, the Brigadier source when using Bukkit is the NMS class CommandListenerWrapper, which means you have to deal with raw types when building the commands. I think it's possible to give a bit more help here.

Expected code

I'll show what I'm thinking with Lear's usecase. Lear wanted to implement filtering for a custom object with syntax like /findCustomObject sort=random limit=1 distance=..3, similar to EntitySelector filtering. Using the FlagsArgument as I'm calling it, something similar could be possible like so:

new CommandAPICommand("findCustomObject")
        .withArguments(
                new FlagsArgument("filters")
                        .loopingBranch(
                                new LiteralArgument("filter", "sort").setListed(true),
                                new MultiLiteralArgument("sortType", "furthest", "nearest", "random")
                        )
                        .loopingBranch(
                                new LiteralArgument("filter", "limit").setListed(true),
                                new IntegerArgument("limitAmount", 0)
                        )
                        .loopingBranch(
                                new LiteralArgument("filter", "distance").setListed(true),
                                new IntegerRangeArgument("distanceRange")
                        )
        )
        .executes((sender, args) -> {
            List<Object> candidateObjects = getCandiates();

            for (CommandArguments branch : args.<List<CommandArguments>>getUnchecked("filters")) {
                String filterType = branch.getUnchecked("filter");
                switch (filterType) {
                    case "sort" -> {
                        String sortType = branch.getUnchecked("sortType");
                        switch (sortType) {
                            case "furthest" -> candidateObjects.sort((a, b) -> -Integer.compare(a.getDistance(), b.getDistance()));
                            case "closest" -> candidateObjects.sort((a, b) -> Integer.compare(a.getDistance(), b.getDistance()));
                            case "random" -> Collections.shuffle(candidateObjects);
                        }
                    }
                    case "limit" -> {
                        int limit = branch.getUnchecked("limitAmount");
                        candidateObjects = candidateObjects.subList(0, limit);
                    }
                    case "distance" -> {
                        IntegerRange range = branch.getUnchecked("distanceRange");
                        candidateObjects.stream().filter(o -> range.isInRange(o.getDistance()));
                    }
                }
            }
            
            processCandidates(candidateObjects);
        })
        .register();

With this code, commands like these should be executable:

/findcustomobject filters sort random
/findcustomobject filters limit 1
/findcustomobject filters distance 4..10
/findcustomobject filters distance ..10 sort random limit 1

Something like the execute command might look like this:

.withArguments(
    new FlagsArgument("execute")
            .loopingBranch(
                    new LiteralArgument("subcommand", "as").setListed(true),
                    new EntitySelectorArgument.ManyEntities("targets")
            )
            .loopingBranch(
                    new FlagsArgument("if")
                            .terminalBranch(
                                    new LiteralArgument("ifType", "block").setListed(true),
                                    new BlockPredicateArgument("predicate")
                            )
                            .terminalBranch(
                                    new LiteralArgument("ifType", "entity").setListed(true),
                                    new EntitySelectorArgument.ManyEntities("predicate")
                            )
            )
            .terminalBranch(
                    new LiteralArgument("run")
            ),
    new CommandArgument("command")
)

A loopingBranch would redirect to the base node of the FlagsArgument, while a terminalBranch could be used to continue down the command tree. There could also be a FlagsArgument inside a branch of another FlagsArgument.

The argument above would create a CommandDispatch tree with an abstract structure like this:

execute Node:
  as Node:
    targets Node
    redirect to execute
  if Node:
    block Node:
      predicate Node
      same termination as if
    entity Node:
      predicate Node
      same termination as if
    redirect to execute
  run Node:
    same termination as execute
  continue to next Node
command Node

Extra details

I'm not sure the FlagsArgument makes sense exactly as I describe, so the API presented here is subject to change.

Implementing anything like the FlagsArgument would also likely require rewriting the CommandAPI's command building system. For one, the CommandAPI doesn't include Brigadier redirects at all. The FlagsArgument also isn't a typical Argument since it's made up of many nodes. I see this as an opportunity though. Currently, the CommandAPI flattens everything into a CommandAPICommand. However, Brigadier natively works with tree structures. Certain features like MultiLiteralArgument, CommandTree, and optional arguments could benefit from building commands directly as trees.

@willkroboth willkroboth added the enhancement New feature or request label Aug 18, 2023
@willkroboth willkroboth self-assigned this Aug 28, 2023
willkroboth added a commit that referenced this issue Sep 2, 2023
Precursor work for #483

Notable changes:
- No more flattening everything into a CommandAPICommand
  - CommandTrees are not flattened
    - CommandMetaData and Execution removed (only used to flatten CommandTrees)
  - MultiLiteralArgument and subcommands are no longer converted into LiteralArguments
  - Optional arguments are not chopped up into multiple arrays
  - In general, a single call to `ExecutableCommand#register` now creates the entire Brigadier tree for that command instance
    - Should only be converting Arguments to Brigadier nodes once instead of multiple times

- CommandAPIHandler no longer creates Brigadier nodes
  - Delegated to AbstractCommandAPICommand, AbstractCommandTree, AbstractArgumentTree.java, and AbstractArgument

- Problems that prevent a command from being registered have been unified under CommandRegistrationException
  - Exception messages tweaked

- Bukkit-specific features removed from `commandapi-core`
  - Removed `isConverted` property of CommandAPICommand
  - Moved logic for flattening EntitySelectorArgument from `CommandAPIHandler#generateBrigadierCommand` to Converter
  - Moved special Bukkit command permission stuff into CommandAPIBukkit

- Taking advantage of Brigadier redirects
  - Command alias nodes redirect to main command name
  - MultiLiteralArgument literal nodes use redirects
  - Instead of duplicating the argument node structure after these arguments, they can reference the same path

TODO:
- The checks performed by `CommandAPIHandler#hasCommandConflict` have not been reimplemented (I'm not sure if they did anything?)
- MultiLiteralArgument is currently broken. See Mojang/brigadier#137
- Many changes not covered by tests (could be sneaky behavioral differences)
willkroboth added a commit that referenced this issue Oct 14, 2023
Precursor work for #483

Notable changes:
- No more flattening everything into a CommandAPICommand
  - CommandTrees are not flattened
    - CommandMetaData and Execution removed (only used to flatten CommandTrees)
  - MultiLiteralArgument and subcommands are no longer converted into LiteralArguments
  - Optional arguments are not chopped up into multiple arrays
  - In general, a single call to `ExecutableCommand#register` now creates the entire Brigadier tree for that command instance
    - Should only be converting Arguments to Brigadier nodes once instead of multiple times

- CommandAPIHandler no longer creates Brigadier nodes
  - Delegated to AbstractCommandAPICommand, AbstractCommandTree, AbstractArgumentTree.java, and AbstractArgument

- Problems that prevent a command from being registered have been unified under CommandRegistrationException
  - Exception messages tweaked

- Bukkit-specific features removed from `commandapi-core`
  - Removed `isConverted` property of CommandAPICommand
  - Moved logic for flattening EntitySelectorArgument from `CommandAPIHandler#generateBrigadierCommand` to Converter
  - Moved special Bukkit command permission stuff into CommandAPIBukkit

- Taking advantage of Brigadier redirects
  - Command alias nodes redirect to main command name
  - MultiLiteralArgument literal nodes use redirects
  - Instead of duplicating the argument node structure after these arguments, they can reference the same path

TODO:
- The checks performed by `CommandAPIHandler#hasCommandConflict` have not been reimplemented (I'm not sure if they did anything?)
- MultiLiteralArgument is currently broken. See Mojang/brigadier#137
- Many changes not covered by tests (could be sneaky behavioral differences)
willkroboth added a commit that referenced this issue Oct 15, 2023
Precursor work for #483

Notable changes:
- No more flattening everything into a CommandAPICommand
  - CommandTrees are not flattened
    - CommandMetaData and Execution removed (only used to flatten CommandTrees)
  - MultiLiteralArgument and subcommands are no longer converted into LiteralArguments
  - Optional arguments are not chopped up into multiple arrays
  - In general, a single call to `ExecutableCommand#register` now creates the entire Brigadier tree for that command instance
    - Should only be converting Arguments to Brigadier nodes once instead of multiple times

- CommandAPIHandler no longer creates Brigadier nodes
  - Delegated to AbstractCommandAPICommand, AbstractCommandTree, AbstractArgumentTree.java, and AbstractArgument

- Problems that prevent a command from being registered have been unified under CommandRegistrationException
  - Exception messages tweaked

- Bukkit-specific features removed from `commandapi-core`
  - Removed `isConverted` property of CommandAPICommand
  - Moved logic for flattening EntitySelectorArgument from `CommandAPIHandler#generateBrigadierCommand` to Converter
  - Moved special Bukkit command permission stuff into CommandAPIBukkit

- Taking advantage of Brigadier redirects
  - Command alias nodes redirect to main command name
  - MultiLiteralArgument literal nodes use redirects
  - Instead of duplicating the argument node structure after these arguments, they can reference the same path

TODO:
- The checks performed by `CommandAPIHandler#hasCommandConflict` have not been reimplemented (I'm not sure if they did anything?)
- MultiLiteralArgument is currently broken. See Mojang/brigadier#137
- Many changes not covered by tests (could be sneaky behavioral differences)
willkroboth added a commit that referenced this issue Dec 24, 2023
Precursor work for #483

Notable changes:
- No more flattening everything into a CommandAPICommand
  - CommandTrees are not flattened
    - CommandMetaData and Execution removed (only used to flatten CommandTrees)
  - MultiLiteralArgument and subcommands are no longer converted into LiteralArguments
  - Optional arguments are not chopped up into multiple arrays
  - In general, a single call to `ExecutableCommand#register` now creates the entire Brigadier tree for that command instance
    - Should only be converting Arguments to Brigadier nodes once instead of multiple times

- CommandAPIHandler no longer creates Brigadier nodes
  - Delegated to AbstractCommandAPICommand, AbstractCommandTree, AbstractArgumentTree.java, and AbstractArgument

- Problems that prevent a command from being registered have been unified under CommandRegistrationException
  - Exception messages tweaked

- Bukkit-specific features removed from `commandapi-core`
  - Removed `isConverted` property of CommandAPICommand
  - Moved logic for flattening EntitySelectorArgument from `CommandAPIHandler#generateBrigadierCommand` to Converter
  - Moved special Bukkit command permission stuff into CommandAPIBukkit

- Taking advantage of Brigadier redirects
  - Command alias nodes redirect to main command name
  - MultiLiteralArgument literal nodes use redirects
  - Instead of duplicating the argument node structure after these arguments, they can reference the same path

TODO:
- The checks performed by `CommandAPIHandler#hasCommandConflict` have not been reimplemented (I'm not sure if they did anything?)
- MultiLiteralArgument is currently broken. See Mojang/brigadier#137
- Many changes not covered by tests (could be sneaky behavioral differences)
willkroboth added a commit that referenced this issue Dec 27, 2023
Changes:
- Implemented `FlagsArgument` (#483)
  - Moved var handles for `CommandNode` `children`,`literals`, and `arguments` to `CommandAPIHandler`
  - Added `FlagsArgumentCommon` FlagsArgumentRootNode` and `FlagsArgumentEndingNode` to handle the special node structure and parsing required
- Updated `CustomArgument`
  - All `AbstractArgument` builder methods are delegated to the base argument
  - Replaced `CommandAPIExecutor` parameter of `AbstractArgument#addArgumentNodes` to a `Function` to allow object that hold arguments to better control how those arguments are executed
- Added package `dev.jorel.commandapi.commandnodes` for class that extend `CommandNode` and related classes
- Tweaked some exceptions
  - `GreedyArgumentException`
    - Changed because the `FlagsArgument` is sometimes greedy - only greedy iff it has no terminal branches
    - Greedy arguments are now detected when `AbstractArgument#addArgumentNodes` returns an empty list
    - Tweaked the exception message
  - `DuplicateNodeNameException`
    - Changed because literal arguments can conflict with other nodes if they are listed
    - Now thrown when two listed arguments have the same node name
    - Added `UnnamedArgumentCommandNode` to make sure unlisted arguments do not conflict
    - Renamed `MultiLiteralCommandNode` to `NamedLiteralCommandNode` for use by listed `Literal` arguments
    - Tweaked the exception message

TODO:
- Clean up code
- Add tests
- Remove test commands in CommandAPIMain
- Add javadocs and documentation
- Hope Mojang/brigadier#144 is resolved, otherwise be annoyed :(
@willkroboth willkroboth mentioned this issue Feb 24, 2024
willkroboth added a commit that referenced this issue Feb 28, 2024
Precursor work for #483

Notable changes:
- No more flattening everything into a CommandAPICommand
  - CommandTrees are not flattened
    - CommandMetaData and Execution removed (only used to flatten CommandTrees)
  - MultiLiteralArgument and subcommands are no longer converted into LiteralArguments
  - Optional arguments are not chopped up into multiple arrays
  - In general, a single call to `ExecutableCommand#register` now creates the entire Brigadier tree for that command instance
    - Should only be converting Arguments to Brigadier nodes once instead of multiple times

- CommandAPIHandler no longer creates Brigadier nodes
  - Delegated to AbstractCommandAPICommand, AbstractCommandTree, AbstractArgumentTree.java, and AbstractArgument

- Problems that prevent a command from being registered have been unified under CommandRegistrationException
  - Exception messages tweaked

- Bukkit-specific features removed from `commandapi-core`
  - Removed `isConverted` property of CommandAPICommand
  - Moved logic for flattening EntitySelectorArgument from `CommandAPIHandler#generateBrigadierCommand` to Converter
  - Moved special Bukkit command permission stuff into CommandAPIBukkit

- Taking advantage of Brigadier redirects
  - Command alias nodes redirect to main command name
  - MultiLiteralArgument literal nodes use redirects
  - Instead of duplicating the argument node structure after these arguments, they can reference the same path

TODO:
- The checks performed by `CommandAPIHandler#hasCommandConflict` have not been reimplemented (I'm not sure if they did anything?)
- MultiLiteralArgument is currently broken. See Mojang/brigadier#137
- Many changes not covered by tests (could be sneaky behavioral differences)
willkroboth added a commit that referenced this issue Feb 28, 2024
Changes:
- Implemented `FlagsArgument` (#483)
  - Moved var handles for `CommandNode` `children`,`literals`, and `arguments` to `CommandAPIHandler`
  - Added `FlagsArgumentCommon` FlagsArgumentRootNode` and `FlagsArgumentEndingNode` to handle the special node structure and parsing required
- Updated `CustomArgument`
  - All `AbstractArgument` builder methods are delegated to the base argument
  - Replaced `CommandAPIExecutor` parameter of `AbstractArgument#addArgumentNodes` to a `Function` to allow object that hold arguments to better control how those arguments are executed
- Added package `dev.jorel.commandapi.commandnodes` for class that extend `CommandNode` and related classes
- Tweaked some exceptions
  - `GreedyArgumentException`
    - Changed because the `FlagsArgument` is sometimes greedy - only greedy iff it has no terminal branches
    - Greedy arguments are now detected when `AbstractArgument#addArgumentNodes` returns an empty list
    - Tweaked the exception message
  - `DuplicateNodeNameException`
    - Changed because literal arguments can conflict with other nodes if they are listed
    - Now thrown when two listed arguments have the same node name
    - Added `UnnamedArgumentCommandNode` to make sure unlisted arguments do not conflict
    - Renamed `MultiLiteralCommandNode` to `NamedLiteralCommandNode` for use by listed `Literal` arguments
    - Tweaked the exception message

TODO:
- Clean up code
- Add tests
- Remove test commands in CommandAPIMain
- Add javadocs and documentation
- Hope Mojang/brigadier#144 is resolved, otherwise be annoyed :(
willkroboth added a commit that referenced this issue Mar 19, 2024
Precursor work for #483

Notable changes:
- No more flattening everything into a CommandAPICommand
  - CommandTrees are not flattened
    - CommandMetaData and Execution removed (only used to flatten CommandTrees)
  - MultiLiteralArgument and subcommands are no longer converted into LiteralArguments
  - Optional arguments are not chopped up into multiple arrays
  - In general, a single call to `ExecutableCommand#register` now creates the entire Brigadier tree for that command instance
    - Should only be converting Arguments to Brigadier nodes once instead of multiple times

- CommandAPIHandler no longer creates Brigadier nodes
  - Delegated to AbstractCommandAPICommand, AbstractCommandTree, AbstractArgumentTree.java, and AbstractArgument

- Problems that prevent a command from being registered have been unified under CommandRegistrationException
  - Exception messages tweaked

- Bukkit-specific features removed from `commandapi-core`
  - Removed `isConverted` property of CommandAPICommand
  - Moved logic for flattening EntitySelectorArgument from `CommandAPIHandler#generateBrigadierCommand` to Converter
  - Moved special Bukkit command permission stuff into CommandAPIBukkit

- Taking advantage of Brigadier redirects
  - Command alias nodes redirect to main command name
  - MultiLiteralArgument literal nodes use redirects
  - Instead of duplicating the argument node structure after these arguments, they can reference the same path

TODO:
- The checks performed by `CommandAPIHandler#hasCommandConflict` have not been reimplemented (I'm not sure if they did anything?)
- MultiLiteralArgument is currently broken. See Mojang/brigadier#137
- Many changes not covered by tests (could be sneaky behavioral differences)
willkroboth added a commit that referenced this issue Mar 19, 2024
Changes:
- Implemented `FlagsArgument` (#483)
  - Moved var handles for `CommandNode` `children`,`literals`, and `arguments` to `CommandAPIHandler`
  - Added `FlagsArgumentCommon` FlagsArgumentRootNode` and `FlagsArgumentEndingNode` to handle the special node structure and parsing required
- Updated `CustomArgument`
  - All `AbstractArgument` builder methods are delegated to the base argument
  - Replaced `CommandAPIExecutor` parameter of `AbstractArgument#addArgumentNodes` to a `Function` to allow object that hold arguments to better control how those arguments are executed
- Added package `dev.jorel.commandapi.commandnodes` for class that extend `CommandNode` and related classes
- Tweaked some exceptions
  - `GreedyArgumentException`
    - Changed because the `FlagsArgument` is sometimes greedy - only greedy iff it has no terminal branches
    - Greedy arguments are now detected when `AbstractArgument#addArgumentNodes` returns an empty list
    - Tweaked the exception message
  - `DuplicateNodeNameException`
    - Changed because literal arguments can conflict with other nodes if they are listed
    - Now thrown when two listed arguments have the same node name
    - Added `UnnamedArgumentCommandNode` to make sure unlisted arguments do not conflict
    - Renamed `MultiLiteralCommandNode` to `NamedLiteralCommandNode` for use by listed `Literal` arguments
    - Tweaked the exception message

TODO:
- Clean up code
- Add tests
- Remove test commands in CommandAPIMain
- Add javadocs and documentation
- Hope Mojang/brigadier#144 is resolved, otherwise be annoyed :(
willkroboth added a commit that referenced this issue Apr 29, 2024
Precursor work for #483

Notable changes:
- No more flattening everything into a CommandAPICommand
  - CommandTrees are not flattened
    - CommandMetaData and Execution removed (only used to flatten CommandTrees)
  - MultiLiteralArgument and subcommands are no longer converted into LiteralArguments
  - Optional arguments are not chopped up into multiple arrays
  - In general, a single call to `ExecutableCommand#register` now creates the entire Brigadier tree for that command instance
    - Should only be converting Arguments to Brigadier nodes once instead of multiple times

- CommandAPIHandler no longer creates Brigadier nodes
  - Delegated to AbstractCommandAPICommand, AbstractCommandTree, AbstractArgumentTree.java, and AbstractArgument

- Problems that prevent a command from being registered have been unified under CommandRegistrationException
  - Exception messages tweaked

- Bukkit-specific features removed from `commandapi-core`
  - Removed `isConverted` property of CommandAPICommand
  - Moved logic for flattening EntitySelectorArgument from `CommandAPIHandler#generateBrigadierCommand` to Converter
  - Moved special Bukkit command permission stuff into CommandAPIBukkit

- Taking advantage of Brigadier redirects
  - Command alias nodes redirect to main command name
  - MultiLiteralArgument literal nodes use redirects
  - Instead of duplicating the argument node structure after these arguments, they can reference the same path

TODO:
- The checks performed by `CommandAPIHandler#hasCommandConflict` have not been reimplemented (I'm not sure if they did anything?)
- MultiLiteralArgument is currently broken. See Mojang/brigadier#137
- Many changes not covered by tests (could be sneaky behavioral differences)
willkroboth added a commit that referenced this issue Apr 29, 2024
Changes:
- Implemented `FlagsArgument` (#483)
  - Moved var handles for `CommandNode` `children`,`literals`, and `arguments` to `CommandAPIHandler`
  - Added `FlagsArgumentCommon` FlagsArgumentRootNode` and `FlagsArgumentEndingNode` to handle the special node structure and parsing required
- Updated `CustomArgument`
  - All `AbstractArgument` builder methods are delegated to the base argument
  - Replaced `CommandAPIExecutor` parameter of `AbstractArgument#addArgumentNodes` to a `Function` to allow object that hold arguments to better control how those arguments are executed
- Added package `dev.jorel.commandapi.commandnodes` for class that extend `CommandNode` and related classes
- Tweaked some exceptions
  - `GreedyArgumentException`
    - Changed because the `FlagsArgument` is sometimes greedy - only greedy iff it has no terminal branches
    - Greedy arguments are now detected when `AbstractArgument#addArgumentNodes` returns an empty list
    - Tweaked the exception message
  - `DuplicateNodeNameException`
    - Changed because literal arguments can conflict with other nodes if they are listed
    - Now thrown when two listed arguments have the same node name
    - Added `UnnamedArgumentCommandNode` to make sure unlisted arguments do not conflict
    - Renamed `MultiLiteralCommandNode` to `NamedLiteralCommandNode` for use by listed `Literal` arguments
    - Tweaked the exception message

TODO:
- Clean up code
- Add tests
- Remove test commands in CommandAPIMain
- Add javadocs and documentation
- Hope Mojang/brigadier#144 is resolved, otherwise be annoyed :(
willkroboth added a commit that referenced this issue Apr 30, 2024
Precursor work for #483

Notable changes:
- No more flattening everything into a CommandAPICommand
  - CommandTrees are not flattened
    - CommandMetaData and Execution removed (only used to flatten CommandTrees)
  - MultiLiteralArgument and subcommands are no longer converted into LiteralArguments
  - Optional arguments are not chopped up into multiple arrays
  - In general, a single call to `ExecutableCommand#register` now creates the entire Brigadier tree for that command instance
    - Should only be converting Arguments to Brigadier nodes once instead of multiple times

- CommandAPIHandler no longer creates Brigadier nodes
  - Delegated to AbstractCommandAPICommand, AbstractCommandTree, AbstractArgumentTree.java, and AbstractArgument

- Problems that prevent a command from being registered have been unified under CommandRegistrationException
  - Exception messages tweaked

- Bukkit-specific features removed from `commandapi-core`
  - Removed `isConverted` property of CommandAPICommand
  - Moved logic for flattening EntitySelectorArgument from `CommandAPIHandler#generateBrigadierCommand` to Converter
  - Moved special Bukkit command permission stuff into CommandAPIBukkit

- Taking advantage of Brigadier redirects
  - Command alias nodes redirect to main command name
  - MultiLiteralArgument literal nodes use redirects
  - Instead of duplicating the argument node structure after these arguments, they can reference the same path

TODO:
- The checks performed by `CommandAPIHandler#hasCommandConflict` have not been reimplemented (I'm not sure if they did anything?)
- MultiLiteralArgument is currently broken. See Mojang/brigadier#137
- Many changes not covered by tests (could be sneaky behavioral differences)
willkroboth added a commit that referenced this issue Apr 30, 2024
Changes:
- Implemented `FlagsArgument` (#483)
  - Moved var handles for `CommandNode` `children`,`literals`, and `arguments` to `CommandAPIHandler`
  - Added `FlagsArgumentCommon` FlagsArgumentRootNode` and `FlagsArgumentEndingNode` to handle the special node structure and parsing required
- Updated `CustomArgument`
  - All `AbstractArgument` builder methods are delegated to the base argument
  - Replaced `CommandAPIExecutor` parameter of `AbstractArgument#addArgumentNodes` to a `Function` to allow object that hold arguments to better control how those arguments are executed
- Added package `dev.jorel.commandapi.commandnodes` for class that extend `CommandNode` and related classes
- Tweaked some exceptions
  - `GreedyArgumentException`
    - Changed because the `FlagsArgument` is sometimes greedy - only greedy iff it has no terminal branches
    - Greedy arguments are now detected when `AbstractArgument#addArgumentNodes` returns an empty list
    - Tweaked the exception message
  - `DuplicateNodeNameException`
    - Changed because literal arguments can conflict with other nodes if they are listed
    - Now thrown when two listed arguments have the same node name
    - Added `UnnamedArgumentCommandNode` to make sure unlisted arguments do not conflict
    - Renamed `MultiLiteralCommandNode` to `NamedLiteralCommandNode` for use by listed `Literal` arguments
    - Tweaked the exception message

TODO:
- Clean up code
- Add tests
- Remove test commands in CommandAPIMain
- Add javadocs and documentation
- Hope Mojang/brigadier#144 is resolved, otherwise be annoyed :(
willkroboth added a commit that referenced this issue May 13, 2024
Precursor work for #483

Notable changes:
- No more flattening everything into a CommandAPICommand
  - CommandTrees are not flattened
    - CommandMetaData and Execution removed (only used to flatten CommandTrees)
  - MultiLiteralArgument and subcommands are no longer converted into LiteralArguments
  - Optional arguments are not chopped up into multiple arrays
  - In general, a single call to `ExecutableCommand#register` now creates the entire Brigadier tree for that command instance
    - Should only be converting Arguments to Brigadier nodes once instead of multiple times

- CommandAPIHandler no longer creates Brigadier nodes
  - Delegated to AbstractCommandAPICommand, AbstractCommandTree, AbstractArgumentTree.java, and AbstractArgument

- Problems that prevent a command from being registered have been unified under CommandRegistrationException
  - Exception messages tweaked

- Bukkit-specific features removed from `commandapi-core`
  - Removed `isConverted` property of CommandAPICommand
  - Moved logic for flattening EntitySelectorArgument from `CommandAPIHandler#generateBrigadierCommand` to Converter
  - Moved special Bukkit command permission stuff into CommandAPIBukkit

- Taking advantage of Brigadier redirects
  - Command alias nodes redirect to main command name
  - MultiLiteralArgument literal nodes use redirects
  - Instead of duplicating the argument node structure after these arguments, they can reference the same path

TODO:
- The checks performed by `CommandAPIHandler#hasCommandConflict` have not been reimplemented (I'm not sure if they did anything?)
- MultiLiteralArgument is currently broken. See Mojang/brigadier#137
- Many changes not covered by tests (could be sneaky behavioral differences)
willkroboth added a commit that referenced this issue May 13, 2024
Changes:
- Implemented `FlagsArgument` (#483)
  - Moved var handles for `CommandNode` `children`,`literals`, and `arguments` to `CommandAPIHandler`
  - Added `FlagsArgumentCommon` FlagsArgumentRootNode` and `FlagsArgumentEndingNode` to handle the special node structure and parsing required
- Updated `CustomArgument`
  - All `AbstractArgument` builder methods are delegated to the base argument
  - Replaced `CommandAPIExecutor` parameter of `AbstractArgument#addArgumentNodes` to a `Function` to allow object that hold arguments to better control how those arguments are executed
- Added package `dev.jorel.commandapi.commandnodes` for class that extend `CommandNode` and related classes
- Tweaked some exceptions
  - `GreedyArgumentException`
    - Changed because the `FlagsArgument` is sometimes greedy - only greedy iff it has no terminal branches
    - Greedy arguments are now detected when `AbstractArgument#addArgumentNodes` returns an empty list
    - Tweaked the exception message
  - `DuplicateNodeNameException`
    - Changed because literal arguments can conflict with other nodes if they are listed
    - Now thrown when two listed arguments have the same node name
    - Added `UnnamedArgumentCommandNode` to make sure unlisted arguments do not conflict
    - Renamed `MultiLiteralCommandNode` to `NamedLiteralCommandNode` for use by listed `Literal` arguments
    - Tweaked the exception message

TODO:
- Clean up code
- Add tests
- Remove test commands in CommandAPIMain
- Add javadocs and documentation
- Hope Mojang/brigadier#144 is resolved, otherwise be annoyed :(
willkroboth added a commit that referenced this issue May 14, 2024
Precursor work for #483

Notable changes:
- No more flattening everything into a CommandAPICommand
  - CommandTrees are not flattened
    - CommandMetaData and Execution removed (only used to flatten CommandTrees)
  - MultiLiteralArgument and subcommands are no longer converted into LiteralArguments
  - Optional arguments are not chopped up into multiple arrays
  - In general, a single call to `ExecutableCommand#register` now creates the entire Brigadier tree for that command instance
    - Should only be converting Arguments to Brigadier nodes once instead of multiple times

- CommandAPIHandler no longer creates Brigadier nodes
  - Delegated to AbstractCommandAPICommand, AbstractCommandTree, AbstractArgumentTree.java, and AbstractArgument

- Problems that prevent a command from being registered have been unified under CommandRegistrationException
  - Exception messages tweaked

- Bukkit-specific features removed from `commandapi-core`
  - Removed `isConverted` property of CommandAPICommand
  - Moved logic for flattening EntitySelectorArgument from `CommandAPIHandler#generateBrigadierCommand` to Converter
  - Moved special Bukkit command permission stuff into CommandAPIBukkit

- Taking advantage of Brigadier redirects
  - Command alias nodes redirect to main command name
  - MultiLiteralArgument literal nodes use redirects
  - Instead of duplicating the argument node structure after these arguments, they can reference the same path

TODO:
- The checks performed by `CommandAPIHandler#hasCommandConflict` have not been reimplemented (I'm not sure if they did anything?)
- MultiLiteralArgument is currently broken. See Mojang/brigadier#137
- Many changes not covered by tests (could be sneaky behavioral differences)
willkroboth added a commit that referenced this issue May 14, 2024
Changes:
- Implemented `FlagsArgument` (#483)
  - Moved var handles for `CommandNode` `children`,`literals`, and `arguments` to `CommandAPIHandler`
  - Added `FlagsArgumentCommon` FlagsArgumentRootNode` and `FlagsArgumentEndingNode` to handle the special node structure and parsing required
- Updated `CustomArgument`
  - All `AbstractArgument` builder methods are delegated to the base argument
  - Replaced `CommandAPIExecutor` parameter of `AbstractArgument#addArgumentNodes` to a `Function` to allow object that hold arguments to better control how those arguments are executed
- Added package `dev.jorel.commandapi.commandnodes` for class that extend `CommandNode` and related classes
- Tweaked some exceptions
  - `GreedyArgumentException`
    - Changed because the `FlagsArgument` is sometimes greedy - only greedy iff it has no terminal branches
    - Greedy arguments are now detected when `AbstractArgument#addArgumentNodes` returns an empty list
    - Tweaked the exception message
  - `DuplicateNodeNameException`
    - Changed because literal arguments can conflict with other nodes if they are listed
    - Now thrown when two listed arguments have the same node name
    - Added `UnnamedArgumentCommandNode` to make sure unlisted arguments do not conflict
    - Renamed `MultiLiteralCommandNode` to `NamedLiteralCommandNode` for use by listed `Literal` arguments
    - Tweaked the exception message

TODO:
- Clean up code
- Add tests
- Remove test commands in CommandAPIMain
- Add javadocs and documentation
- Hope Mojang/brigadier#144 is resolved, otherwise be annoyed :(
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant