Skip to content

Commit d8b94da

Browse files
committed
feat: kotlin-based commands part
1 parent 274983d commit d8b94da

File tree

6 files changed

+574
-1
lines changed

6 files changed

+574
-1
lines changed

docs/.vitepress/theme/prefer/PreferenceSwitch.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ onMounted(() => {
121121
/>
122122
<label class="maven-label" @click="toggleMaven(true)">Maven</label>
123123
</div>
124-
<div v-if="!preferMaven" class="switch-container">
124+
<div v-if="preferencesToDisplay.includes('build-system') && !preferMaven" class="switch-container">
125125
<label class="groovy-label" @click="toggleGradleDsl(false)">.gradle</label>
126126
<VTSwitch
127127
class="dsl-switch"
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
---
2+
order: 3
3+
authors:
4+
- DerEchtePilz
5+
---
6+
7+
# Delegated properties
8+
9+
The CommandAPI offers an additional way to access arguments when using Kotlin: [delegated properties](https://kotlinlang.org/docs/delegated-properties.html). With delegated properties, there are two possible dependencies you can use:
10+
11+
1. `commandapi-core-kotlin`
12+
13+
Support for delegated properties has been added to the `commandapi-core-kotlin` module. If you want to use delegated properties, you need to add this dependency.
14+
15+
2. `commandapi-bukkit-kotlin`
16+
17+
If you are already using the Kotlin DSL to create your commands, you can already use delegated properties. `commandapi-core-kotlin` is included in `commandapi-bukkit-kotlin`.
18+
19+
### Access arguments using delegated properties
20+
21+
To be able to access arguments by using delegated properties, your variable name needs to match the node name of the argument. This could look like this:
22+
23+
:::tabs
24+
===Kotlin
25+
<<< @/../reference-code/src/main/kotlin/kotlindsl/DelegatedProperties.kt#delegatedPropertiesExample
26+
===Kotlin DSL
27+
<<< @/../reference-code/src/main/kotlin/kotlindsl/DelegatedProperties.kt#delegatedPropertiesExampleDSL
28+
:::

docs/en/kotlin-dsl/intro.md

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
---
2+
order: 1
3+
preferences: ["build-system"]
4+
authors:
5+
- JorelAli
6+
- willkroboth
7+
- DerEchtePilz
8+
---
9+
10+
# Kotlin-based commands
11+
12+
The CommandAPI also provides an alternative way of making commands when using Kotlin to develop your plugins: A DSL!
13+
14+
This DSL provides many methods to easily add arguments to your command structure. Examples of the DSL can be found [here](./usage.md).
15+
16+
## Installing the DSL
17+
18+
To install the DSL, you need to add the `commandapi-bukkit-kotlin` dependency into your `pom.xml` or your `build.gradle`, making sure to specify the server flavor you are developing for:
19+
20+
### Adding the dependency
21+
22+
<div class="maven">
23+
24+
```xml
25+
<dependencies>
26+
<dependency>
27+
<groupId>dev.jorel</groupId>
28+
<artifactId>commandapi-bukkit-kotlin</artifactId>
29+
<version>9.7.0</version>
30+
</dependency>
31+
</dependencies>
32+
```
33+
34+
Next, you need to add Kotlin to your project. For this, you first need to add the dependency:
35+
36+
```xml
37+
<dependencies>
38+
<dependency>
39+
<groupId>org.jetbrains.kotlin</groupId>
40+
<artifactId>kotlin-stdlib</artifactId>
41+
<version>1.9.0</version>
42+
</dependency>
43+
</dependencies>
44+
```
45+
46+
Finally, you need to add the `kotlin-maven-plugin`:
47+
48+
```xml
49+
<build>
50+
<plugins>
51+
<plugin>
52+
<groupId>org.jetbrains.kotlin</groupId>
53+
<artifactId>kotlin-maven-plugin</artifactId>
54+
<version>1.9.0</version>
55+
<executions>
56+
<execution>
57+
<id>compile</id>
58+
<phase>compile</phase>
59+
<goals>
60+
<goal>compile</goal>
61+
</goals>
62+
</execution>
63+
<execution>
64+
<id>test-compile</id>
65+
<phase>test-compile</phase>
66+
<goals>
67+
<goal>test-compile</goal>
68+
</goals>
69+
</execution>
70+
</executions>
71+
<configuration>
72+
<jvmTarget>16</jvmTarget>
73+
</configuration>
74+
</plugin>
75+
</plugins>
76+
</build>
77+
```
78+
79+
</div>
80+
<div class="gradle">
81+
82+
First, you need to add the repository:
83+
84+
<div class="groovy">
85+
86+
```groovy
87+
repositories {
88+
mavenCentral()
89+
}
90+
```
91+
92+
</div>
93+
<div class="kts">
94+
95+
```kotlin
96+
repositories {
97+
mavenCentral()
98+
}
99+
```
100+
101+
</div>
102+
103+
Next, you need to add the dependency:
104+
105+
<div class="groovy">
106+
107+
```groovy
108+
dependencies {
109+
implementation "dev.jorel:commandapi-bukkit-kotlin:9.7.0"
110+
}
111+
```
112+
113+
</div>
114+
<div class="kts">
115+
116+
```kotlin
117+
dependencies {
118+
implementation("dev.jorel:commandapi-bukkit-kotlin:9.7.0")
119+
}
120+
```
121+
122+
</div>
123+
124+
You also need to add Kotlin to your project. For this, you first need to add the Kotlin plugin:
125+
126+
<div class="groovy">
127+
128+
```groovy
129+
plugins {
130+
id "org.jetbrains.kotlin.jvm" version "1.9.0"
131+
}
132+
```
133+
134+
</div>
135+
<div class="kts">
136+
137+
```kotlin
138+
plugins {
139+
kotlin("jvm") version "1.9.0"
140+
}
141+
```
142+
143+
</div>
144+
145+
Next, you need to add the dependency (you should already have added the `mavenCentral()` repository to your project):
146+
147+
<div class="groovy">
148+
149+
```groovy
150+
dependencies {
151+
implementation "org.jetbrains.kotlin:kotlin-stdlib"
152+
}
153+
```
154+
155+
</div>
156+
<div class="kts">
157+
158+
```kotlin
159+
dependencies {
160+
implementation("org.jetbrains.kotlin:kotlin-stdlib")
161+
}
162+
```
163+
164+
</div>
165+
166+
Then, you need to configure the Java version to build against:
167+
168+
<div class="groovy">
169+
170+
```groovy
171+
kotlin {
172+
jvmToolchain(16)
173+
}
174+
```
175+
176+
</div>
177+
<div class="kts">
178+
179+
```kotlin
180+
kotlin {
181+
jvmToolchain(16)
182+
}
183+
```
184+
185+
</div>
186+
187+
</div>

docs/en/kotlin-dsl/usage.md

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
---
2+
order: 2
3+
authors:
4+
- JorelAli
5+
- willkroboth
6+
- DerEchtePilz
7+
- Sytm
8+
---
9+
10+
# Using the DSL
11+
12+
## Defining a simple message command
13+
14+
As a first example and to take a first look at the Kotlin DSL syntax, we will first create a simple command to send messages to a player.
15+
16+
::::tip Example – Sending a message to a player using the Kotlin DSL
17+
18+
We want to create a command that lets us send a message to a player. To do this, we want to register a command with the following syntax:
19+
20+
```mccmd
21+
/sendmessageto <player> <msg>
22+
```
23+
24+
We can then use the following command registration:
25+
26+
:::tabs key:dsl-usage-page
27+
===CommandTree
28+
<<< @/../reference-code/src/main/kotlin/kotlindsl/Usage.kt#dslTreeExample
29+
===CommandAPICommand
30+
<<< @/../reference-code/src/main/kotlin/kotlindsl/Usage.kt#dslExample
31+
:::
32+
33+
34+
Here you can see some interesting things:
35+
36+
- You do not need to call the `.register()` method when using the DSL
37+
- You do not need to initialise any arguments
38+
39+
::::
40+
41+
## Executors
42+
43+
The Kotlin DSL also provides executors to execute your command. You've seen the `anyExecutor` in the example above.
44+
45+
To find out, which DSL executor corresponds to "normal" executors, you can refer to the table below:
46+
47+
| DSL normal executor | DSL resulting executor | DSL normal execution info | DSL resulting execution info | "normal" Executor |
48+
|---------------------------|------------------------------------|--------------------------------|-----------------------------------------|---------------------------|
49+
| `anyExecutor()` | `anyResultingExecutor()` | `anyExecutionInfo()` | `anyResultingExecutionInfo` | `executes()` |
50+
| `playerExecutor()` | `playerResultingExecutor()` | `playerExecutionInfo()` | `playerResultingExecutionInfo()` | `executesPlayer()` |
51+
| `entityExecutor()` | `entityResultingExecutor()` | `entityExecutionInfo()` | `entityResultingExecutionInfo()` | `executesEntity()` |
52+
| `consoleExecutor()` | `consoleResultingExecutor()` | `consoleExecutionInfo()` | `consoleResultingExecutionInfo()` | `executesConsole()` |
53+
| `commandBlockExecutor()` | `commandBlockResultingExecutor()` | `commandBlockExecutionInfo()` | `commandBlockResultingExecutionInfo()` | `executesCommandBlock()` |
54+
| `proxyExecutor()` | `proxyResultingExecutor()` | `proxyExecutionInfo()` | `proxyResultingExecutionInfo()` | `executesProxy()` |
55+
| `nativeExecutor()` | `nativeResultingExecutor()` | `nativeExecutionInfo()` | `nativeResultingExecutionInfo()` | `executesNative()` |
56+
| `remoteConsoleExecutor()` | `remoteConsoleResultingExecutor()` | `remoteConsoleExecutionInfo()` | `remoteConsoleResultingExecutionInfo()` | `executesRemoteConsole()` |
57+
58+
## Arguments
59+
60+
The DSL implements almost every argument with a method. You've seen the `playerArgument()` and the `greedyStringArgument()` method in the example at the top of this page.
61+
62+
The way arguments are implemented is pretty straight forward: It's basically the argument class' name, but as a method. So if you wanted to use a `ItemStackArgument` in your command, you would use the `itemStackArgument()` method of the DSL.
63+
64+
One thing to note is that the DSL also features every existing constructor. This means if you want to use an `IntegerArgument` with a minimum of `0` and a maximum of `10`, you normally would implement it like this:
65+
66+
```java
67+
new IntegerArgument("integer", 0, 10)
68+
```
69+
70+
However, when using this DSL it is implemented like this:
71+
72+
```kotlin
73+
integerArgument("integer", 0, 10)
74+
```
75+
76+
:::warning Developer's Note:
77+
78+
There are a few arguments not having a method which directly corresponds to their respective argument.
79+
80+
These arguments most likely use a builder pattern and because of that require further implementation by the user.
81+
82+
To use these arguments, the DSL also provides the `argument()` method which takes in any argument as a parameter.
83+
84+
:::
85+
86+
## Editing arguments
87+
88+
When using the DSL, you might want to modify the behaviour of certain arguments by adding requirements or suggestions to them.
89+
90+
To give you a general idea how you could accomplish that, the `sendMessageTo` command is adding a broadcast option which should only be executed by server operators.
91+
92+
:::tabs key:dsl-usage-page
93+
===CommandTree
94+
<<< @/../reference-code/src/main/kotlin/kotlindsl/Usage.kt#argumentRequirementsTreeExample
95+
===CommandAPICommand
96+
<<< @/../reference-code/src/main/kotlin/kotlindsl/Usage.kt#argumentRequirementsExample
97+
:::
98+
99+
Notice how you can just add the requirement in a CommandTree by adding it to the argument block where you also define the next arguments and the executor.
100+
101+
However, when modifying the behaviour of an argument in a CommandAPICommand you have to add an extra block where you can implement the additional behaviour.
102+
103+
### Adding requirements to commands
104+
105+
Expanding on the previous example where we added a requirement to a single argument, we now also want to add a requirement to a whole command.
106+
107+
This works similar to how argument behaviour is modified in a CommandTree:
108+
109+
:::tabs key:dsl-usage-page
110+
===CommandTree
111+
<<< @/../reference-code/src/main/kotlin/kotlindsl/Usage.kt#commandRequirementsTreeExample
112+
===CommandAPICommand
113+
<<< @/../reference-code/src/main/kotlin/kotlindsl/Usage.kt#commandRequirementsExample
114+
:::
115+
116+
## More examples
117+
118+
Now, a few more examples are shown to demonstrate the use of this DSL a little more:
119+
120+
::::tip Example – Implementing optional arguments with the Kotlin DSL
121+
122+
We want to create a `/give` command with the following syntax:
123+
124+
```mccmd
125+
/optionalArgument give <item>
126+
/optionalArgument give <item> <amount>
127+
```
128+
129+
To declare an argument as optional you need to set the `optional` value to `true`:
130+
131+
:::tabs key:dsl-usage-page
132+
===CommandTree
133+
<<< @/../reference-code/src/main/kotlin/kotlindsl/Usage.kt#optionalArgumentsTreeExample
134+
===CommandAPICommand
135+
<<< @/../reference-code/src/main/kotlin/kotlindsl/Usage.kt#optionalArgumentsExample
136+
:::
137+
138+
::::
139+
140+
::::tip Example – Replacing suggestions using the Kotlin DSL
141+
142+
We want to create a command with the following syntax to demonstrate replacing suggestions using the Kotlin DSL:
143+
144+
```mccmd
145+
/replaceSuggestions <strings>
146+
```
147+
148+
Replacing suggestions works similar to how you would add a requirement to an argument as shown in [Editing arguments](#editing-arguments).
149+
150+
You just have to use the `replaceSuggestions` method this time:
151+
152+
:::tabs key:dsl-usage-page
153+
===CommandTree
154+
<<< @/../reference-code/src/main/kotlin/kotlindsl/Usage.kt#replaceSuggestionsTreeExample
155+
===CommandAPICommand
156+
<<< @/../reference-code/src/main/kotlin/kotlindsl/Usage.kt#replaceSuggestionsExample
157+
:::
158+
159+
::::

0 commit comments

Comments
 (0)