An open API service indexing awesome lists of open source software.

https://github.com/okaeripoland/okaeri-commands

Simple command framework with yet powerful features and ability to adapt
https://github.com/okaeripoland/okaeri-commands

acl brigadier bukkit cli commands minecraft paper spigot

Last synced: 6 months ago
JSON representation

Simple command framework with yet powerful features and ability to adapt

Awesome Lists containing this project

README

          

# Okaeri Commands (WIP)

![License](https://img.shields.io/github/license/OkaeriPoland/okaeri-commands)
![Total lines](https://img.shields.io/tokei/lines/github/OkaeriPoland/okaeri-commands)
![Repo size](https://img.shields.io/github/repo-size/OkaeriPoland/okaeri-commands)
![Contributors](https://img.shields.io/github/contributors/OkaeriPoland/okaeri-commands)
[![Discord](https://img.shields.io/discord/589089838200913930)](https://discord.gg/hASN5eX)

Simple command framework with yet powerful features and ability to adapt. Part of the [okaeri-platform](https://github.com/OkaeriPoland/okaeri-platform).

## Example Usage

```java
Commands commands = new OkaeriCommands();
commands.registerCommand(ExampleCommand.class); // built for DI (accepts empty constructor by default)
// commands.registerCommand(new ExampleCommand()); // pass own instance (e.g. with custom constructor parameters)

// call manually
commands.call("cmd hello");

// call and get result
Object result = commands.call("cmd woah");

// TODO
```

## Performance

```console
# single thread performance on ryzen 3600, about 1,000,000 invocations per second
Benchmark Mode Cnt Score Error Units
BenchmarkCommands.command_complex thrpt 5 1109842.766 ± 47168.401 ops/s
BenchmarkCommands.command_medium thrpt 5 1112048.204 ± 46700.652 ops/s
BenchmarkCommands.command_simple thrpt 5 1253307.288 ± 31533.820 ops/s
```

## Example CommandService

```java
// platform specific (bukkit)
// makes all executors async,
// to include/exclude single use @Async/@Sync
@Async
// declare command service using annotation
// aliases can be also specified here
@Command(label = "cmd", description = "Example command service")
public class ExampleCommand implements CommandService {

// cmd
//
// empty pattern represents command without
// arguments (similar to @Default in other frameworks)
//
// no pattern + method name starting with underscore
// is the same as using @Executor(pattern = "")
//
@Executor
public String _def() {
return "called default";
}

// cmd woah
//
// simple commands with no additional effort
// using method name is same as pattern = "woah"
//
// it also works for simple arguments:
// @Executor
// String woah(@Arg String name) -> cmd woah
//
@Executor(description = "Prints woah message")
public String woah() {
return "woah!";
}

// cmd hello
// cmd hello everyone
//
// two patterns are possible in single method, they should
// however match (e.g. have all the same non-static arguments)
//
@Executor(pattern = {"hello", "hello everyone"}, description = "Prints hello message")
public String hello_everyone() {
return "hello!";
}

// cmd hi
// cmd hii
//
// overwrite usage/description with Commands#resolveText()
// available out-of-the-box in OkaeriPoland/okaeri-platform i18n integration
//
@Executor(pattern = {"hi", "hii"}, description = "${command-cmd-hi-description}", usage = "${command-cmd-hi-usage}")
public String hi() {
return "hi!";
}

// cmd hello
//
// required arguments can be specified using ''
// or '*' (recommended with -parameters compiler option, uses in-order param name)
//
@Completion(arg = "name", value = "@allplayers")
@Executor(pattern = "hello *", description = "Prints hello message with name")
public String hello_name(@Arg("name") String name) {
return "hello " + name;
}

// cmd hi [name]
//
// optional arguments can be specified using '[PARAMETER_NAME]'
// or '?' (recommended with -parameters compiler option, uses in-order param name)
//
// optional arguments require param to be an Optional or preferably
// in-house eu.okaeri.commands.service.Option with additional utilities
//
@Executor(pattern = "hi ?", description = "Prints hi message with optional name")
public String hi_name(@Arg("name") Option name) {
return "hi, " + name.getOr("guest");
}

// cmd salute [nameAndSurname]
// cmd salute John Doe
//
// accepts specific number of arguments into one parameter
// example: *:2 same as , ?:2 same as [name:2]
//
// optional arguments require param to be an Optional or preferably
// in-house eu.okaeri.commands.service.Option with additional utilities
//
@Executor(pattern = "salute ?:2" , description = "Prints salute message with optional name and surname")
public String salute_nameAndSurname(@Arg("nameAndSurname") Option name) {
return "salute " + name.getOr("some guest") + "!";
}

// cmd print
// cmd print Some message with unspecified length
//
// accepts all sequential arguments into one parameter
//
@Executor(pattern = "print *..." , description = "Prints system out message")
public void log_message(@Arg("message") String message) {
System.out.println(message);
}

// cmd player set [flag]
//
// mix and match pattern elements, return values to be processed by adapter
// see below for recommended and simplified pattern variant (for -parameters compiler flag)
//
@Executor(pattern = "player set [flag]", description = "Complex command test")
public String complex1(@Arg("player") String name, @Arg("perm") String perm, @Arg("value") String value, @Arg("flag") Option flag) {
return name + " " + perm + " " + value + " " + flag;
}

// recommended usage
//
// mix param types and resolve unknown values by overriding Commands#resolveMissingArgument (e.g. DI)
// preserve param names using javac's -parameters or specify them manually @Arg("name")
//
// specify inline string completions or use previously registered named completion from Commands#registerCompletion
// you can also pass @CompletionData and read it in your custom completion implementation as you like
//
@Completion(arg = "name", value = "@allplayers", data = @CompletionData(name = "limit", value = "10"))
@Completion(arg = "perm", value = {"build", "break", "place"})
@Completion(arg = "value", value = {"allow", "deny"})
@Completion(arg = "flag", value = {"-silent"})
@Executor(pattern = "player * set2 * * ?", description = "Complex command test")
public String complex2(@Arg String name, int huh, @Arg String perm, @RawArgs String[] args, @Arg String value, String randomElement, @Arg Option flag) {
return (">> " + name + " " + perm + " " + value + " " + flag + "\n" + Arrays.toString(args));
}
}
```

## Recommendations

It is highly recommended to use `-parameters` compiler flag for better overall feature support.

### Maven (Java)

```xml



org.apache.maven.plugins
maven-compiler-plugin
3.8.1


-parameters



```

### Maven (Kotlin)

```xml



org.jetbrains.kotlin
kotlin-maven-plugin
${kotlin.version}




-java-parameters



```

### Gradle (Java)

```groovy
compileJava {
options.compilerArgs << '-parameters'
}
```

### Gradle (Kotlin)

```groovy
compileKotlin {
kotlinOptions {
javaParameters = true
}
}
```