Skip to content

Latest commit

 

History

History
224 lines (181 loc) · 7.14 KB

1-5_如何使用配置文件.md

File metadata and controls

224 lines (181 loc) · 7.14 KB

上一节 下一节

第一章 第五节 如何编写配置文件

参与编写者: MagicLu550

建议学习时间: 40分钟

学习要点: 了解如何创建配置文件,了解使用SimpleConfig

配置文件用于存储插件的配置信息,供用户自定义和修改,以及存储一些永久数据,我们称 配置文件属于 持久层

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内容复制过来. 5-01 之后我们调用这个方法即可 5-02 我们这里打开一个服务器,做一个实验可以看看,插件名为FirstPlugin 5-03 我们插件被加载成功,我们看看我们的文件夹 5-04 发现.../plugins/FirstPlugin下面出现了一模一样的config.yml

使用自定义的配置

自定义配置有两种方式,一种是已经初始化的文件,一种是空白文件,元素后期添加

  1. 初始化的文件 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);
        }
    }

  1. 空白文件 空白文件的文件默认没有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;
        }
}

上一节 下一节