|
| 1 | +--- |
| 2 | +order: 11 |
| 3 | +authors: |
| 4 | + - JorelAli |
| 5 | + - willkroboth |
| 6 | + - DerEchtePilz |
| 7 | + - MC-XiaoHei |
| 8 | +--- |
| 9 | + |
| 10 | +# Command trees |
| 11 | + |
| 12 | +So far in this documentation, we've described many different ways to register commands. We've described writing commands by declaring a `CommandAPICommand` object, using a list of arguments and providing an executor for the command. We've also described another way of registering commands with multiple "paths" using the `withSubcommand` method to generate a tree-like structure. As of CommandAPI 7.0.0, another method for registering commands, _command trees_, has been introduced. |
| 13 | + |
| 14 | +## The `executes()` and `then()` methods |
| 15 | + |
| 16 | +The Command Tree represents command structures in a tree-like fashion, in a very similar way that Brigadier's API lets you declare commands. Command tree commands effectively revolve around two methods: |
| 17 | + |
| 18 | +```java |
| 19 | +public T executes(CommandExecutor executor); |
| 20 | + |
| 21 | +public CommandTree then(ArgumentTree branch); |
| 22 | +public ArgumentTree then(ArgumentTree branch); |
| 23 | +``` |
| 24 | + |
| 25 | +The `executes()` method is the same `executes()` method that you have seen previously in this documentation for normal CommandAPI commands. This also includes all of the `executes...()` methods described in [Normal command executors](./executors/normal-executors#restricting-who-can-run-your-command), but for the sake of simplicity, we'll simply refer to all of these by `executes()`. |
| 26 | + |
| 27 | +The `then()` method allows you to create new "branches" in your command "tree" data structure. If you are familiar with [Brigadier](https://github.com/Mojang/brigadier)'s `then()` method for argument nodes, then you should feel right at home. Otherwise, for all intents and purposes `then()` lets you specify additional paths that a command can take when a user is typing their command. |
| 28 | + |
| 29 | +Because the underlying type hierarchy of command trees is fairly complex (`then()` having multiple return types and taking in `ArgumentTree` objects), instead of trying to describe how all of that works, we'll instead describe how to make command trees by using the methods `executes()` and `then()` in practice. |
| 30 | + |
| 31 | +## Declaring a command tree |
| 32 | + |
| 33 | +The basic syntax of a command tree is effectively identical to a normal `CommandAPICommand`, but instead you use the `CommandTree` object. For example, if we want to create a simple command which sends "Hi!" to a command sender, we declare the name of our command, make use of the `executes()` method, and then we use the `CommandTree` constructor instead of the `CommandAPICommand` constructor: |
| 34 | + |
| 35 | +```mccmd |
| 36 | +/sayhi |
| 37 | +``` |
| 38 | + |
| 39 | +```java |
| 40 | +new CommandAPICommand("sayhi") |
| 41 | + .executes((sender, args) -> { |
| 42 | + sender.sendMessage("Hi!"); |
| 43 | + }) |
| 44 | + .register(); |
| 45 | +``` |
| 46 | + |
| 47 | +$$\downarrow$$ |
| 48 | + |
| 49 | +```java |
| 50 | +new CommandTree("sayhi") |
| 51 | + .executes((sender, args) -> { |
| 52 | + sender.sendMessage("Hi!"); |
| 53 | + }) |
| 54 | + .register(); |
| 55 | +``` |
| 56 | + |
| 57 | +## Adding arguments to a command tree |
| 58 | + |
| 59 | +Unlike the `CommandAPICommand` class, the `CommandTree` class doesn't let you add arguments using the `withArguments()` method. Instead, it makes use of the `then()` method, which allows you to provide an argument to it. This is best described with an example. |
| 60 | + |
| 61 | +::::tip Example – Declaring a command tree with a single argument |
| 62 | + |
| 63 | +Say we want to take our `/sayhi` command from above and also have an argument which lets you specify a target player. In this example, we'll have the following command syntax: |
| 64 | + |
| 65 | +```mccmd |
| 66 | +/sayhi - Says "Hi!" to the current sender |
| 67 | +/sayhi <target> - Says "Hi!" to a target player |
| 68 | +``` |
| 69 | + |
| 70 | +We can do this by adding a `PlayerArgument` to our command. As described above, to add this argument, we must use the `then()` method: |
| 71 | + |
| 72 | +:::tabs |
| 73 | +===Java |
| 74 | +<<< @/../reference-code/src/main/java/createcommands/CommandTrees.java#commandTreesExample |
| 75 | +===Kotlin |
| 76 | +<<< @/../reference-code/src/main/kotlin/createcommands/CommandTrees.kt#commandTreesExample |
| 77 | +::: |
| 78 | + |
| 79 | +In this example, we have our normal `/sayhi` command using the `executes()` method. We then add a new argument (a new "branch" in our "tree"), the `PlayerArgument`, using the `then()` method. **We want to make this branch executable, so we also use the `executes()` method _on the argument itself_**. To register the full command tree (which includes both `/sayhi` and `/sayhi <target>`), we call `register()` on the `CommandTree` object. |
| 80 | + |
| 81 | +:::: |
| 82 | + |
| 83 | +### Reduce indentation with nested arguments |
| 84 | + |
| 85 | +Sometimes we will need such a `CommandTree`: |
| 86 | + |
| 87 | +:::tabs |
| 88 | +===Java |
| 89 | +<<< @/../reference-code/src/main/java/createcommands/CommandTrees.java#legacyLargeArgumentsExample |
| 90 | +===Kotlin |
| 91 | +<<< @/../reference-code/src/main/kotlin/createcommands/CommandTrees.kt#legacyLargeArgumentsExample |
| 92 | +===Kotlin DSL |
| 93 | +<<< @/../reference-code/src/main/kotlin/createcommands/CommandTrees.kt#legacyLargeArgumentsExampleDSL |
| 94 | +::: |
| 95 | + |
| 96 | +Well, there's too much indentation. We can use nested arguments to reduce the indentation levels: |
| 97 | + |
| 98 | +:::tabs |
| 99 | +===Java |
| 100 | +<<< @/../reference-code/src/main/java/createcommands/CommandTrees.java#nestedLargeArgumentsExample |
| 101 | +===Kotlin |
| 102 | +<<< @/../reference-code/src/main/kotlin/createcommands/CommandTrees.kt#nestedLargeArgumentsExample |
| 103 | +===Kotlin DSL |
| 104 | +<<< @/../reference-code/src/main/kotlin/createcommands/CommandTrees.kt#nestedLargeArgumentsExampleDSL |
| 105 | +::: |
| 106 | + |
| 107 | +That's effectively all of the basics of command trees! We start by writing a normal command, use `executes()` to make it executable and use `then()` to add additional paths to our command. Finally, we finish up with `register()` to register our command. Below, I've included a few more examples showcasing how to design commands using command trees. |
| 108 | + |
| 109 | +## Command tree examples |
| 110 | + |
| 111 | +::::tip Example – Sign editing plugin |
| 112 | + |
| 113 | +Say we wanted to create a plugin to let a user edit signs. We have a single command tree `/signedit`, with a number of branching paths `set`, `clear`, `copy` and `paste` which represent various operations that this command can be performed on a sign: |
| 114 | + |
| 115 | +```mccmd |
| 116 | +/signedit set <line_number> <text> - Sets the text for a line on a sign |
| 117 | +/signedit clear <line_number> - Clears a sign's text on a specific line |
| 118 | +/signedit copy <line_number> - Copies the current text from a line on a sign |
| 119 | +/signedit paste <line_number> - Pastes the copied text onto a line on a sign |
| 120 | +``` |
| 121 | + |
| 122 | +:::tabs |
| 123 | +===Java |
| 124 | +<<< @/../reference-code/src/main/java/createcommands/CommandTrees.java#signeditCommandExample |
| 125 | +===Kotlin |
| 126 | +<<< @/../reference-code/src/main/kotlin/createcommands/CommandTrees.kt#signeditCommandExample |
| 127 | +::: |
| 128 | + |
| 129 | +:::: |
0 commit comments