Skip to content

LorgeN/CrazyCommands

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CrazyCommands

An annotation-driven command framework for Java. The core module is pure JDK + Guava; platform bindings live in their own modules (spigot-1.8.8, terminal, ...).

Modules

Module Purpose JDK target
core Annotation processing, argument parsing, dispatch, sub-commands. No platform deps. 8 (compiled with toolchain 21)
spigot-1.8.8 Bukkit 1.8.8 binding: CoreCommandAdapter, CoreCommandMap injection, BungeeCord help rendering. 8
terminal Pure-JDK REPL binding — drives commands from stdin. 21

Adding a future binding (e.g. paper-1.21/) means copying spigot-1.8.8/ and updating the API coordinates.

Quick start (Spigot)

@Command(name = "ping", desc = "ping pong")
@Alias({"p"})
public class PingCommand {
    @CommandExecutor
    public void run(CommandSender sender) {
        sender.sendMessage("pong");
    }
}
public class MyPlugin extends JavaPlugin {
    @Override
    public void onEnable() {
        Platform platform = SpigotPlatform.create(this);
        CoreCommandMap map = CoreCommandMap.injectCommandMap(platform, getLogger());
        map.registerCommand("myplugin", PingCommand.class);
    }
}

Quick start (terminal REPL)

TerminalRuntime runtime = new TerminalRuntime();
runtime.register(PingCommand.class);
runtime.run();   // reads stdin, dispatches commands

Authoring commands

  • @Command(name, desc) on the class. Optional @Alias({...}) for alternative labels.
  • @CommandExecutor on the method that runs the command. Parameters are resolved from @Arg, @Sender, @Service, or @Context annotations.
  • @Arg(desc, defaultValue?) for positional user arguments. Built-in parsers cover primitives, UUID, java.time.Duration, Enum, and InetAddress. Spigot adds Player, World, ItemStack, Command.
  • Nested @Command-annotated static inner classes become sub-commands automatically. External sub-commands attach via @SubCommand({Other.class}).
  • @TabCompleter on a method matching an executor's signature provides custom completions.

Permissions

Two layers, used independently or together:

  1. String permissions — call sender.hasPermission("foo.bar") from within a check method, or rely on the binding's permission system. The Spigot binding's CoreCommandAdapter.testPermissionSilent calls command.hasAccess(sender).
  2. @AccessChecker methods — annotate any method on the command class that returns boolean and takes a CommandSender / User. The framework runs every @AccessChecker method before dispatch; if any returns false, execution is blocked. applyTo restricts a check to specific sub-command names.
  3. @Permission("foo.bar") — sugar over @AccessChecker. On the class it gates every executor; on a method it gates only that one. Multiple values (@Permission({"a","b"})) are AND'd. Calls sender.hasPermission(...) under the hood.

Building

JAVA_HOME=$(/usr/libexec/java_home -v 17) ./gradlew test

Gradle 8.7 cannot launch under JDK 26, so set JAVA_HOME to a 17/21 JDK. Toolchains for the actual compile (Java 8 for core/spigot-1.8.8, Java 21 for terminal) are auto-provisioned via foojay.

Testing pattern

core and terminal use hand-rolled stubs (FakeCommandSender, TestPlatform) — no Mockito. spigot-1.8.8 uses Mockito 4.11 (Java 8 compatible) for Bukkit interfaces. Bukkit-server-dependent paths (event firing, scheduler) are exercised by integration runs against a live server, not unit tests.

About

Annotation powered command library written in Java

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages