From 8927c10d7a7f681153c6ebd1b81433a8908c46e9 Mon Sep 17 00:00:00 2001 From: wisdommen <41609381+wisdommen@users.noreply.github.com> Date: Sat, 20 Jan 2024 22:38:45 +1100 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E4=BA=86=E6=96=87=E6=A1=A3?= =?UTF-8?q?=EF=BC=8C=E9=80=82=E9=85=8DUltiTools-API=206.0.6=E7=89=88?= =?UTF-8?q?=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vitepress/config.mts | 4 + docs/guide/advanced/auto-register.md | 79 ++++++++++----- docs/guide/advanced/gui.md | 79 +++++++++++++++ docs/guide/advanced/ioc-container.md | 5 +- docs/guide/essentials/cmd-executor.md | 126 ++++++++++++++++++------ docs/guide/essentials/config-file.md | 11 ++- docs/guide/essentials/data-storage.md | 8 +- docs/guide/essentials/event-listener.md | 2 +- docs/guide/introduction.md | 6 +- docs/guide/quick-start.md | 126 +++++++++++++----------- 10 files changed, 327 insertions(+), 119 deletions(-) create mode 100644 docs/guide/advanced/gui.md diff --git a/.vitepress/config.mts b/.vitepress/config.mts index 3146675..071c982 100644 --- a/.vitepress/config.mts +++ b/.vitepress/config.mts @@ -229,6 +229,10 @@ export default withPwa( { text: 'IOC容器', link: 'advanced/ioc-container' + }, + { + text: 'GUI界面', + link: 'advanced/gui' } ] }, diff --git a/docs/guide/advanced/auto-register.md b/docs/guide/advanced/auto-register.md index 4764b01..d2a4c48 100644 --- a/docs/guide/advanced/auto-register.md +++ b/docs/guide/advanced/auto-register.md @@ -2,8 +2,59 @@ 这篇文章将会教你如何使用注解让UltiTools帮你完成一系列的、繁琐的注册任务。 +## @UtiToolsModule 注解 + +在继承了 `UltiToolsPlugin` 的类的上方添加这一注解。 + +此注解仅可用于UltiTools模块主类,用于简化注解配置。 + +此注解包含了自动扫描并注册此类包名下的命令,监听器和配置文件。 + +如果你想要手动注册命令或监听器,可以将 `eventListener` 设置为 `false` 或 `cmdExecutor` 设置为 `false`。 + +```java +import com.ultikits.ultitools.abstracts.UltiToolsPlugin; +import com.ultikits.ultitools.annotations.UltiToolsModule; +import lombok.Getter; +import org.springframework.beans.factory.annotation.Autowired; + +@UltiToolsModule( + // 是否扫描并注册监听器 + eventListener = true, + // 是否扫描并注册命令 + cmdExecutor = true, + // 是否扫描并注册配置文件 + config = true, + // 扫描包名 + scanBasePackages = {"com.test.plugin"}, + // 制定特定的扫描类 + scanBasePackageClasses = {}, + // 多语言支持 + i18n = {"zh", "en"} +) +public class PluginMain extends UltiToolsPlugin { + + @Getter + private static PluginMain pluginMain; + + public PluginMain() { + super(); + pluginMain = this; + } + + @Override + public boolean registerSelf() { + return true; + } + + ... +} +``` + ## @EnableAutoRegister 注解 +`@UtiToolsModule` 内包含了 `@EnableAutoRegister` 注解,在不适合使用 `@UtiToolsModule` 的情况下,你可以使用 `@EnableAutoRegister` 注解,比如你想在你自己的插件中使用 UltiTools 的自动注册。 + 在继承了 `UltiToolsPlugin` 的类的上方添加这一注解,UltiTools 在加载你的模块时会根据你的配置进行自动注册: ```java @@ -25,16 +76,8 @@ public class UltiToolsConnector extends UltiToolsPlugin { public boolean registerSelf() throws IOException { return true; } - - @Override - public void unregisterSelf() { - - } - - @Override - public void reloadSelf() { - super.reloadSelf(); - } + + ... } ``` @@ -56,26 +99,18 @@ public class UltiToolsConnector extends UltiToolsPlugin { public boolean registerSelf() throws IOException { return true; } - - @Override - public void unregisterSelf() { - - } - - @Override - public void reloadSelf() { - super.reloadSelf(); - } + + ... } ``` ## @CmdExecutor 注解 -带有此注解的 `CommandExecutor` 类在自动注册启用的情况下被自动注册 +带有此注解的继承 `AbstractCommandExecutor` 的类在自动扫描注册命令启用的情况下被自动注册 详情参见 [命令执行器](/guide/essentials/cmd-executor) ## @EventListener 注解 -带有此注解的 `Listener` 类在自动注册启用的情况下被自动注册 +带有此注解的实现 `Listener` 的类在自动扫描注册监听器启用的情况下被自动注册 详情参见 [事件监听器](/guide/essentials/event-listener) diff --git a/docs/guide/advanced/gui.md b/docs/guide/advanced/gui.md new file mode 100644 index 0000000..c89908c --- /dev/null +++ b/docs/guide/advanced/gui.md @@ -0,0 +1,79 @@ +# GUI 编写 + +UltiTools 提供了obliviate-invs的 GUI API,您可以轻松地开发出 GUI 插件,而无需担心 GUI 的实现细节。 + +感谢Hamza Coşkun的开源项目 [obliviate-invs](https://github.com/hamza-cskn/obliviate-invs) + +UltiTools-API 目前提供了两个预制的 GUI 界面: + +分页界面 `PagingPage` 和 确认界面 `OkCancelPage` + +## 创建一个 GUI + +在这里我使用 `PagingPage` 作为例子。 + +首先,您需要创建一个 GUI 类,继承 `PagingPage` 类。 + +```java +public class WarpGui extends PagingPage { + // 新建一个 WarpService 实例(并不重要,只是演示) + private final WarpService warpService = new WarpService(); + + // 你需要重写一个构造函数,用于传递参数,这里的Player参数是必须的 + public WarpGui(Player player) { + super( + // 打开GUI的玩家 + player, + // GUI的ID + "Warp-list", + // GUI的标题 + Component.text(BasicFunctions.getInstance().i18n("传送点列表")) + .color(TextColor.color(0xFF00A6)), + // GUI的行数 + 3 + ); + } + + // 重写这个方法,用于设置GUI的内容 + @Override + public List setAllItems() { + List icons = new ArrayList<>(); + List allWarps = warpService.getAllWarps(); + for (WarpData warpData : allWarps) { + Location location = WarpService.toLocation(warpData.getLocation()); + Icon icon = new Icon(UltiTools.getInstance().getVersionWrapper().getEndEye()); + TextComponent textComponent = Component.text(warpData.getName()).color(TextColor.color(0xFF00A6)); + icon.toComp().setName(textComponent); + String world = String.format(ChatColor.YELLOW + BasicFunctions.getInstance().i18n("所在世界 %s"), location.getWorld().getName()); + String xyz = String.format(ChatColor.GRAY + "X: %.2f Y: %.2f Z: %.2f", location.getX(), location.getY(), location.getZ()); + icon.setLore(world, xyz); + // 按钮点击事件 + icon.onClick((e) -> { + player.performCommand("warp tp " + warpData.getName()); + player.closeInventory(); + }); + icons.add(icon); + } + return icons; + } +} +``` + +然后在你的命令执行器中调用这个 GUI 类即可。 + +```java + +@CmdTarget(CmdTarget.CmdTargetType.PLAYER) +@CmdExecutor(alias = {"warp"}, manualRegister = true, permission = "ultikits.tools.command.warp", description = "传送点功能") +public class WarpCommands extends AbstractCommendExecutor { + + @CmdMapping(format = "list") + public void listWarps(@CmdSender Player player) { + WarpGui warpGui = new WarpGui(player); + warpGui.open(); + } + +} +``` + +更多的GUI API用法请参考 [obliviate-invs Wiki](https://github.com/hamza-cskn/obliviate-invs/wiki) diff --git a/docs/guide/advanced/ioc-container.md b/docs/guide/advanced/ioc-container.md index ada1ef0..769a4d2 100644 --- a/docs/guide/advanced/ioc-container.md +++ b/docs/guide/advanced/ioc-container.md @@ -42,10 +42,7 @@ import com.ultikits.ultitools.annotations.I18n; import org.springframework.context.annotation.ComponentScan; import org.springframework.stereotype.Component; -@Component -@ComponentScan -@I18n({"zh", "en"}) -@EnableAutoRegister +@UltToolsModule public class BasicFunctions extends UltiToolsPlugin { @Override diff --git a/docs/guide/essentials/cmd-executor.md b/docs/guide/essentials/cmd-executor.md index 1d31267..a9e0107 100644 --- a/docs/guide/essentials/cmd-executor.md +++ b/docs/guide/essentials/cmd-executor.md @@ -20,20 +20,25 @@ import com.ultikits.ultitools.annotations.command.CmdExecutor; import com.ultikits.ultitools.annotations.command.CmdTarget; import org.bukkit.command.CommandSender; +// 命令限制执行者为玩家和控制台 @CmdTarget(CmdTarget.CmdTargetType.BOTH) @CmdExecutor( - permission = "ultikits.example.all", - description = "测试指令", - alias = {"test","ts"} + // 命令权限(可选) + permission = "ultikits.example.all", + // 命令描述(可选) + description = "测试指令", + // 命令别称 + alias = {"test","ts"}, + // 是否手动注册(可选) + manualRegister = false, + // 是否需要OP权限(可选) + requireOp = false ) public class ExampleCommand extends AbstractCommendExecutor { @Override protected void handleHelp(CommandSender sender) { - sender.sendMessage("=== 测试指令 ===\n" + - "/test 测试指令\n" + - "/ts 测试指令\n" + - "==========="); + // 向命令发送者发送帮助信息 } } ``` @@ -44,6 +49,8 @@ public class ExampleCommand extends AbstractCommendExecutor { 和spigot开发一样,有了执行器,就需要去注册它。我们可以在 `registerSelf` 方法中使用 `getCommandManager().register()` 方法来注册命令。 +如果你的模块存在大量的命令执行器而不想手动注册,也可以使用 UltiTools 提供的自动注册功能,详情可以查看[这篇文章](/guide/advanced/auto-register)。 + ```java import com.ultikits.plugin.ultikitsapiexample.context.ContextConfig; import com.ultikits.ultitools.abstracts.UltiToolsPlugin; @@ -63,12 +70,7 @@ public class UltiToolsConnector extends UltiToolsPlugin { @Override public boolean registerSelf() throws IOException { - getCommandManager().register( - new ExampleCommand(), //命令执行器 - "permission.test", //命令权限 - "示例功能", //命令描述 - "test" //命令 - ); + getCommandManager().register(this, ExampleCommand.class); return true; } @@ -85,22 +87,6 @@ public class UltiToolsConnector extends UltiToolsPlugin { ``` -当然你也可以使用不添加后面三个参数,前提是在你的执行器类添加 `@CmdExecutor` 注解: - -```java -@CmdExecutor( - permission = "ultikits.example.all", - description = "测试指令", - alias = {"test","ts"} -) -``` - -其中 `description` 为命令描述,`alias` 为命令别称(键入指令时的根命令,支持多个),`permission` 为命令权限。 - -如果你的模块存在大量的命令执行器而不想手动注册,也可以使用 UltiTools 提供的自动注册功能,详情可以查看[这篇文章](/guide/advanced/auto-register)。 - -使用传统的命令执行器的编写方式仅需使用上述参数即可,使用基于映射的命令编写方式将会更加详细地介绍这个注解。 - ## 基于映射的命令执行器 ### 快速上手 @@ -110,7 +96,7 @@ public class UltiToolsConnector extends UltiToolsPlugin { 那么这个命令应该会长这样:`/point add name` 如果是使用传统的方法,你需要判断参数输入的合法性,发送者以及权限等,如果还有其他功能,你还需要编写一大堆的 `switch ... case` 和 `if ... else` 语句,疯狂嵌套。 -使得代码可读性变差,提高了维护的难度。~~(还容易烧干你的CPU)~~ +使得代码可读性变差,提高了维护的难度。~~(还容易烧干你的脑子)~~ 使用这个方法,你只需要编写最主要的逻辑即可,剩下的交给 UltiTools。 @@ -148,6 +134,86 @@ public void addPoint(@CmdSender Player player, @CmdParam("name") String name) { 至此,你只需要和传统方式一样注册命令执行器即可完成所有工作。 +### 参数Tab提示补全 + +每次写完一个命令之后希望给自己的命令添加Tab提示补全,但是又不想写一大堆的代码? + +为Tab补全绞尽脑汁判断每个命令的长度和之前的参数来生成一个补全List,这非常容易把人累死。 + +现在你只需要简单的为每一个参数写一个方法返回补全List即可!这个方法可以被反复利用,所有繁杂的参数数量判断都交给 UltiTools 来完成。 + +你所需要做的只是在 `@CmdParam` 注解中添加 `suggest` 属性,指定一个方法名即可。 + + +```java +@CmdMapping(format = "add ") +public void addPoint(@CmdSender Player player, @CmdParam(value = "name", suggest="listName") String name) { + ... +} + +public List listName(Player player, Command command, String[] args) { + ... +} +``` + +UltiTools会首先在当前类中搜索匹配的方法名,并尝试调用此方法。 + +你的方法可以包含最多三个参数,分别对应的类型是 `Player`, `Command` 和 `String[]`,你可以选择任意的参数数量和顺序,但是类型只能是这三种,每种类型一个参数。 + +`Player` 代表了发送此命令的玩家,`Command` 代表了当前的命令,`String[]` 代表了当前命令的参数。 + +你的方法需要返回一个 `List` 类型的值,UltiTools 将会将此值作为补全列表返回给玩家。 + +::: tip + +如果你仅仅只是想返回一个简单的提示字符串,那么你只需要在 `suggest` 字段中写上你想要的字符串即可。这里的字符串也支持i18n国际化。 + +```java +@CmdMapping(format = "add ") +public void addPoint(@CmdSender Player player, + @CmdParam(value = "name", suggest="[名称]") String name) { + ... +} + +``` +::: + +::: tip + +如果你对UltiTools生成的补全列表不满意,你可以重写 `suggest` 方法,自己生成补全列表。 + +```java +@Override +protected List suggest(Player player, Command command, String[] strings) { + ... +} +``` +::: + +#### @CmdSuggest 注解 + +如果你希望你的这个补全方法与其他命令类共享,那么你可以创建一个类,将想要复用的方法写在此类下。 + +在需要使用此类中的方法的类上添加 `@CmdSuggest` 注解,指定此类的类名即可。 + +```java +@CmdSuggest({PointSuggest.class}) +public class PointCommand extends AbstractCommandExecutor { + + @CmdMapping(format = "add ") + public void addPoint(@CmdSender Player player, @CmdParam(value = "name", suggest="listName") String name) { + ... + } +} +``` +```java +public class PointSuggest { + public List listName(Player player, Command command, String[] args) { + ... + } +} +``` + ### 权限 #### 方法权限 diff --git a/docs/guide/essentials/config-file.md b/docs/guide/essentials/config-file.md index 0f97c5a..0d567cd 100644 --- a/docs/guide/essentials/config-file.md +++ b/docs/guide/essentials/config-file.md @@ -38,7 +38,7 @@ public class SomeConfig extends AbstractConfigEntity { 你需要获取插件主类的实例,然后调用 `getConfig` 方法。 ```java -SomeConfig someConfig = SomePlugin.getInstance().getConfig("/path/to/config.yml", SomeConfig.class); +SomeConfig someConfig = SomePlugin.getInstance().getConfig(SomeConfig.class); ``` 然后,你就可以使用 `getter` 和 `setter` 方法来操作配置文件了。 @@ -47,6 +47,15 @@ SomeConfig someConfig = SomePlugin.getInstance().getConfig("/path/to/config.yml" boolean something = someConfig.getSomething(); ``` +::: tip + +尽管UltiTools允许你对配置文件做出更改并可以保存更改,但是这并不意味着由程序更改配置文件是好的行为。 +程序更改配置文件会产生让用户意想不到的改变,可能会让用户尚未保存的配置丢失。 +配置是用来读取的,应该由用户自行配置并决定是否应用配置。 +如果你需要持久化的储存数据,请查看 [数据存储](/guide/essentials/data-storage)。 + +::: + ## 注册配置文件 在你的插件主类中注册配置文件。 diff --git a/docs/guide/essentials/data-storage.md b/docs/guide/essentials/data-storage.md index c21d93b..0fad518 100644 --- a/docs/guide/essentials/data-storage.md +++ b/docs/guide/essentials/data-storage.md @@ -58,13 +58,19 @@ DataOperator dataOperator = SomePlugin.getInstance().getDataOperator ``` DataOperator 的具体使用方法请参阅 Java Doc +::: warning + +`DataOperator` 不是线程安全的,请在需要的时候获取 `DataOperator`,不要试图保存 `DataOperator` 对象。 + +::: + ### WhereCondition `WhereCondition` 用于指定查询条件。 ```java -WhereCondition.builder().column("somecol").value(someval).build() +WhereCondition.builder().column("somecol").value(someval).build(); ``` 其中,`column` 属性用于指定查询的列,`value` 属性用于指定查询的值。 diff --git a/docs/guide/essentials/event-listener.md b/docs/guide/essentials/event-listener.md index 220c9c5..1ade136 100644 --- a/docs/guide/essentials/event-listener.md +++ b/docs/guide/essentials/event-listener.md @@ -27,7 +27,7 @@ public class UltiToolsConnector extends UltiToolsPlugin { @Override public boolean registerSelf() throws IOException { - getListenerManager().register(this, new SomeListener()); + getListenerManager().register(this, SomeListener.class); return true; } diff --git a/docs/guide/introduction.md b/docs/guide/introduction.md index 1332bc7..e7c5f47 100644 --- a/docs/guide/introduction.md +++ b/docs/guide/introduction.md @@ -8,7 +8,7 @@ footer: false UltiTools是一款发布于2020年6月的MC服务器基础插件,拥有诸多基础及特色功能,并且注重每个用户的反馈。 -作者致力于让更多服主轻松上手服务器的搭建,减少语言不通、插件不兼容等问题带来的烦恼。 +致力于让更多服主轻松上手服务器的搭建,减少语言不通、插件不兼容等问题带来的烦恼。 ## 特点 @@ -30,11 +30,11 @@ UltiTools是一款发布于2020年6月的MC服务器基础插件,拥有诸多 UltiTools API是UltiTools的核心,UltiTools API提供了一套完整的API,可以让您轻松开发出功能丰富的插件。 -UltiTools API打包了很多常用的库,包括但不限于Spring core、FastJson、Hutool、Adventure、Obliviate等,您可以在开发中直接使用这些库而无需担心插件的体量。 +UltiTools API打包了很多常用的库,包括但不限于Spring core、FastJson、Hutool、Adventure、obliviate-invs等,您可以在开发中直接使用这些库而无需担心插件的体量。 UltiTools API提供了一套完整的GUI API,您可以轻松地开发出GUI插件,而无需担心GUI的实现细节。 -UltiTools API提供了高级的注解系统,您可以像开发Spring Boot插件一样开发UltiTools插件。(由Spring Core提供的IOC框架) +UltiTools API提供了高级的注解系统,您可以像开发Spring Boot应用一样开发UltiTools插件。(由Spring Core提供的IOC框架) UltiTools 还提供了一个maven插件,可以自动将编译后的插件放入文件夹和上传模块至UltiCloud,提升您开发插件的生活质量。 diff --git a/docs/guide/quick-start.md b/docs/guide/quick-start.md index efe60c2..233a989 100644 --- a/docs/guide/quick-start.md +++ b/docs/guide/quick-start.md @@ -45,7 +45,7 @@ dependencies { ## 创建一个UltiTools的模块 -以下内容将会教你如何创建一个UltiTools的模块。如果你只是想使用UltiTools-API,可以跳转到 [使用UltiTools-API](#使用ultitools-api)。 +以下内容将会教你如何创建一个UltiTools的模块。如果你只是想在自己的插件中使用UltiTools-API,可以跳转到 [使用UltiTools-API](#使用ultitools-api)。 ### 创建模块元数据文件 @@ -72,22 +72,27 @@ authors: [ yourname ] 但是UltiToolsPlugin增加了一个可选的 `UltiToolsPlugin#reloadSelf()` 方法,用于模块重载时执行。 ```java +// 此注解包含了自动注册,必须添加到模块主类上 +@UltiToolsModule public class MyPlugin extends UltiToolsPlugin { - @Override - public boolean registerSelf() { - // 插件启动时执行 - return true; - } - - @Override - public void unregisterSelf() { - // 插件关闭时执行 - } - - @Override - public void reloadSelf() { - // 插件重载时执行 - } + @Override + public boolean registerSelf() { + // 插件启动时执行 + // 如果返回false则会阻止UltiTools加载该模块 + return true; + } + + @Override + public void unregisterSelf() { + // 可选,如果只是注销所有命令和监听器的话,不需要重写这个方法 + // 插件关闭时执行 + } + + @Override + public void reloadSelf() { + // 可选,如果只是重载模块配置文件的话,不需要重写这个方法 + // 插件重载时执行 + } } ``` @@ -101,32 +106,40 @@ public class MyPlugin extends UltiToolsPlugin { ```java import com.ultikits.ultitools.abstracts.UltiToolsPlugin; +import com.ultikits.ultitools.annotations.EnableAutoRegister; import java.io.IOException; import java.util.List; +// 此注解是必须的,指定了自动注册的扫描包名 +@EnableAutoRegister(scanPackage = "com.ultikits.plugin.ultikitsapiexample") public class UltiToolsConnector extends UltiToolsPlugin { - // 如果需要连接到UltiTools-API,则需要重写这个有参数的构造函数,另一个无参数的是给模块开发使用的。 - // 在这里请不要主动使用无参数的构造函数 - public UltiToolsConnector(String name, String version, List authors, List depend, int loadPriority, String mainClass) { - super(name, version, authors, depend, loadPriority, mainClass); - } - - @Override - public boolean registerSelf() throws IOException { - return false; - } - - @Override - public void unregisterSelf() { - - } - - @Override - public void reloadSelf() { - super.reloadSelf(); - } + // 如果需要连接到UltiTools-API,则需要重写这个有参数的构造函数,另一个无参数的是给模块开发使用的。 + // 在这里请不要使用无参数的构造函数 + public UltiToolsConnector(String name, String version, List authors, List depend, int loadPriority, String mainClass) { + super(name, version, authors, depend, loadPriority, mainClass); + } + + @Override + public boolean registerSelf() throws IOException { + // 插件启动时执行 + // 如果返回false则会阻止UltiTools加载该模块 + return true; + } + + + @Override + public void unregisterSelf() { + // 可选,如果只是注销所有命令和监听器的话,不需要重写这个方法 + // 插件关闭时执行 + } + + @Override + public void reloadSelf() { + // 可选,如果只是重载模块配置文件的话,不需要重写这个方法 + // 插件重载时执行 + } } ``` @@ -140,28 +153,27 @@ import org.bukkit.plugin.java.JavaPlugin; import java.util.Collections; +// 插件主类 public final class UltiKitsExample extends JavaPlugin { - @Override - public void onEnable() { - // 将此连接类注册到UltiTools的模块/插件管理器中 - UltiTools.getInstance().getPluginManager().register( - UltiToolsConnector.class, - "Example", // 模块名称 - "1.0.0", // 模块版本 - Collections.singletonList("wisdomme"), // 模块作者 - Collections.emptyList(), // 模块依赖 - 600, // UltiTools API 需求最低版本 - "com.ultikits.plugin.ultikitsapiexample.UltiToolsConnector" // 模块主类 - ); - - System.out.println(); - } - - @Override - public void onDisable() { - // 记得在插件卸载时将连接类从UltiTools的模块/插件管理器中注销 - UltiTools.getInstance().getPluginManager().unregister(UltiToolsConnector.getInstance()); - } + @Override + public void onEnable() { + // 将此连接类注册到UltiTools的模块/插件管理器中 + UltiTools.getInstance().getPluginManager().register( + UltiToolsConnector.class, + "Example", // 名称 + "1.0.0", // 版本 + Collections.singletonList("wisdomme"), // 作者 + Collections.emptyList(), // 依赖 + 600, // UltiTools API 需求最低版本 + "com.ultikits.plugin.ultikitsapiexample.UltiToolsConnector" // 连接类的完整类名 + ); + } + + @Override + public void onDisable() { + // 记得在插件卸载时将连接类从UltiTools的模块/插件管理器中注销 + UltiTools.getInstance().getPluginManager().unregister(UltiToolsConnector.getInstance()); + } } ```