Introduction
Imperat is a powerful command dispatching framework, it allows you to create
commands and converts them into the form of multiple data-condensed objects like Command
, CommandUsage
and CommandParameter
These objects are registered/injected into the class Imperat
which handles all information about each command and then dispatches/executes the command requested.
Installation
Imperat is a versatile command dispatching framework designed to work across various platforms with the appropriate implementation. This is will guide you through the installation step by step.
Repository setup
Most builds won't require special repository configuration as Imperat artifacts are hosted on Maven Central. However, if you need to explicitly declare it:
- Maven (pom.xml)
- Gradle (build.gradle)
- Gradle (build.gradle.kts)
<repositories>
<repository>
<id>maven-central</id>
<url>https://repo1.maven.org/maven2/</url>
</repository>
</repositories>
repositories {
mavenCentral()
}
repositories {
mavenCentral()
}
Core Dependency setup
Before adding any platform-specific module, you must include the core Imperat dependency:
- Maven
- Gradle (Groovy)
- Gradle (Kotlin)
<dependency>
<groupId>studio.mevera</groupId>
<artifactId>imperat-core</artifactId>
<version>loading...</version>
</dependency>
implementation 'studio.mevera:imperat-core:loading...'
implementation("studio.mevera:imperat-core:loading...")
Preserve parameter names [OPTIONAL]
Imperat uses parameter names to generate helpful command metadata like usage examples and tab completion suggestions. However, Java doesn't preserve parameter names in the compiled bytecode by default. To enable this feature, you need to configure your build tool to preserve parameter names.
- Maven (pom.xml)
- Gradle (build.gradle)
- Gradle (build.gradle.kts)
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<parameters>true</parameters>
</configuration>
</plugin>
</plugins>
</build>
tasks.withType(JavaCompile).configureEach {
// Preserve parameter names in the bytecode
options.compilerArgs += '-parameters'
}
tasks.withType<JavaCompile> {
// Preserve parameter names in the bytecode
options.compilerArgs.add("-parameters")
}
// optional: if you're using Kotlin
tasks.withType<KotlinJvmCompile> {
compilerOptions {
javaParameters = true
}
}
You wouldn't need to use @Named
Explicitly on method parameters, if you preserved the names of the compiled paramters from your method signatures (Explained how to do that above)
Platform Dependency setup
Choose the platform you are developing for to see specific setup instructions.
- Bukkit
- BungeeCord
- Velocity
- Minestom
- CLI
- Others
Implementation for Bukkit-based Minecraft servers (like Spigot, Paper).
- Imperat Class:
BukkitImperat
- Command Source:
BukkitSource
Installation
- Maven
- Gradle (Groovy)
- Gradle (Kotlin)
<dependency>
<groupId>studio.mevera</groupId>
<artifactId>imperat-bukkit</artifactId>
<version>loading...</version>
</dependency>
implementation 'studio.mevera:imperat-bukkit:loading...'
implementation("studio.mevera:imperat-bukkit:loading...")
You can integrate Imperat with Mojang's Brigadier for enhanced command features (like suggestions and argument types) on compatible servers (Minecraft 1.13+).
Call this applyBrigadier
method while configuring imperat's instance, the method must be the FIRST one to be called in the builder's chain like the following example:
BukkitImperat imperat = BukkitImperat.builder(this)
.applyBrigadier(true)
.build();
Do NOT register your commands within your plugin's plugin.yml
file. Imperat handles registration dynamically.
Implementation for BungeeCord Minecraft proxies.
- Imperat Class:
BungeeImperat
- Command Source:
BungeeSource
Z
Installation
- Maven
- Gradle (Groovy)
- Gradle (Kotlin)
<dependency>
<groupId>studio.mevera</groupId>
<artifactId>imperat-bungee</artifactId>
<version>loading...</version>
</dependency>
implementation 'studio.mevera:imperat-bungee:loading...'
implementation("studio.mevera:imperat-bungee:loading...")
Implementation for Velocity Minecraft proxies.
- Imperat Class:
VelocityImperat
- Command Source:
VelocitySource
Installation
- Maven
- Gradle (Groovy)
- Gradle (Kotlin)
<dependency>
<groupId>studio.mevera</groupId>
<artifactId>imperat-velocity</artifactId>
<version>loading...</version>
</dependency>
implementation 'studio.mevera:imperat-velocity:loading...'
implementation("studio.mevera:imperat-velocity:loading...")
Implementation for Minestom Minecraft servers.
- Imperat Class:
MinestomImperat
- Command Source:
MinestomSource
Installation
- Maven
- Gradle (Groovy)
- Gradle (Kotlin)
<dependency>
<groupId>studio.mevera</groupId>
<artifactId>imperat-minestom</artifactId>
<version>loading...</version>
</dependency>
implementation 'studio.mevera:imperat-minestom:loading...'
implementation("studio.mevera:imperat-minestom:loading...")
Implementation for standalone Command-Line Interface (CLI) applications.
- Imperat Class:
CommandLineImperat
- Command Source:
ConsoleSource
This module provides a basic loop to read input from the console and dispatch commands.
Installation
- Maven
- Gradle (Groovy)
- Gradle (Kotlin)
<dependency>
<groupId>studio.mevera</groupId>
<artifactId>imperat-cli</artifactId>
<version>loading...</version>
</dependency>
implementation 'studio.mevera:imperat-cli:loading...'
implementation("studio.mevera:imperat-cli:loading...")
Support for more platforms is planned for the future.
Imperat's core is platform-agnostic, making it possible to implement support for various environments like Discord bots (JDA, Discord4J), other game servers, or custom applications.
Ensure you use the same version (loading...
) for both imperat-core
and the platform-specific module (e.g., imperat-bukkit
) to avoid compatibility issues.
Initializing Imperat
Frequently asked question: What's a command dispatcher/Imperat ??
Answer: It's the Ultimate class handling all data needed when processing and registering
commands objects (Command
).
You have to create new instance of the imperat.
on the start of your platform by calling YourPlatformImperat#builder
(the method is static) to configure your imperat instance,
then finally end the chain with build
method to return a new instance of YourPlatformImperat
type.
Creation of an instance of your PlatformImperat
depends mainly on which platform
you are using.
Creation of Commands
There's mainly 2 ways of creating commands:
- Annotations Command API
- Classic (Built-in
Command.create(imperat, commandName)
)
(See the Classic Commands page for a full guide and examples of this approach.)
I will be giving an intro to the easier way for creating commands which is the annotations.
Annotated Commands
Creating commands with annotations is easy with 2 steps only:
- Create a class that will represent your command class
- Add unique annotations to it that allows the dispatcher to identify it as a command class
Quick example (Same results as the one above, but with annotations):
@Command("example")
public final class ExampleCommand {
@Usage
public void defaultUsage(BukkitSource source) {
source.reply("This is just an example with no arguments entered");
}
@Usage
public void exampleOneArg(
BukkitSource source,
@Named("firstArg") int firstArg
) {
source.reply("Entered required number= " + firstArg);
}
}
Register your commands
Register your command by calling the method imperat.registerCommand(command)
Note: the method is called from the YourPlatformImperat
instance that you should have created
Here's a quick bukkit example:
public class YourPlugin extends JavaPlugin {
private BukkitImperat imperat;
@Override
public void onEnable() {
//initializing imperat
imperat = BukkitImperat.builder(plugin).build();
//registering the command
imperat.registerCommand(new ExampleCommand());
}
}
Basic Execution Flow
It's essential to know how the basic flow of executing a command using Imperat.
It will help you grasp the concept of Context
Key Execution Steps:
- Parse Command - Convert raw input into structured Context object
- Permission Check - Verify source has permission for root command
- Tree Traversal - Find matching usage path through command tree via
CommandTree#contextMatch()
- Usage Permission - Check permissions for the specific usage found
- Pre-Processing - Execute global and command-specific pre-processor
- Argument Resolution - Convert raw strings into typed values according to the type of their parameters using
ParameterValueAssigner
, then inject the values into theExecutionContext
. - Command Execution - Invoke your actual command method with resolved parameters
- Post-Processing - Execute global and command-specific post-processors
- Result - Return success or failure wrapped in
ExecutionResult
Any step can throw exceptions (PermissionDeniedException
, InvalidSyntaxException
, etc.) which are caught and converted to failed ExecutionResult
objects.
Execution flowchart
Customizing Imperat
If you wanted to register a Context Resolver or a Parameter Type , or even set a Suggestion Resolver for tab-completion in commands, You would have to call some methods while configuring imperat.
With Imperat, you can even register your own sender/source type, check out Source Resolver For a complete detailed guide on this, please check out Customizing Imperat
Big-example:
BukkitImperat imperat = BukkitImperat.builder(plugin)
.parameterType(Arena.class, new ArenaParameterType()) //registering custom type 'Arena'
.parameterType(Kit.class, new KitParameterType()) //registering custom type 'Kit'
.parameterType(DuelMode.class, new DuelModeParameterType()) //registering custom type 'DuelMode'
.sourceResolver(CustomSource.class, CustomSource::new) //registering custom command sender/source type 'CustomSource'
.build();
If you ever wanted to create your own implementation of Imperat
interface,
you will not receive any support and your issue will be instantly ignored/discarded
Tutorials
Check out all the Imperat tutorials here!
🗃️ Basics
7 items
🗃️ Advanced
7 items
🗃️ Examples
4 items
🗃️ Extra
1 item