Skip to content

Commit e6c46a2

Browse files
committed
feat: all argument pages finished
1 parent be8789f commit e6c46a2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+2644
-1
lines changed

docs/.vitepress/config.mts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {VitePressSidebarOptions, withSidebar} from "vitepress-sidebar";
77
import {tabsPlugin} from "./theme/tabs/markdownPlugin";
88
import fs from "fs";
99
import {exampleAutoAnchorPreprocessor} from "./theme/anchor/exampleAutoAnchorPreprocessor";
10+
import {mathjaxContainerPreprocessor} from "./theme/mathjax/mathjaxContainerPreprocessor";
1011

1112
const defaultLocale: string = 'en';
1213
const supportLocales: string[] = [
@@ -103,6 +104,7 @@ const vitepressOptions: UserConfig = {
103104
config: (md) => {
104105
tabsPlugin(md);
105106
exampleAutoAnchorPreprocessor(md);
107+
mathjaxContainerPreprocessor(md);
106108
}
107109
}
108110
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import MarkdownIt from "markdown-it";
2+
3+
export const mathjaxContainerPreprocessor = (md: MarkdownIt) => {
4+
md.core.ruler.before('normalize', 'mathjax-container', (state) => {
5+
const lines = state.src.split("\n");
6+
const processedLines = lines.map((line) => {
7+
if (line.startsWith("$$\\begin")) {
8+
return `
9+
<div style="overflow-x: auto">
10+
<div style="width: fit-content;">
11+
12+
${line}
13+
`;
14+
} else if (line.endsWith("}$$")) {
15+
return `
16+
${line}
17+
18+
</div>
19+
</div>
20+
`;
21+
} else {
22+
return line;
23+
}
24+
});
25+
state.src = processedLines.join("\n");
26+
});
27+
}

docs/.vitepress/theme/tabs/markdownPlugin.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ type Params = {
1010
shareStateKey: string | undefined
1111
}
1212

13+
const parseTabsParams = (input: string, fallback: string): Params => {
14+
const match = input.match(/key:(\S+)/)
15+
return {
16+
shareStateKey: match?.[1] ?? fallback
17+
}
18+
}
19+
1320
export const tabsPlugin = (md: MarkdownIt) => {
1421
md.use(container, 'tabs', {
1522
render(tokens: Token[], index: number) {
@@ -26,7 +33,11 @@ export const tabsPlugin = (md: MarkdownIt) => {
2633
}
2734
const token = tokens[index]
2835
if (token.nesting === 1) {
29-
return `<PluginTabs sharedStateKey="${tabsCnt}">\n`
36+
const params = parseTabsParams(token.info, `tabs-${tabsCnt}`);
37+
const shareStateKeyProp = params.shareStateKey
38+
? `sharedStateKey="${md.utils.escapeHtml(params.shareStateKey)}"`
39+
: ''
40+
return `<PluginTabs ${shareStateKeyProp}>\n`
3041
} else {
3142
return `</PluginTabs>\n`
3243
}

docs/en/create-commands/arguments/command-arguments.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ authors:
44
- DerEchtePilz
55
- willkroboth
66
- JorelAli
7+
title: CommandArguments class
78
---
89

910
# The `CommandArguments` class
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
---
2+
order: 15
3+
authors:
4+
- DerEchtePilz
5+
- JorelAli
6+
- willkroboth
7+
---
8+
9+
# Command arguments
10+
11+
![Command arguments](/images/commandargument.gif)
12+
13+
Command arguments allows users to provide an executable server command. The `CommandArgument` class lets you specify:
14+
15+
- Arbitrary commands - any command that the user has permissions to run can be provided.
16+
- Restricted commands - only specific commands can be provided.
17+
18+
Using the `CommandArgument` will return a `CommandResult`, which contains a Bukkit `Command` instance representing the command to be executed, and a `String[]` of command arguments.
19+
20+
## Command results
21+
22+
The `CommandResult` record contains the following methods:
23+
24+
```java
25+
public record CommandResult {
26+
Command command();
27+
String[] args();
28+
29+
boolean execute(CommandSender target);
30+
}
31+
```
32+
33+
These methods can be used to retrieve information about the command that was provided by the user:
34+
35+
```java
36+
Command command();
37+
```
38+
39+
`command()` returns the Bukkit `Command` instance that the user provided. For example, if a player provided `/mycommand hello world`, then `command()` will represent the `/mycommand` command.
40+
41+
```java
42+
String[] args();
43+
```
44+
45+
`args()` returns an array of string argument inputs that were provided to the command. For example, if a player provided `/mycommand hello world`, then `args()` will be the following:
46+
47+
```java
48+
[ "hello", "world" ]
49+
```
50+
51+
```java
52+
boolean execute(CommandSender target);
53+
```
54+
55+
`execute(CommandSender)` runs the Bukkit `Command` using the arguments contained in the `CommandResult` as the given `CommandSender`. It returns true if the command dispatch succeeded, and false if it failed. Using this method is equivalent to running the following:
56+
57+
```java
58+
result.command().execute(target, result.command().getLabel(), result.args());
59+
```
60+
61+
## Arbitrary commands
62+
63+
Arbitrary commands let the user enter any command that they have permission to execute. To use arbitrary commands, you just need to use the `CommandArgument` normally.
64+
65+
::::tip Example - A `/sudo` command
66+
67+
We want to create a `/sudo` command which lets you execute a command as another online player.
68+
69+
![Sudo command example](/images/sudocommand.gif)
70+
71+
To do this, we want to use the following command syntax:
72+
73+
```mccmd
74+
/sudo <target> <command>
75+
```
76+
77+
In this example, we want to be able to run any arbitrary command, so we will simply use the `CommandArgument` on its own (without using suggestions). Using the `CommandArgument` generates a `CommandResult` and we can use the `.command()` and `.args()` methods above to access the command and arguments. We can make use of the `Command.execute()` method to execute our command and use the target player as the command sender.
78+
79+
:::tabs
80+
===Java
81+
<<< @/../reference-code/src/main/java/createcommands/arguments/types/CommandArguments.java#sudoCommandExample
82+
===Kotlin
83+
<<< @/../reference-code/src/main/kotlin/createcommands/arguments/types/CommandArguments.kt#sudoCommandExample
84+
===Kotlin DSL
85+
<<< @/../reference-code/src/main/kotlin/createcommands/arguments/types/CommandArguments.kt#sudoCommandExampleDSL
86+
:::
87+
88+
::::
89+
90+
## Restricted commands
91+
92+
Restricted commands allows you to restrict what commands a user is allowed to submit in the `CommandArgument`. Commands can be restricted by replacing the `CommandArgument`'s suggestions using the `replaceSuggestions()` method. For better fine-tuning of what commands a user can submit, commands can also be restricted by using _suggestion branches_.
93+
94+
<!-- TODO: Give an example using .replaceSuggestions(). -->
95+
96+
::::tip Example – Restricting commands using suggestion branches
97+
98+
To demonstrate restricting commands, let's create a command argument that allows players to enter one of the following commands:
99+
100+
```mccmd
101+
/tp <player> <target>
102+
/give <player> <item> <amount>
103+
```
104+
105+
Let's also add a restriction that the player can only use diamonds or dirt for the `/give` command, and they can only specify an amount if they selected dirt. Overall, our command argument should allow players to follow this path:
106+
107+
$$\begin{gather}
108+
\texttt{(start)}\\\\
109+
\swarrow\hspace{1.2cm}\searrow\\\\
110+
\texttt{tp}\hspace{2cm}\texttt{give}\\\\
111+
\swarrow\hspace{3cm}\searrow\\\\
112+
\texttt{player}\hspace{3.25cm}\texttt{player}\\\\
113+
\hspace{0.25cm}\swarrow\hspace{3.75cm}\swarrow\hspace{1cm}\searrow\\\\
114+
\hspace{0.25cm}\texttt{target}\hspace{3cm}\texttt{diamond}\hspace{1.75cm}\texttt{dirt}\\\\
115+
\hspace{4.9cm}\texttt{minecraft:diamond}\hspace{1.75cm}\texttt{minecraft:dirt}\\\\
116+
\hspace{10cm}\downarrow\\\\
117+
\hspace{10cm}\texttt{(amount)}\\\\
118+
\end{gather}$$
119+
120+
In our diagram above, we have two main branches: `/tp` and `/give`. The `/tp` branch has `player` followed by `target`, and the `/give` branch has `player` and then that branches off into two new sections.
121+
122+
We can implement our `/tp` branch using the `SuggestionsBranch.suggest()` method, then provide argument suggestions for our options. In this case, we have `tp` and then a list of online players. We include the list of online players twice, because we need suggestions for `<player>` as well as `<target>`:
123+
124+
:::tabs
125+
===Java
126+
<<< @/../reference-code/src/main/java/createcommands/arguments/types/CommandArguments.java#suggestionBranchesStep1
127+
===Kotlin
128+
<<< @/../reference-code/src/main/kotlin/createcommands/arguments/types/CommandArguments.kt#suggestionBranchesStep1
129+
:::
130+
131+
For the `/give` branch, we can use a similar thing, but we need to tell the CommandArgument that the `/give` command branches into "diamond" and "dirt" suggestions. We can do this by using the `.branch()` method to add a new nested list of suggestions:
132+
133+
:::tabs
134+
===Java
135+
<<< @/../reference-code/src/main/java/createcommands/arguments/types/CommandArguments.java#suggestionBranchesStep2
136+
===Kotlin
137+
<<< @/../reference-code/src/main/kotlin/createcommands/arguments/types/CommandArguments.kt#suggestionBranchesStep2
138+
:::
139+
140+
Adding everything together, we get this fully completed CommandArgument:
141+
142+
:::tabs
143+
===Java
144+
<<< @/../reference-code/src/main/java/createcommands/arguments/types/CommandArguments.java#suggestionBranchesStep3
145+
===Kotlin
146+
<<< @/../reference-code/src/main/kotlin/createcommands/arguments/types/CommandArguments.kt#suggestionBranchesStep3
147+
:::
148+
149+
::::
150+
151+
### Null and empty suggestions
152+
153+
In the above example about restricted commands, we used `null` and `ArgumentSuggestions.empty()` in our `SuggestionsBranch.suggest()` method. These special suggestions have specific effects when used in suggestions for the `CommandArgument`.
154+
155+
#### Null suggestions
156+
157+
Null suggestions ensure that the suggestions at the current position will not be overridden. In the case of the `CommandArgument`, this means that the default command suggestions will be provided. For example, if we have the following `null` entry in our suggestions, users are allowed to enter a value if they choose to do so, meaning that the examples below are all valid:
158+
159+
```java
160+
SuggestionsBranch.suggest(
161+
ArgumentSuggestions.strings("give"),
162+
null,
163+
ArgumentSuggestions.empty()
164+
)
165+
```
166+
167+
```mccmd
168+
/give dirt
169+
/give diamond
170+
/give apple
171+
```
172+
173+
Ending the command argument with nothing is also equivalent to using `null`, for example the following suggestion branch allows any of the following commands:
174+
175+
```java
176+
SuggestionsBranch.suggest(
177+
ArgumentSuggestions.strings("give"),
178+
ArgumentSuggestions.strings("dirt", "minecraft:dirt")
179+
)
180+
```
181+
182+
```mccmd
183+
/give dirt
184+
/give dirt 10
185+
/give dirt 10 name:Hello
186+
```
187+
188+
#### Empty suggestions
189+
190+
Empty suggestions that are provided using `ArgumentSuggestions.empty()` tell the `CommandArgument` to stop accepting further suggestions. This "ends" the command. Using the following example, this allows the user to enter `/give diamond` and only `/give diamond` - users cannot enter any other commands.
191+
192+
```java
193+
SuggestionsBranch.suggest(
194+
ArgumentSuggestions.strings("give"),
195+
ArgumentSuggestions.strings("diamond", "minecraft:diamond"),
196+
ArgumentSuggestions.empty()
197+
)
198+
```
199+
200+
These commands are valid:
201+
202+
```mccmd
203+
/give diamond
204+
/give minecraft:diamond
205+
```
206+
207+
These commands are not valid:
208+
209+
```mccmd
210+
/give
211+
/give diamond 10
212+
```

0 commit comments

Comments
 (0)