参与编写者: MagicLu550
配置文件用于存储插件的配置信息,供用户自定义和修改,以及存储一些永久数据,我们称 配置文件属于 持久层。
nukkit提供了多种配置文件格式,如yaml,json,properties等,其中最常用的是yaml, 我们主要讲解这个配置文件格式,其他如果想要了解,可以发送issues,我们可以补充。
一. 关于yaml
nukkit的yaml框架基于snakeYaml实现的, snakeYaml是一款使用广泛的yaml解析库,我们可以从它的官网了解 他们的语法,在nukkit开发中,我们更多使用key: value的映射形式
这是一个yaml的文件案例
server:
name: 12
player:
- nihao
- xiaoming
- xiaogang
time:
year: 2019
yaml的标准语法是使用空格来划分级别,前面为键,后面为值,且值和冒号之间有空格, 虽然yaml的语法不止如此简单,但是我们最常用的也就这些很简单的东西。
yaml的数组有两个表示形式
array1: ["1","2"] #yaml的注释
array2: [1,2] #yaml不允许有重复的键
array3:
- 1
- 2
- 3
如果还要了解其他,可以上yaml官网查看他们语法,这里只讲解这些语法
二. 如何使用nukkit的配置文件库
原本的snakeYaml使用起来比较复杂,因此nukkit官方提供了简化,同一 使用Config对象来表达和操作。
使用默认的配置
默认配置文件为config.yml,可以通过saveDefaultConfig()方法来实现, 前提是你的resources下面要创建一个config.yml,这个方法会默认在 plugins/${你的插件名字}下创建一个config.yml,并且会把resources下面的那个 config.yml内容复制过来. 之后我们调用这个方法即可 我们这里打开一个服务器,做一个实验可以看看,插件名为FirstPlugin 我们插件被加载成功,我们看看我们的文件夹 发现.../plugins/FirstPlugin下面出现了一模一样的config.yml
使用自定义的配置
自定义配置有两种方式,一种是已经初始化的文件,一种是空白文件,元素后期添加
- 初始化的文件 saveResource(String fileName, boolean replace)
第一个是文件名称,默认是this.getDataFolder()+"/"+fileName的路径 getDataFolder()为.../plugins/你的插件名 ,不包含后面的"/",使用时记得注意 假如你的插件名称为abc,那么路径为.../plugins/abc
第二个是是否替换文件,每次重新启动服务器时,会把文件内容重新更新,如果为false, 则不会更新。或者已经存在config,将不会换掉。如果为true,那么就会换掉它。之前修改 的内容就会被替换(实际上加了true就是把文件删掉重新创建一遍)
而文件初始化的来源和之前的config.yml一样,我们可以看看saveDefaultConfig()源码会发现, 它的本质也是saveResource
PluginBase.java
@Override
public void saveDefaultConfig() {
if (!this.configFile.exists()) {
this.saveResource("config.yml", false);
}
}
- 空白文件 空白文件的文件默认没有getDataFolder(),它的默认路径是和nukkit.jar同一级别的文件目录.
Config config = new Config(this.getDataFolder()+"/myConfig.yml",Config.YAML);
config.save();//保存文件,文件不存在就会创建
Config可以实现对文件的操作,例如先前的config.yml,我们想对其实现操作,可以
Config config = new Config(this.getDataFolder()+"/config.yml",Config.YAML);
config.set("me","12");//将me修改为12,如果me不存在将创建me
config.save();
当然值得注意,每次重新运行,set都会修改一次me,所以如果手动修改了me,就会被还原。 所以你可以做一个条件判断来避免还原的问题,比如判断文件是否存在。 当然这是初始化文件出现的问题,我还是建议初始化文件使用saveResource来初始化
Config的常用方法 1.构造方法
我们可以看官方源码
Config.java
/**
* Constructor for Config instance with undefined file object
*
* @param type - Config type
*/
public Config(int type) {
this.type = type;
this.correct = true;
this.config = new ConfigSection();
}
/**
* Constructor for Config (YAML) instance with undefined file object
*/
public Config() {
this(Config.YAML);
}
public Config(String file) {
this(file, Config.DETECT);
}
public Config(File file) {
this(file.toString(), Config.DETECT);
}
public Config(String file, int type) {
this(file, type, new ConfigSection());
}
public Config(File file, int type) {
this(file.toString(), type, new ConfigSection());
}
file为文件名称,默认路径为nukkit的根目录 type为类型,主要使用的类型是
Config.java
public static final int DETECT = -1; //Detect by file extension
public static final int PROPERTIES = 0; // .properties
public static final int CNF = Config.PROPERTIES; // .cnf
public static final int JSON = 1; // .js, .json
public static final int YAML = 2; // .yml, .yaml
//public static final int EXPORT = 3; // .export, .xport
//public static final int SERIALIZED = 4; // .sl
public static final int ENUM = 5; // .txt, .list, .enum
public static final int ENUMERATION = Config.ENUM;
我们主要使用yaml,json.properties,其他大家可以自行查询。
如何实现动态内容
比如一些插件可以这样做
message: ${player}加入了信息
其实可以使用replace做到
package net.noyark.www;
import cn.nukkit.event.EventHandler;
import cn.nukkit.event.Listener;
import cn.nukkit.event.player.PlayerJoinEvent;
public class OtherListener implements Listener {
@EventHandler
public void onPLayerJoin(PlayerJoinEvent e){
String message;
//获取到内容后...
e.getPlayer().sendMessage(message.replace("${player}",e.getPlayer().getName()));
}
}
当然我们也可以基于反射做一个简单的解析工具
class Utils{
String[] vals = {"player","ip"};
Map map = new HashMap(){
{
put("player","getName");
put("ip","getAddress");
}
};
public String translate(Event e,String message){
try{
Set<Map.Entry<String,String>> entries = map.entrySet();
for(Map.Entry<String,String> e1:entries){
message = message.replace("${"+e1.getKey()+"}",e.getClass().getDeclaredMethod(e1.getValue()).invoke(e).toString());
}
}catch (Exception e2){
e2.printStackTrace();
}
return message;
}
}