# 配置API
# 配置文件和配置API
配置文件用来储存配置信息, 以便使用文件开关功能、储存数据、修改信息.
我们往往需要读写配置文件. Bukkit为我们提供了配置API.
配置API是BukkitAPI提供的读写配置文件的工具. 其相对而言较为简单, 是插件开发中常用的API.
目前为止, 配置API只有YAML配置功能可用. 这也是大多数插件为什么配置文件是YAML文件的原因.
在本文中, 我们也将使用YAML配置API.
# 了解YAML文件
# 键值对
相信开服的经验已经使你对YAML文件有了初步认识.
YAML文件的文件后缀是.yml
. 其配置文件结构需要严格遵守YAML标准.
下面是一个符合标准的YAML配置文件的内容:
Settings:
DebugMode: true
Time:
CoolDown: 10
Data:
player1:
NickName: HandsomeBoy
Score: 50
TotalTime: 40
Title:
- Toilet Protecter
- Widow Maker
- Chicken Fucker
相信你可以根据空格看出每个项目之间的所属关系, 如下:
我们把上面所属关系图中, 矩形框内的东西叫做键(Key). 例如, Settings
是一个键, Data
是个键. 在Settings
键下存在DebugMode
、Time
两个子键, 它们分别叫做Settings.DebugMode
键和Settings.Time
键. 同理, 在Settings.Time
键下还有CoolDown
这个子键, 这个子键叫Settings.Time.CoolDown
键.
我们可以用这样的命名方法来称呼一个YAML文件中的任一一个键了. 并且还可以根据名称看出所属关系.
例如, Data.player1.Score
键对应的值是 50
.
在YAML中, 键和值一一对应, 一个键一定会有一个值.
# 数据类型
通常可以用配置文件存储一些基本类型(int、double、boolean)、String、数组和可被序列化的对象.
Bukkit中给出的一些对象有些是可以直接存进配置文件的, 这需要看这个类是不是实现了ConfigurationSerializable
接口. 例如, Player
类型的对象就可以被直接存入配置文件, 因为查阅JavaDoc后可以发现它实现了ConfigurationSerializable
.
后续会详细介绍, 这里需要知道判断方法.
在上面的配置文件中, 配置文件里储存了:
- 存储了一个
boolean
类型的值(Settings.DebugMode
键). - 存储了一些数字类型的值.
- 存储了一个
String
字符串(Data.player1.NickName
键). - 存储了一个
StringList
(YAML里的StringList
就是Java中的List<String>
, 例如Data.player1.Title
键).
YAML中注释以#
表示.
#就像这样写注释, 配置文件读取时会忽略掉注释
Settings:
DebugMode: true
相信你可以通过这个例子明白配置文件中可以储存哪些数据了.
# 对于不存在的数据
很明显, 上面的配置文件中, 并没有Data.player2.NickName
键, 那么如果我非要获取Data.player2.NickName
键的值, 获取到的数据是什么呢?
答案是null. 换句话说, YAML里所有不存在的键, 值是null.
请记住这句话. 我们可以根据这个原理推导出, 如果你想删除一个已经存在的键, 那就是把这个键的值设置为null.
# 操作默认配置文件
这里的默认配置文件指的是config.yml
文件.
首先我们需要准备一个默认的config.yml
文件. 这个文件会在插件检测到plugins\插件名
文件夹下没有config.yml
文件时被放入该文件夹中.
在插件jar文件里, 默认的config.yml
文件要与plugin.yml
文件处于同一目录下, 所以创建默认config.yml
的方法与创建plugin.yml
文件的操作方法一致. 在这里我们在默认config.yml
文件中存入我们一开始举的例子.
# 读取config.yml数据
下面做一个插件, 在玩家登陆服务器时, 给玩家显示配置文件Data.玩家名.Score
键对应的值.
public class HelloWorld extends JavaPlugin implements Listener{
public void onEnable(){
saveDefaultConfig(); //这个代码会自动判断插件配置文件里是不是有config.yml, 没有就会放入默认的config.yml
Bukkit.getPluginManager().registerEvents(this,this);
}
public void onDisable(){}
@EventHandler
public void onPlayerJoin(PlayerJoinEvent e){
//在这里我们监听了PlayerJoinEvent, 并操作`config.yml`
String key = "Data." + e.getPlayer().getName() + ".Score"; //这是我们要获取的键名
int score;
if(getConfig().contains(key)){ //先判断一下有没有这个键
score = getConfig().getInt(key); //有的话读取
} else {
score = 0; //没有的话就按0处理
}
e.getPlayer().sendMessage("你的积分是: " + score); //然后给玩家发送
}
}
如果你用getConfig().getString(key)
获取玩家数据Score
键的值, 那么获取到的就是一个String字符串.
也就是, YAML中值对应的数据类型具体是什么, 关键要看你用的getter是什么.
# 写入数据到config.yml
我们再来做个"加分项", 玩家挖掉一个石头后, 给他加分.
public class HelloWorld extends JavaPlugin implements Listener{
public void onEnable(){
saveDefaultConfig();
Bukkit.getPluginManager().registerEvents(this,this);
}
public void onDisable(){}
@EventHandler
public void onPlayerJoin(PlayerJoinEvent e){
//这里代码跟上面是一模一样的, 这里只是做了简化, 因为原先的if占篇幅太大
String key = "Data." + e.getPlayer().getName() + ".Score";
int score = getConfig().contains(key)?getConfig().getInt(key):0;
e.getPlayer().sendMessage("你的积分是: " + score);
}
@EventHandler
public void onBlockBreak(BlockBreakEvent e){
if (e.isCancelled()) return; //判断此事件是不是被其它插件取消掉了
if(e.getBlock().getType() == Material.STONE){ //判断类型, 是石头
String key = "Data." + e.getPlayer().getName() + ".Score";
int score = getConfig().contains(key)?getConfig().getInt(key):0; //获取玩家当前积分, 如果从未记录此玩家的积分数据则默认为0
getConfig().set(key,score + 10); //挖一个石头加10分
//但是写到这里要小心!你只是修改了内存上的数据, 你没有修改硬盘上的config.yml文件里的数据!
saveConfig(); //所以要注意, 修改数据要记得保存
}
}
}
由此, 你需要小心, getConfig()的内容是内存上的内容, 修改它并没有修改硬盘上的内容, 关服/重载后就会消失, 因此要注意保存!
set
不区分数据类型是什么, 存储数据全部都用set
方法. set
不管这个键在配置文件里存不存在, 都会写入这个数据.
还记得我们一开始说的YAML里所有不存在的键, 值是null
吗? 如果你想删除掉player3
的数据, 那你应该写成:
getConfig().set("Data.player3",null);
这样配置文件里Data
键下就没有player3
的数据了,也就达到了删除一个键的目的.