跳到主要内容

4-3 创建和初始化项目

和先前一样创建项目,你可以将其命名为 start-menu,也可以自行选用其它名称。别忘了正确地修改 build.gradle.kts 和其它相关文件。

配置文件

由于我们的插件有自定义命令的功能,因此需要在配置文件中添加相应的键。我们的配置文件设计如下:

enabled: true
command:
  label: "Ciallo~(∠・ω< )⌒☆"
  run: "say Ciallo~(∠・ω< )⌒☆"
liftoff:
  velocity: 5

Nyaci:……所以你是柚子厨,对吗?

Maybe.

这里我们允许管理员通过修改 command.label 来改变按钮的标签(即显示的文本),command.run 来改变要执行的命令(命令没有前缀 /)。此外,我们还给快速起飞功能增加了一个可调的 liftoff.velocity,允许管理员决定起飞的动量(或者说速度)有多大。

另外我们保留了先前的 enabled 选项。基本上来说,每个插件都会有一个选项开启或关闭插件功能,这是因为从 plugins 中移除和添加插件是相对麻烦的,而修改配置文件则简单很多。

插件信息

和先前一样,我们创建 plugin.yml

name: StartMenu
author: skjsjhb
description: A tiny menu with custom command support.
website: https://bpd.skjsjhb.moe/docs/the-tutorial/start-menu/sketch
main: Main
version: 1.0
api-version: 1.21

但是还没完!如果我们的插件要使用命令,需要在 plugin.yml 中添加它。向 plugin.yml 中再增加以下内容:

commands:
  menu:
    usage: /menu            # commands.menu.usage,命令用法说明
    description: 打开菜单    # commands.menu.description,命令简介

Bukkit 规定命令必须填在 commands 键下,即 commands 是一张表,它的键是命令名称(在这里是 menu),值又是一张子表,其中包含命令的一些属性,通过上面的缩进关系不难看出它们的层级,在编辑代码时,大家也要使用正确数目的空格。

usage 描述命令的用法,description 则对命令的功能做个简要说明,这些信息会在有人输入 /help 你的命令 的时候显示出来。除此之外,命令还有一些其它属性可以设置,不过限于篇幅,无法在这里展开说明了。

所有的键都是可选的,因此理论上,最少只需要下面的代码就可以添加一条命令:

commands:
  menu: {}  # {} 表示空白表

但是这么做不太好,因为当用户输入 /help menu 而找不到任何提示信息的时候,他们会非常沮丧。

主程序

Main.kt 中添加以下内容(你应该已经对此感到得心应手了):

import org.bukkit.plugin.java.JavaPlugin

class Main : JavaPlugin() {
    override fun onEnable() {
        saveDefaultConfig()
    }
}

由于这次我们要用到更多的事件处理器,再把整个 object 都放在 onEnable 中就不合适了。我们可以选择不再使用 object 就地创建监听器,而使用一个类来描述监听器,利用构造函数传递配置对象:

class EventHandlers(
    private val config: ConfigurationSection  // 比使用 FileConfiguration 更泛用
) : Listener {
    // 可以在这里使用 config 获取插件配置
}

这里我们向 EventHandlers 中添加了一个私有属性 config,用来存储插件读到的配置,这样我们就将监听器的内容与主类分离开来。我们将 config 放在构造函数参数列表中,这样稍后创建对象时,这个位置的参数就会被自动赋给该属性,希望你还没忘记这一点(笑)。

宽以待人

选择 ConfigurationSection 作为 config 的类型,正是印证了上一节中关于接口的用法,即 如果可能,就总是使用基类的类型,而不是具体类型,避免对对象施加超出必要范围的限制。

JavaPluginconfig 属性获取的是 FileConfiguration,但我们只使用到其中的 getXXX 等方法,通过查阅 Javadoc,我们得知这些方法来自于 ConfigurationSection,那么选择它作为类型就比 FileConfiguration 更好,因为我们并不需要 ConfigurationSection 以外的功能就足以读取配置信息。

Javadoc Interface

现在,向 onEnable 中添加如下代码来实例化 EventHandlers 并将它注册(还记得吗,类只是蓝图):

if (config.getBoolean("enabled", false)) {
    server.pluginManager.registerEvents(EventHandlers(config), this)
}

由于通过 EventHandlers(config) 创建的对象此后不会再使用,因此就不必创建额外的中间变量,直接将它作为参数传递就好。

到目前为止,Main.kt 的内容如下:

class Main : JavaPlugin() {
    override fun onEnable() {
        saveDefaultConfig()
        if (config.getBoolean("enabled", false)) {
            server.pluginManager.registerEvents(EventHandlers(config), this)
        }
    }
}

class EventHandlers(
    private val config: ConfigurationSection
) : Listener {
}