{"id":22733261,"url":"https://github.com/ultikits/ultikits-command","last_synced_at":"2026-02-03T07:31:28.172Z","repository":{"id":251727461,"uuid":"838264845","full_name":"UltiKits/UltiKits-Command","owner":"UltiKits","description":"This project is a module of UltiKits, provides a better way to develop spigot commands.","archived":false,"fork":false,"pushed_at":"2024-11-03T15:05:04.000Z","size":53,"stargazers_count":1,"open_issues_count":0,"forks_count":2,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-07-05T22:41:41.191Z","etag":null,"topics":["minecraft","minecraft-plugin","minecraft-plugin-development","spigot","spigot-lib"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/UltiKits.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-08-05T09:37:22.000Z","updated_at":"2024-11-03T15:05:08.000Z","dependencies_parsed_at":"2024-08-05T11:26:42.872Z","dependency_job_id":"b86e2b47-f04b-4ad8-a9ec-d2d126667120","html_url":"https://github.com/UltiKits/UltiKits-Command","commit_stats":null,"previous_names":["ultikits/ultikits-command"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/UltiKits/UltiKits-Command","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UltiKits%2FUltiKits-Command","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UltiKits%2FUltiKits-Command/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UltiKits%2FUltiKits-Command/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UltiKits%2FUltiKits-Command/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/UltiKits","download_url":"https://codeload.github.com/UltiKits/UltiKits-Command/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UltiKits%2FUltiKits-Command/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29037469,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-03T06:39:36.383Z","status":"ssl_error","status_checked_at":"2026-02-03T06:39:32.787Z","response_time":96,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["minecraft","minecraft-plugin","minecraft-plugin-development","spigot","spigot-lib"],"created_at":"2024-12-10T20:13:28.223Z","updated_at":"2026-02-03T07:31:28.151Z","avatar_url":"https://github.com/UltiKits.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ⌨️ UltiTools-Command 🛠️\n\n[![Maven Central](https://img.shields.io/maven-central/v/com.ultikits.lib/UltiKits-Command?label=Maven%20Central)](https://search.maven.org/artifact/com.ultikits.lib/UltiKits-Command)\n[![GitHub](https://img.shields.io/github/license/UltiKits/UltiKits-Command)](https://github.com/UltiKits/UltiKits-Command?tab=MIT-1-ov-file#readme)\n[![GitHub](https://img.shields.io/github/issues/UltiKits/UltiKits-Command)](https://github.com/UltiKits/UltiKits-Command/issues)\n[![CodeFactor](https://www.codefactor.io/repository/github/ultikits/ultikits-command/badge)](https://www.codefactor.io/repository/github/ultikits/ultikits-command)\n[![GitHub](https://img.shields.io/github/forks/UltiKits/UltiKits-Command)](https://github.com/UltiKits/UltiKits-Command/network/members)\n[![GitHub](https://img.shields.io/github/stars/UltiKits/UltiKits-Command)](https://github.com/UltiKits/UltiKits-Command/stargazers)\n\nIn traditional Bukkit plugin development, we usually use the `CommandExecutor` interface of Bukkit to handle commands.\n\nHowever, in some cases, we need to determine whether the sender of the command is a player, whether it has certain\npermissions, and determine the parameters, etc.\n\nIf a plugin has multiple commands, then these judgment logic will be repeated in the processing method of each command,\nsuch code is very redundant.\n\nIn addition, we may also need to handle command errors, output help information, etc.\n\nUltiTools-Command offers a more concise way to handle commands by encapsulating the native `CommandExecutor` interface.\n\n# Quick start\n\n## Installation\n\n### Maven\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.ultikits.lib\u003c/groupId\u003e\n    \u003cartifactId\u003eUltiKits-Command\u003c/artifactId\u003e\n    \u003cversion\u003e1.0.2\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n### Gradle\n\n```groovy\ndependencies {\n    implementation 'com.ultikits.lib:UltiKits-Command:1.0.2'\n}\n```\n\n## Usage\n\nAssuming that your plugin has a function to set the teleport point, you want the player to enter a command with the\nteleport point name, to set up a teleport point.\n\nThen this command should look like this: `/point add [name]`\n\nIf you use the traditional method, you need to judge the legality of the parameter input, the sender and permissions,\netc. If there are other functions, you also need to write a lot of `switch ... case` and `if ... else` statements, crazy\nnesting.\n\nHowever, with UltiTools-Command, you only need to write the main logic, and the rest will be handled automatically.\n\nFirst, you need to create an executor class that inherits `AbstractCommandExecutor`.\n\n```java\nimport com.ultikits.lib.command.AbstractCommendExecutor;\nimport com.ultikits.lib.annotations.command.CmdExecutor;\nimport com.ultikits.lib.annotations.command.CmdTarget;\nimport org.bukkit.command.CommandSender;\n\n// Command limits executor\n@CmdTarget(CmdTarget.CmdTargetType.PLAYER)\n@CmdExecutor(\n        // Command permission (optional)\n        permission = \"ultikits.example.all\",\n        // Command description (optional)\n        description = \"Test Command\",\n        // Command alias\n        alias = {\"point\"},\n        // Whether to register manually (optional)\n        manualRegister = false,\n        // Whether to require OP permission (optional)\n        requireOp = false\n)\npublic class PointCommand extends AbstractCommendExecutor {\n\n    @Override\n    protected void handleHelp(CommandSender sender) {\n        // Send help message to command sender\n    }\n}\n```\n\nThen create a method named `addPoint` and add the parameters you want:\n\n```java\npublic void addPoint(@CmdSender Player player, String name) {\n    // Your code\n}\n```\n\nYes, each of your functions uses a separate function without extra judgment.\n\nThen, you need to add the `@CmdMapping` annotation to match your method according to the input\ncommand:\n\n```java\n\n@CmdMapping(format = \"add \u003cname\u003e\")\npublic void addPoint(@CmdSender Player player, String name) {\n    // Your code\n}\n```\n\nFinally, use `@CmdParam` to bind command parameters:\n\n```java\n\n@CmdMapping(format = \"add \u003cname\u003e\")\npublic void addPoint(@CmdSender Player player, @CmdParam(\"name\") String name) {\n    // Your code\n}\n``` \n\nFull code:\n    \n```java\nimport com.ultikits.lib.command.AbstractCommendExecutor;\nimport com.ultikits.lib.annotations.command.CmdExecutor;\nimport com.ultikits.lib.annotations.command.CmdTarget;\nimport org.bukkit.command.CommandSender;\n\n// Command limits executor\n@CmdTarget(CmdTarget.CmdTargetType.PLAYER)\n@CmdExecutor(\n        // Command permission (optional)\n        permission = \"ultikits.example.all\",\n        // Command description (optional)\n        description = \"Test Command\",\n        // Command alias\n        alias = {\"point\"},\n        // Whether to register manually (optional)\n        manualRegister = false,\n        // Whether to require OP permission (optional)\n        requireOp = false\n)\npublic class PointCommand extends AbstractCommendExecutor {\n\n    @CmdMapping(format = \"add \u003cname\u003e\")\n    public void addPoint(@CmdSender Player player, @CmdParam(\"name\") String name) {\n        // Your code\n    }\n\n    @Override\n    protected void handleHelp(CommandSender sender) {\n        // Send help message to command sender\n    }\n}\n```\n\nNow, you can register the command executor in your main class by using ```CommandManager``` to complete all the work.\n\n```java\nimport com.ultikits.lib.command.CommandManager;\nimport org.bukkit.plugin.java.JavaPlugin;\n\npublic class PluginMain extends JavaPlugin {\n\n    @Override\n    public void onEnable() {\n        // Register command executor\n        CommandManager.registerCommand(new PointCommand());\n    }\n}\n```\n\nYeah! You can now use the `/point add [name]` command in the game.\n\n### Tab completion\n\nNeed Tab suggestion for each command parameter, but don't want to write a lot of code?\n\nIt is a disaster to generate a completion list by judging the length of each command and the previous parameters.\n\nNow you only need to write a method for each parameter to return a completion list! This method can be reused, and all\nthe complicated parameter quantity judgments are left to UltiTools to complete.\n\nWhat you need to do is just add the `suggest` attribute in the `@CmdParam` annotation and specify a method name.\n\n```java\n\n@CmdMapping(format = \"add \u003cname\u003e\")\npublic void addPoint(@CmdSender Player player, @CmdParam(value = \"name\", suggest = \"listName\") String name) {\n    // Your code\n}\n\npublic List\u003cString\u003e listName(Player player, Command command, String[] args) {\n    // Your code\n}\n```\n\nUltiTools will first search for matching method names in the current class and try to call this method.\n\nYour method can contain up to three parameters, corresponding to the types `Player`, `Command` and `String[]`. You can\nchoose any amount or order of parameters, but the type can only be these three types, one parameter for each type.\n\n`Player` represents the player who sent the command, `Command` represents the current command, and `String[]` represents\nthe current parameters of the current command.\n\nYour method needs to return a value of type `List\u003cString\u003e`, and UltiTools will return this value as a completion list to\nthe player.\n\nIf you just want to return a simple prompt string, then you only need to write the string you want in the `suggest`\nfield. The string here also supports internationalization.\n\n```java\n\n@CmdMapping(format = \"add \u003cname\u003e\")\npublic void addPoint(@CmdSender Player player,\n                     @CmdParam(value = \"name\", suggest = \"[name]\") String name) {\n    // Your code\n}\n\n```\n\nIf you are not satisfied with the completion list generated by UltiTools, you can override the `suggest` method to\ngenerate the completion list yourself.\n\n```java\n\n@Override\nprotected List\u003cString\u003e suggest(Player player, Command command, String[] strings) {\n    // Your code\n}\n```\n\n#### @CmdSuggest\n\nIf you want a completion method to be shared with other command classes, you can create a class and write methods which\nyou want to reuse in other class.\n\nAdd the `@CmdSuggest` annotation to the class which need to use suggestion method, and specify the suggestion class.\n\n```java\n\n@CmdSuggest({PointSuggest.class})\npublic class PointCommand extends AbstractCommandExecutor {\n\n    @CmdMapping(format = \"add \u003cname\u003e\")\n    public void addPoint(@CmdSender Player player, @CmdParam(value = \"name\", suggest = \"listName\") String name) {\n        // Your code\n    }\n}\n```\n\n```java\npublic class PointSuggest {\n    public List\u003cString\u003e listName(Player player, Command command, String[] args) {\n        // Your code\n    }\n}\n```\n\n### Parameters\n\n#### Command without Parameters\n\nIf a command does not require any parameters, simply leave the `format` value empty.\n\n```java\n@CmdMapping(format=\"\")\n```\n\nThis type of command can have at most one occurrence.\n\n#### Variable Parameters\n\nFor the last parameter in a method, you can use an array type by adding `...` to the last parameter in the `format`. Here's an example:\n\n```java\n@CmdMapping(format = \"add \u003cname...\u003e\")\npublic void addPoint(@CmdSender Player player, @CmdParam(value = \"name...\") String[] name) {\n    // Your code\n}\n```\n\nIn this example, when a player enters `/somecmd add aa bb cc`, the `name` will be `['aa', 'bb', 'cc']`.\n\n#### Type Parsing\n\nBefore passing parameters to a method, UltiTools converts the command's variable parameters based on the types required by the method.\n\nAll parsers are stored in a map called `parsers`, and you can use `getParser()` to access it.\n\nFor some types, `AbstractCommandExecutor` provides default parsers (including base types and arrays):\n\n- String (Java built-in)\n- Float (Java built-in)\n- Double (Java built-in)\n- Integer (Java built-in)\n- Short (Java built-in)\n- Byte (Java built-in)\n- Long (Java built-in)\n- OfflinePlayer (Bukkit API)\n- Player (Bukkit API)\n- Material (Bukkit API)\n- UUID (Java built-in)\n- Boolean (Java built-in)\n\nIf you want to use a custom parser, you need to create a method that can be used with the `Function` interface.\n\nSupported parser types are `\u003cString, ?\u003e`, meaning the method has exactly one parameter of type `String` and returns a value of any type.\n\n```java\npublic static SomeType toSomeType(String s) {\n  //do something...\n  return result;\n}\n```\n\nThen, add the converter in the constructor:\n\n```java\npublic SomeCommand() {\n  super();\n  getParsers().put(Arrays.asList(SomeType.class, SomeType[].class), SomeType::toSomeType);\n}\n```\n\nMake sure to add the array type as well; otherwise, variable parameters won't be parsed.\n\n### Permission\n\n#### Method permission\n\nIf you need to specify permissions for a method, you need to add the `permission` attribute in the `@CmdMapping`\nannotation.\n\n```java\n@CmdMapping(..., permission = \"point.set.add\")\n```\n\nThe permissions specified in `@CmdExecutor` will override any permission set in `@CmdMapping`.\n\n#### OP Required\n\nIf you want all methods to be executed by OP only, you need to set the `requireOp` attribute in `@CmdExecutor` to `true`\n\n```java\n@CmdExecutor(..., requireOp = true)\n```\n\nIf you want a method to be executed by OP only, you need to set the `requireOp` attribute in `@CmdMapping` to `true`\n\n```java\n@CmdMapping(..., requireOp = true)\n```\n\n### Sender Limitation\n\nIf you want to specify the sender for all methods, you need to add the `@CmdTarget` annotation in front of your\nclass.\n\nIf you want to specify the sender for a method, just add it in front of the method.\n\n```java\n@CmdTarget(CmdTarget.CmdTargetType.BOTH)\n```\n\nIf the sender is specified in both the class and the method, both must be met.\n\n### Asynchronous Execution\n\nIf a command needs to execute a task that takes a long time, you need to add `@RunAsync` in front of the corresponding\n\n```java\n\n@CmdMapping(format = \"list\")\n@RunAsync\npublic void listPoint(@CmdSender Player player) {\n    //do query\n}\n```\n\nThis will create a new asynchronous thread to execute the method, avoiding blocking in the Bukkit main thread.\n\nSince the Bukkit API does not allow asynchronous calls, if you need to call the Bukkit API, you need to create a\nsynchronous task:\n\n```java\n\n@CmdMapping(format = \"list\")\n@RunAsync\npublic void listPoint(@CmdSender Player player) {\n    //do query\n    new BukkitRunnable() {\n        @Override\n        public void run() {\n            //call bukkit api\n        }\n    }.runTask(PluginMain.getInstance());\n}\n```\n\n### Command cooldown\n\nIf you don't want a command to be executed in large quantities and consume server resources, then you can add\n`@CmdCD` in front of the corresponding method:\n\n```java\n@CmdCD(60)\n```\n\nParameter type is integer, in second.\n\nIf the command is executed before the cooldown ends, the message `Frequent operations, please try again later` will be\nsent.\n\nThis restriction only takes effect on **players**.\n\n### Execution lock\n\nIf you want a command to be executed only one by one, you can add `@UsageLimit` in front of the corresponding method:\n\n```java\n@UsageLimit(ContainConsole = false, value = LimitType.SENDER)\n```\n\n`ContainConsole` is whether the restriction is applied to the console, and `value` is the restriction type.\n\nAvailable types are:\n\n- `LimitType.SENDER` limits that each sender can only have one command of this type executed at a time\n- `LimitType.ALL` limits that only one command of this type can be executed in the whole server\n- `LimitType.NONE` no limit\n\nUnder the `LimitType.SENDER` strategy, the player will receive a prompt: `Please wait for last Command Processing!`\n\nUnder the `LimitType.ALL` strategy, the player will receive a\nprompt: `Please wait for last Command Processing which sent by other players!`\n\n### Help Message\n\nAll three classes above provide a `sendHelpMessage` method for sending help messages to players or consoles.\n\n```java\nsendHelpMessage(CommandSender sender) {\n    // send help message\n}\n```\n\nWhen sending the `/somecommand help` command, this method will be called.\n\n### Error Message\n\nYou may find that the `onCommand` method of the three classes above returns a `boolean` type value.\n\nIt is the same as the native `CommandExecutor` interface, this value is used to indicate whether the command was\nexecuted successfully.\n\nWhen the command execution returns `false`, the command sender will be automatically prompted with an error message.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fultikits%2Fultikits-command","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fultikits%2Fultikits-command","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fultikits%2Fultikits-command/lists"}