Command
Module required for creating multi-platform commands.
Features
Usage
Supported platforms are: bukkit, bungee, minestom, sponge, velocity
Maven
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 | <repositories>
<repository>
<id>screamingrepo</id>
<url>https://repo.screamingsandals.org/repository/maven-public</url>
</repository>
<repository>
<id>papermc</id>
<url>https://papermc.io/repo/repository/maven-public</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.screamingsandals.lib</groupId>
<artifactId>command-YOUR_PLATFORM</artifactId>
<version>2.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.screamingsandals.lib</groupId>
<artifactId>annotation</artifactId>
<version>2.0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!-- Optional, but recommended (change version to the latest if necessary) -->
<!-- https://mvnrepository.com/artifact/cloud.commandframework/cloud-minecraft-extras -->
<dependency>
<groupId>cloud.commandframework</groupId>
<artifactId>cloud-minecraft-extras</artifactId>
<version>1.5.0</version>
</dependency>
</dependencies>
<!-- Shade plugin configuration and relocation package org.screamingsandals.lib to your own package -->
|
Gradle
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | repositories {
maven {
url 'https://repo.screamingsandals.org/repository/maven-public'
}
maven {
url 'https://papermc.io/repo/repository/maven-public'
}
}
dependencies {
implementation 'org.screamingsandals.lib:command-YOUR_PLATFORM:2.0.1-SNAPSHOT'
annotationProcessor 'org.screamingsandals.lib:annotation:2.0.1-SNAPSHOT'
// Optional, but recommended (change the version to the latest if necessary)
// https://mvnrepository.com/artifact/cloud.commandframework/cloud-minecraft-extras
implementation 'cloud.commandframework:cloud-minecraft-extras:1.5.0'
}
|
Examples
Creating commands with Cloud
Command service
Let's start with creating a service that will construct all of our commands (feel free to copy paste the snippet).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 | @Service(dependsOn = {
CloudConstructor.class
})
public final class CommandService {
@Provider(level = Provider.Level.POST_ENABLE)
public static CommandManager<CommandSenderWrapper> provideCommandManager() {
try {
final CommandManager<CommandSenderWrapper> manager = CloudConstructor.construct(CommandExecutionCoordinator.simpleCoordinator());
// provides a central place for handling common command usage errors
// remove this part if you don't have the cloud-minecraft-extras module
new MinecraftExceptionHandler<CommandSenderWrapper>()
.withDefaultHandlers()
.withHandler(MinecraftExceptionHandler.ExceptionType.NO_PERMISSION, (senderWrapper, e) ->
// Component from Adventure
Component.text("Insufficient permissions!")
)
.withHandler(MinecraftExceptionHandler.ExceptionType.INVALID_SYNTAX, (senderWrapper, e) ->
// Component from Adventure
Component.text("Invalid syntax!")
)
.apply(manager, s -> s);
return manager;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
|
Base command class
Then, create an abstract class that will be extended by the command classes (feel free to copy paste the snippet).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 | @ServiceDependencies(dependsOn = {
CommandService.class // the command service class you created in the last step
})
public abstract class BaseCommand {
protected final @NonNull String name;
protected final @Nullable Permission permission;
protected final boolean allowConsole;
public BaseCommand(String name, Permission permission, boolean allowConsole) {
this.name = name;
this.permission = permission;
this.allowConsole = allowConsole;
}
public @NonNull String getName() {
return name;
}
public @Nullable Permission getPermission() {
return permission;
}
public boolean isConsoleAllowed() {
return allowConsole;
}
protected abstract void construct(Command.Builder<CommandSenderWrapper> commandSenderWrapperBuilder, CommandManager<CommandSenderWrapper> manager);
@OnPostEnable
public void construct(@ProvidedBy(CommandService.class) CommandManager<CommandSenderWrapper> manager) {
// all commands will have the same root, e.g. /someplugin <command name>
Command.Builder<CommandSenderWrapper> builder = manager.commandBuilder("someplugin")
.literal(name);
// or you can have separated commands
// Command.Builder<CommandSenderWrapper> builder = manager.commandBuilder(name);
// checks for permissions
if (permission != null) {
builder = builder.permission(
PredicatePermission.of(SimpleCloudKey.of(name), perm ->
perm.getType() == CommandSenderWrapper.Type.CONSOLE || permission.hasPermission(perm)
)
);
}
// sender will be directly PlayerWrapper, if console is not allowed
if (!allowConsole) {
builder = builder.senderType(PlayerWrapper.class);
}
construct(builder, manager);
}
}
|
Command implementation
Now let's actually implement the command.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 | @Service
public class ExampleCommand extends BaseCommand { // extend the base command class that we created in the last step
public ExampleCommand() {
// command name, command permission (can be null for no permission), is console allowed?
super("examplecommand", null, true);
}
@Override
protected void construct(Command.Builder<CommandSenderWrapper> commandSenderWrapperBuilder, CommandManager<CommandSenderWrapper> manager) {
manager.command(
commandSenderWrapperBuilder
// PlayerWrapper argument
.argument(
manager
.argumentBuilder(String.class, "player")
.withSuggestionsProvider((c, s) ->
Server.getConnectedPlayers().stream().map(PlayerWrapper::getName).toList()
)
)
.handler(commandContext -> {
final Optional<PlayerWrapper> player = PlayerMapper.getPlayer((String) commandContext.get("player"));
if (player.isEmpty()) {
commandContext.getSender().sendMessage("Invalid player specified!");
return;
}
final String senderName = (commandContext.getSender().getType() == CommandSenderWrapper.Type.CONSOLE) ? "CONSOLE" : commandContext.getSender().as(PlayerWrapper.class).getName();
player.orElseThrow().sendMessage("Hello from " + senderName);
})
);
}
}
|
Now register the command implementation class in your plugin's @Init
annotation, and you're done! You've just made yourself a command in the /someplugin examplecommand <player>
format.
Last update:
2022-03-22