# Command Framework
Command Framework 是一个灵活且可扩展的命令框架,专为 Bukkit/Spigot 和 Paper 分叉设计。它简化了在运行时动态创建、注册和管理命令的过程——这是一个在 Bukkit/Spigot 和 Paper 之间存在固有差异和限制的情况下可能具有挑战性的任务。
---
## 概述
`me.croabeast.command` 包提供了一个模块化的命令系统,该系统提供:
- **强大的注册/反注册:**
即使在许多传统 Bukkit/Spigot 实现中会出现中断的 Paper 服务器上,也能无缝地注册和反注册命令,在运行时进行注册和反注册。 Command Framework 解决了 Paper 提出的运行时注册挑战。
- **子命令支持:**
轻松实现带有子命令的命令层级结构。 每个子命令会自动从其父命令继承权限节点,并且可以配置别名。
- **动态制表符补全:**
使用内置的 `TabBuilder` 类构建上下文相关的制表符补全。 您可以定义静态和动态建议,甚至可以使用谓词和函数来根据命令发送者或输入来定制补全。
- **权限处理:**
利用 `Permissible` 和 `DefaultPermissible` 接口进行强大的权限检查。 该框架支持通配符权限,并与 Bukkit 权限系统集成。
- **流畅的命令创建:**
使用 `CommandBuilder` 类进行流畅的 API 以快速创建和配置命令,设置属性,例如覆盖行为、错误处理和自定义制表符补全策略。
- **与 Bukkit/Spigot/Paper 集成:**
Command Framework 构建在 Bukkit 的命令系统之上,与服务器的命令映射和权限系统无缝集成。 它特别针对在运行时命令管理具有挑战性的 Paper 服务器进行了调整。
---
## 关键组件
### Permissible & DefaultPermissible
- **目的:** 定义命令的基本权限要求。
- **用法:** 实现这些接口以确保只有授权用户才能执行命令。
### Executable
- **目的:** 表示执行的命令操作。
- **用法:** 使用 {@code State} 枚举返回结果以指示成功或失败。
### BaseCommand
- **目的:** 建立命令的核心结构,包括其名称、别名和可执行操作。
- **用法:** 使用这些接口作为构建更复杂命令的基础,例如带有子命令和权限的命令。
### Command
- **目的:** 扩展 BaseCommand 和 Completable 以提供具有制表符补全支持的完整命令接口。
- **用法:** 管理子命令和通配符权限。
### SubCommand
- **目的:** 创建自动链接到父命令的子命令。
- **用法:** 轻松扩展命令以获得额外的功能(例如,“reload” 子命令),同时继承权限设置。
### TabBuilder
- **目的:** 构建和管理制表符补全建议。
- **用法:** 使用灵活的过滤和基于谓词的选择来配置特定命令参数的建议。
### BukkitCommand
- **目的:** 与 Bukkit 的命令系统集成的抽象基类。
- **用法:** 扩展此类以获得对命令执行的完全控制,包括在 Paper 服务器上常见的运行时注册/反注册。
### CommandBuilder
- **目的:** 提供用于构建命令的流畅 API。
- **用法:** 使用 CommandBuilder 快速创建具有制表符补全和错误处理的命令,非常适合具有动态运行时命令管理的 Paper 分叉。
---
## Command Framework 为什么能在 Paper 分叉上工作
Bukkit/Spigot 的 Paper 分叉通常会破坏传统的命令注册方法,尤其是在尝试运行时动态注册和反注册时。 Command Framework 考虑到这些挑战而构建:
- **支持运行时更改:**
允许在 Paper 上在运行时注册和反注册命令,而不会出现问题。
- **处理兼容性问题:**
包含一些解决方法和专门的实现(例如,在 `BukkitCommand` 和 `CommandBuilder` 中),以解释 Bukkit/Spigot 和 Paper 之间的命令系统修改。
- **确保稳定性:**
在底层 API 更改时,即使在 Bukkit/Spigot 和 Paper 之间,也能提供强大的错误处理和权限管理。
---
## 用法示例
### 示例 1:通过扩展 BukkitCommand 创建自定义命令
通过扩展 `BukkitCommand` 创建自定义命令:
```java
package com.example.myplugin.command;
import me.croabeast.command.BukkitCommand;
import me.croabeast.command.BaseCommand;
import me.croabeast.command.Executable;
import me.croabeast.command.SubCommand;
import me.croabeast.command.TabBuilder;
import me.croabeast.command.DefaultPermissible;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
public class GreetCommand extends BukkitCommand implements DefaultPermissible {
/**
* 使用指向拥有者的插件的引用构造 GreetCommand。
*
* @param plugin 插件实例。
*/
public GreetCommand(Plugin plugin) {
super(plugin, "greet");
// 设置主命令可执行程序
setExecutable((CommandSender sender, String[] args) -> {
sender.sendMessage("Hello, " + sender.getName() + "!");
return Executable.State.TRUE;
});
// 注册一个别名为“r”的“reload”子命令
SubCommand reloadSub = new SubCommand(this, "reload;r");
reloadSub.setExecutable((sender, args) -> {
// 在此处放置重新加载逻辑
sender.sendMessage("GreetCommand 配置已重新加载。");
return Executable.State.TRUE;
});
registerSubCommand(reloadSub);
}
/**
* 提供命令的自定义制表符补全。
*
* @param sender 命令发送者。
* @param alias 使用的命令别名。
* @param args 传递给命令的参数。
* @return 建议列表。
*/
@NotNull
@Override
public java.util.List tabComplete(@NotNull CommandSender sender, @NotNull String alias, String[] args) {
// 为建议创建一个简单的 TabBuilder
TabBuilder builder = new TabBuilder();
if (args.length == 1) {
// 在未指定子命令时建议“hello”和“hi”
builder.addArgument(1, "hello");
builder.addArgument(1, "hi");
} else if (args.length > 1) {
// 可选地,为进一步的参数提供其他建议
builder.addArgument(args.length, "option1");
builder.addArgument(args.length, "option2");
}
return builder.build(sender, args);
}
}
```
#### 注册命令
在插件的主要类(扩展 `JavaPlugin`)中注册命令:
```java
package com.example.myplugin;
import com.example.myplugin.command.GreetCommand;
import org.bukkit.plugin.java.JavaPlugin;
public class MyPlugin extends JavaPlugin {
@Override
public void onEnable() {
// 创建 GreetCommand 的实例并注册它
GreetCommand greetCommand = new GreetCommand(this);
greetCommand.register();
// 要稍后取消注册命令,请调用:
// greetCommand.unregister();
}
}
```
### 示例 2:使用 CommandBuilder 创建命令
或者,使用 `CommandBuilder` 提供的流畅 API:
```java
package com.example.myplugin;
import com.example.myplugin.command.CommandBuilder;
import com.example.myplugin.command.Executable;
import com.example.myplugin.command.TabBuilder;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.Arrays;
public class MyPlugin extends JavaPlugin {
@Override
public void onEnable() {
// 使用 CommandBuilder 创建 "example" 命令
CommandBuilder builder = CommandBuilder.from(this, "example")
.setOverriding(true)
.setCompletions((sender, args) -> Arrays.asList("optionA", "optionB", "optionC"))
.setCompletionBuilder(new TabBuilder().addArgument(1, "optionA"))
.apply(cmd -> cmd.setExecutable((sender, args) -> {
sender.sendMessage("使用以下参数执行示例命令: " + String.join(" ", args));
return Executable.State.TRUE;
}));
// 在运行时注册命令(在 Paper 上也能无缝工作)
builder.register();
// 稍后取消注册:
// builder.unregister();
}
}
```
---
## Maven / Gradle 安装
要将 Command Framework 包含到项目中,请将以下仓库和依赖项添加到构建配置中。 将 `${version}` 替换为所需的版本标记。
### Maven
将仓库和依赖项添加到您的 `pom.xml`:
```xml
croabeast-repo
https://croabeast.github.io/repo/
me.croabeast
CommandFramework
${version}
compile
```
### Gradle
将仓库和依赖项添加到您的 `build.gradle`:
```groovy
repositories {
maven {
url "https://croabeast.github.io/repo/"
}
}
dependencies {
implementation "me.croabeast:CommandFramework:${version}"
}
```
将 `${version}` 替换为适当的模块版本。
---
## 结论
**Command Framework**(`me.croabeast.command` 包中的类集合)旨在简化 Minecraft 插件的命令开发,尤其是在 Paper 分叉上,运行时注册可能具有挑战性。 其模块化设计、对子命令的支持、动态制表符补全以及强大的权限检查使其成为现代插件开发的理想选择。
借助 Command Framework,您可以构建复杂的命令层级结构、提供上下文相关的制表符补全以及管理运行时命令的注册和反注册,从而在最新版本的 Paper 服务器上确保兼容性和稳定性。
祝您编码愉快,并享受使用 Command Framework 构建强大命令的乐趣!
— *CroaBeast*