• 因近日遭受攻击,百科现已限制新用户的编辑权限,一段时间后成为自动确认用户方可编辑。

Configuration API Reference

From Minecraft插件百科
Revision as of 20:56, 15 August 2016 by Tdiant (talk | contribs) (Configuration对象)
Jump to: navigation, search

点击此处浏览原文

Icon-info.png
本页面已存在其他语言的内容,请协助翻译为本地化的中文。
  • 点击此处开始翻译。
  • 如本模板出现在原文存档页面,请注意更新主页面后,仍需要去除此处该模板
  • 如当前页面已经没有需要翻译的内容,请删去待翻译模板
  • 有标题的大篇幅文章,如果短时间内无法全部翻译,请先把所有的标题翻译出来,以便
  • 之后的贡献者选择与翻译章节内容。


Configuration API是一个帮助程序员们更快地解析与编辑配置文件的设置工具,让人们觉得配置文件更简单更容易编辑。不管是什么,这个API可以帮助你更容易的存储你插件的信息。目前只有这个 YAML configurations 可以用。然而,有了这个API,设计的能有更多的扩展空间,还能允许你实现其他的东西。

Configuration API可以在 org.bukkit.configuration 和 org.bukkit.configuration.file 这俩包里找到。插件的版本如果创建在 1.1-R5之前,就只能用老的并且与此不同的方法了,这些东西在org.bukkit.util.configuration这个包里。这些实现方法彼此不兼容并且老的方法因为太过时了,在新版中被删去了。

This introduction assumes that you have some knowledge about proper object oriented design, Java, and the core design of Bukkit plugins. This page is not a substitute for the JavaDocs for the FileConfiguration Class

基本论述

Configuration对象

[1] 当你的插件主类继承了 JavaPlugin的时候, 这个类也会继承JavaPlugin这个父类的的方法和属性。 在被继承的方法其中, getConfig() 返回的是一个 FileConfiguration类型的对象。这个对象就代表你插件数据文件夹里的config.yml

你的插件在第一次使用getConfig()的时候,会从你插件的jar文件中读取相应的config.yml ,同时从jar中的config.yml加载相应的默认值。 需要注意的是,第一次使用之后再调用getConfig()只会返回内存中保存的FileConfiguration 对象,而并非磁盘上保存的最新的。除非你手动保存了,否则你对这个对象进行的修改并不会被保存。同理,在第一次调用getConfig()之后,对磁盘上的config.yml文件的修改不会被反映在这个对象里。如果在plugins文件夹中对应的插件文件夹里不存在 config.yml ,这时会等价于存在一个空的config.yml, 也会加载一个空的FileConfiguration

Warning.png 如果你在利用getConfig()的返回值,请不要把它赋给一个变量来使用
Warning.png 如果需要这样的话,一定要记住在重载配置文件后,再把 getConfig() 分配给那个变量
Warning.png 保险起见,推荐你尽可能的直接用getConfig(),而不是将其分配给一个变量

键值

配置文件由键值组合构成,所有的键都是字符串.值对于其他键来说可能是一个FileConfigurationSection或是独立的数据. getKeys(boolean) 方法会返回现有FileConfigurationSection集合的值.布尔值决定返回的集合是不是递归的,如果为true,其将返回指定节点的键与子键, 如果为false则只会返回指定节点的键.为了获得特定节点的键, getKeys(boolean) 方法必须加载在特定节点. 你可以通过getConfigurationSection(String)方法来获取这个部分.

Warning.png getKeys(boolean)方法返回的是这里的字符串集合

路径

Configuration API 使用路径来形成独立的键值组合.路径是键的集合用来将其与值关联的.每层都被路径分隔符区分开来,默认的分隔符是 '.' (段落).举例来说,下面的YAML文件就有着一个路径的集合.

key: value
one:
  two: value
  three:
    - values
    - values
    - values
  four: 
    five: value
  *:
    six: value
    seven: value
  • key
  • one
  • one.two
  • one.three
  • one.four
  • one.four.five
  • one.*
  • one.*.six
  • one.*.seven

默认值

你的jar中应该为用户准备一个默认的config.yml.当出现config.yml丢失或是不完整的情况时,程序将会访问jar内的 config.yml来获取值.准备好的文件必须被命名为 config.yml ,且应当放在与 plugin.yml相同的目录. The file should have the intended structure of your config.yml. This file can be copied as is into the datafolder by invoking saveDefaultConfig() on the Appropriate instance of JavaPlugin.

this.saveDefaultConfig()

If dynamic key-value pairs are required as default values, they can added as defaults to the configuration with invocations of addDefault(String, Object) and addDefaults(Map<String,Object>) methods.

In certain cases if you wish to append new key-value pairs to an existing config.yml you can set the copyDefaults to true for the ConfigurationOptions object.

this.getConfig().options().copyDefaults(true)

创建一份config.yml的拷贝

你可以使用JavaPlugin类中的saveDefaultConfig()方法,将jar中的config.yml拷贝一份至插件的数据文件夹中[2] . saveDefaultConfig()并不会覆盖已有的文件.

获得值

Reading values from the configuration involves invoking one of the many getter methods. A complete list of getters can be found here. Every getter method takes a configuration path detailed above. Some of the commonly used getter methods are as follows

  • getBoolean(String)
  • getInt(String)
  • getString(String)
  • getList(String)
  • getStringList(String)

HashMaps

In the case of HashMaps as a value, they are treated differently than other forms of data. There is a restriction for Map types. It must use a String as a key, and the value but be either a boxed primitive, String, List, Map, or a ConfigurationSerializable type. They will lose their type.

To get a HashMap, a ConfigurationSection must must first be retrieved. You can return the configuration with getConfigurationSection method. The getValues method will return the values in the ConfigurationSection as a map, it takes a boolean which controls if the nested maps will be returned in the map. You can obtain the original map by invoking getValues(false) on the returned ConfigurationSection. Due to the way Java handles generic classes, type information will be lost, thus a cast will need to be performed to set the original type information. The API makes no guarantees that the cast you perform will be safe.

this.getConfig().getConfigurationSection("path.to.map").getValues(false)

设定值

Writing values involves invoking the set(String, Object) method on an instance of Configuration. Unlike the different get methods that FileConfiguration has, there is only one set method. Not all objects can be set, only primitive types, String, Lists, and types that implement ConfigurationSerializable, such as Vector and ItemStack, can be set. To erase a value supply null as a parameter. All changes made by set will only affect the copy of the configuration in memory, and will not persist beyond restarting the server until the configuration is saved. Following are some example uses:

// setting a boolean value
this.getConfig().set("path.to.boolean", true);

// setting a String
String stringValue = "Hello World!";
this.getConfig().set("path.to.string", stringValue);

// setting an int value
int integerValue = 8;
this.getConfig().set("path.to.integer", integerValue);

// Setting a List of Strings
// The List of Strings is first defined in this array
List<String> listOfStrings = Arrays.asList("Hello World", "Welcome to Bukkit", "Have a Good Day!");
this.getConfig().set("path.to.list", listOfStrings);

// Setting a vector
// event is assumed to be an existing event inside an "onEvent" method.
Vector vector = event.getPlayer().getLocation().toVector();
this.getConfig().set("path.to.vector", vector);

// Erasing a value
this.getConfig().set("path.to.value", null);


HashMaps

When HashMaps are used as a value, they are treated slightly differently. The Map must parameterized with a String type for the key, and the value must be parameterized as a boxed primitive, String, List, Map, or a ConfigurationSerializable.

While you can use the set method to directly set a HashMap to a key, you cannot directly retrieve the Map back with the get method after reading directly from disk. The context above is to minimize unpredictability.

To set a HashMap, a ConfigurationSection must be created for that HashMap. You can only set HashMap where the key is a string the the value is something that is ConfigurationSerializable. The createSectionMethod

this.getConfig().createSection(String path, Map< String, Object > map)

保存文件

If make any changes to theFileConfiguration with set methods, or mutate any Lists, you will need to save the changes to disk if you wish to keep these changes after the plugin is disabled. To save the file to disk invoke the saveConfig method for your plugin, it will overwrite the file already there.

this.saveConfig();

从磁盘中重载配置文件

If you suspect that users have made changes to the config.yml in the data folder, those changes are not reflected in memory. Invoke the reloadConfig() method of your plugin to load from the disk again. It will destroy all changes in memory.

this.reloadConfig();
  1. key 键 value 值
  2. /plugins/YourPlugin/

高级

The following are some more advanced topics, meant for more advanced plugins. If you only require the default config.yml, creating custom methods for reading, and saving, you will not need to go this far.

菜单

Every FileConfiguration instance is associated with a FileConfigurationOptions object. The FileConfigurationOptions object controls the behavior of the FileConfiguration it is associated with. FileConfiguration's options() method returns the FileConfigurationOption's responsible for it. With it you can check and set each option. There are currently four options. Be aware that the methods are overloaded, for example copyDefaults() which returns a boolean and copyDefaults(boolean) which returns it self, but has a side effect which changes the state.

CopyDefaults

The copyDefaults option changes the behavior of Configuration's save method. By default, the defaults of the configuration will not be written to the target save file. If set to true, it will write out the default values, to the target file. However, once written, you will not be able to tell the difference between a default and a value from the configuration.

PathSeperator

PathSeperator changes the character that is used to separate the different levels of the configuration. By default it is the "." (period) but it can be changed to any char.

Header

Header is the comment block at the top of a YAML file, it is applied to the save output. The header is the only comment that Configuration API knows how to copy.

copyHeader

If copyHeader() returns true then the header will be copied on save, from the default source.

自定义配置文件

如果你需要额外的YAML文件,用于存储配置信息或坚持额外的游戏信息你需要访问额外的配置文件,写下你自己的方法。仿照 JavaPlugin 里的 getConfig,reloadConfig,saveConfig方法,下面是一个例子,如何编写你自己的方法来读取和保存自定义配置文件。由于这些配置文件,属于你的插件,你可以把这个方法在你的主类,这样你可以有相同的访问,你有config.yml 。你必须为每个YAML文件写的一套方法。这里的优势是,你可以使用都以相同的方式设置为默认设置的方法config.yml 。另外,添加额外的方法可以保持较低的计数方法,并允许访问多个文件。

JavaPlugin 镜像的实现

javaplugin实现方法config.yml。插件需要实现它自己的方法来访问插件的配置文件。实现插件的方法后,就可以调用相同的上下文中的继承”getconfig() '、' reloadconfig() '、' saveconfig() ',和' savedefaultconfig()”方法javaplugin。以下可以做成一个类可以访问任何YAML文件。这样一个类可以在这里找到:

ClickHere

首先,您需要声明2个字段,并将其初始化为每个自定义配置文件空值。一个“'fileconfiguration”对象和一个"file‘’的对象。file对象表示磁盘上的文件,和fileconfiguration代表配置的内容。

private FileConfiguration customConfig = null;
private File customConfigFile = null;
实现重载

然后,你写的方法负责从磁盘加载配置。它将加载文件和搜索位于jar里的默认customconfig.yml 。

public void reloadCustomConfig() {
    if (customConfigFile == null) {
    customConfigFile = new File(getDataFolder(), "customConfig.yml");
    }
    customConfig = YamlConfiguration.loadConfiguration(customConfigFile);

    // Look for defaults in the jar
    Reader defConfigStream = new InputStreamReader(this.getResource("customConfig.yml"), "UTF8");
    if (defConfigStream != null) {
        YamlConfiguration defConfig = YamlConfiguration.loadConfiguration(defConfigStream);
        customConfig.setDefaults(defConfig);
    }
}


实现获取

Next, you need to write the getter method. Check if customConfig is null, if it is load from disk.


public FileConfiguration getCustomConfig() {
    if (customConfig == null) {
        reloadCustomConfig();
    }
    return customConfig;
}


实现保存

Finally, write the save method, which saves changes and overwrites the file on disk.

public void saveCustomConfig() {
    if (customConfig == null || customConfigFile == null) {
        return;
    }
    try {
        getCustomConfig().save(customConfigFile);
    } catch (IOException ex) {
        getLogger().log(Level.SEVERE, "Could not save config to " + customConfigFile, ex);
    }
}
实施默认覆盖

Optionally, you may want to write a method that mimics JavaPlugin's saveDefaultConfig() method.

public void saveDefaultConfig() {
    if (customConfigFile == null) {
        customConfigFile = new File(getDataFolder(), "customConfig.yml");
    }
    if (!customConfigFile.exists()) {            
         plugin.saveResource("customConfig.yml", false);
     }
}

Serializing and Deserializing Objects

The Configuration API, as mentioned above can store Java objects that implement the ConfigurationSerializable Interface. Object serialization facilitates easy saving and loading so plugin authors can focus on other parts of their plugin. It greatly simplifies tasks such as storing a Location in YAML, a developer can serialize a wrapper class, which provide methods to retrieve a Location.

Classes, in addition to implementing the ConfigurationSerializable interface must also implment one of the following as noted in the Javadoc, so that they can be serialized by the API:

  • A constructor that accepts a single Map.
  • A static method "deserialize" that accepts a single Map and returns the class.
  • A static method "valueOf" that accepts a single Map and returns the class.

In order for a serialized object to be deserialized, it must also be registered with ConfigurationSerialization. The static registerClass method must be invoked once per class that has been serialized.

This statement must be placed in your onEnable method or some other location that gets called every time your plugin is initialized:

ConfigurationSerialization.registerClass(Class<? extends ConfigurationSerializable>)

Warning.png {{{1}}} Do not use a static block to execute the above; if you do so, it will not be called a second time when /reload is used and you will encounter errors due to it not being registered!

Aliases

When classes are serialized they are marked with their fully qualified name.

You can provide an alias to your class so that it does not serialize with the fully qualified name of your class, but the alias instead. You provide the alias with the SerializableAs annotation to the class implementing ConfigurationSerializable.

@SerializableAs(String)

When registering a class with an alias, the alias must be provided on registration.

ConfigurationSerialization.registerClass(Class<? extends ConfigurationSerializable>, String)

使用样例

Below is the an example plugin that uses the new Configuration API to be display messages as an MOTD as players join, and for the player to retrieve the rules on command. It does not follow proper style and plugin layout to keep the number of lines to a minimum.

import java.util.*;
import org.bukkit.command.*;
import org.bukkit.event.*;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.configuration.file.FileConfiguration;


public class SimpleMOTD extends JavaPlugin {

    @Override
    public void onEnable() {
        // Save a copy of the default config.yml if one is not there
        this.saveDefaultConfig();
        
        // Register a new listener
        getServer().getPluginManager().registerEvents(new Listener() {
            
            @EventHandler
            public void playerJoin(PlayerJoinEvent event) {
                // On player join send them the message from config.yml
                event.getPlayer().sendMessage(this.getConfig().getString("message"));
            }
        }, this);

        // Set the command executor for the rules command
        this.getCommand("rules").setExecutor(new CommandExecutor() {
            
            public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
                // On command send the rules from config.yml to the sender of the command
                List<String> rules = this.getConfig().getStringList("rules");
                for (String s : rules){
                    sender.sendMessage(s);
                }
                return true;
            }
        });
    }
}

The default config.yml that is in the plugin's jar

# default config.yml
message: Hello World and Welcome! :)
rules:
  - Play Nice
  - Respect others
  - Have Fun