3-1 YAML Again
客制化产品
在上一章中你或许已经发现,如果想让欢迎消息的内容不同,那就需要修改 Kotlin 源代码。这在开发环境中很方便,可如果插件安装在一个生产环境的服务器上,指望服务器管理员来修改代码根本就是不切实际的事情,特别是当插件的规模增大时。
开发环境(Development Environment) 是指用于测试的服务器,例如我们使用的 paper-1.21.4.jar,你简单通过命令来启动它,并且可以随时将它关闭,增加或移除插件,而且即使存档数据丢失了也不太担心。
生产环境(Production Environment) 则刚好与开发环境相反,指的是正式在运行的服务器,它们直接面向玩家服务,通常来说需要长期在线,即使要停服维护也需要提前发送公告,数据完整性更是极其重要(有时甚至会找来一台单独的服务器备份数据)。
由于生产环境对稳定性的要求是如此之高,插件必须经过大量的测试才能移动到生产环境中,连随意修改生产环境中的插件配置都是很危险的,更别提修改代码本身了。
为了解决这个问题,绝大多数插件都使用所谓的配置文件(Configuration),也就是平时常说的 config.yml。配置文件是用户与插件代码的交互接口。 插件读取配置文件中的一些数据来改变自身的行为(例如欢迎消息的内容),而这些数据可以由服务器管理员进行设置。我们的插件向用户授予了有限的权力,允许用户改变插件中的特定行为,而不需要修改代码。
在这里要说明的一点是,尽管很多配置文件都是 YAML 格式的,但这并非唯一的选择。插件完全可以选择任何数据格式,包括 JSON、TOML、Properties 甚至纯文本文件,只要插件有一种方式来解析配置文件中的数据,用户也能相对容易地修改,那么这就是有效的配置文件格式。不过,Bukkit 提供了很多内置功能来支持 YAML 文件,所以在插件中使用 YAML 格式的配置文件非常容易。
设计配置文件结构
在继续之前,先向你介绍第三个项目的内容:
今日要闻(Anno)
向加入服务器的玩家展示一份公告。
公告的内容可能经常变化,所以需要能由管理员容易地修改。此外,管理员应当可以在不删除插件的前提下暂时关闭公告系统。
在这样的设计里,有哪些东西是需要『可变』的呢?至少包含以下两部分:
- 是否启用公告:当禁用时,不管公告内容如何设置都不显示公告。
- 公告内容:要发送给玩家的内容。
当明确了插件中可变的部分后,我们可以先用 YAML 格式,试着写一个想象中的配置文件:
enabled: true
content: Welcome to my Paper server!
不同于 plugin.yml,配置文件的格式完全是由插件自定义的,所以你也可以选择 aaa 或者 unicorn 这样的键名,不过,通常配置文件的键名会使用有意义的名称,方便阅读和修改。
我们先前提到过,YAML 的 : 右侧的值具体是什么类型,是由读取 YAML 的人来定义的。Bukkit 为 YAML 定义了很多可用的类型,以下是一些常用的:
bool-value: true # 逻辑值
num-value: 1.13 # 数字
str-value: "ciallo, world" # 文本,两侧的引号可以省略
list-value: [1, 2, 3] # 列表
list-value-dashed: # 列表的另一种写法
- 1
- 2
- 3
table-value: # 子表
sub-key-1: 42 # 子表中的一个键
在 YAML 中,以 # 开头直至当前行的末尾都被当作是注释(Python 开发者应该很熟悉这一点),这与 Kotlin 中的 // 功能类似。
这里出现了一个新东西,就是列表(List)。列表可以包含一列值,包括数字、文本、逻辑,甚至也能包含其它的列表!这用来存储用户名称之类的信息是再合适不过了。
在我们这次的配置文件中,我们只使用了两种类型,enabled 是逻辑值,代表插件是否启用,而 content 是文本,代表要发给玩家的信息。
读取配置文件的一般流程
配置文件,顾名思义,是保存在服务器的硬盘上的。将配置文件转换成 Kotlin(和 Java)能使用的格式(也就是对象)叫做读取(Load) 配置文件。在 Bukkit 中,读取配置文件分为以下三步:
- 看看配置文件是否存在,如果不存在,则生成一份默认的配置文件。
- 将配置文件的内容读到内存中。
- 把读取到的内容转换为 Kotlin 对象。
Bukkit 把这些工作都包装成了可用的函数,我们不需要关注 Bukkit 具体是怎么做到这些的,只要使用相应的函数就好啦。
Nyaci:喂,Ted,从第一章开始你就一直在变魔术诶,告诉我『Bukkit 里有这个』『Bukkit 里有那个』『只要这么做就行了』,你到底是怎么知道这些东西的?
好吧,Nyaci 是一只好奇心很强的猫猫,我们将在下一小节里向 Nyaci 和各位读者解答这个问题。