--- front: hard: 入门 time: 20分钟 --- # 配置文件 ## 介绍 EventBus 是 Bukkit开发核心内容之一 ## 监听事件 通常情况下也就能使用到此功能 比如我们要监听玩家进入游戏的事件 应该如何书写? ```kotlin @SubscribeEvent fun hello(event: PlayerJoinEvent) { event.player.sendMessage("Hello, ${event.player.name}") } ``` > 和原版的监听器相似 都是在方法上 进行标记 但是我们不需要去主类注册 ## 注册事件 ```kotlin @Config("lib/test.yml") lateinit var config: ConfigFile ``` 那设置配置文件了如何保存呢? ```kotlin fun test() { config.set("hello.hello", "value") // 等价于 config["hello.hello"] = "value" config.saveToFile() } ``` ## 本地数据文件 `createLocal( path, saveTime, type )` 比如某些数据,我想通过本地配置文件保存 方法参数: 1. path - 文件路径 2. saveTime - 自动保存时间 3. type - 文件类型 ```kotlin fun test() { val test = createLocal("test.yml") test[playerName, number] // 不需要写保存 会自动保存 当然也可以手动保存 // createLocal.saveToFile() } ``` ## 创建配置文件 如果不想让TabooLib帮助你管理 比如你想自己在resources里手动创建好一个配置文件,然后在里面预设好配置这个配置文件 应该怎么写? ```kotlin fun test() { val file = newFile(getDataFolder(), "path.yml", create = true) val loadFromFile = Configuration.loadFromFile(file, Type.YAML) } ``` ## 读取某个文件 如果有一个 yaml 并不是你创建的或者是你创建了但是没有缓存应该如何读取呢? 和创建方法相似但是我们不需要 create = true ```kotlin fun test() { val file = newFile(getDataFolder(), "path.yml") ?: return val loadFromFile = Configuration.loadFromFile(file, Type.YAML) } ``` > 一个小 tip 给不会使用Kotlin的读者 > 当你在一个变量后面写了 ?: return 的时候 > 当这个变量为空的时候 就自动结束方法 ## 创建并写入File文本 通常是在一些 序列化 的场景中使用 ```kotlin newFile(getDataFolder(), it.path, create = true).writeText( Yaml.encodeToString(ShopGoodsBaseData.serializer(), it), StandardCharsets.UTF_8 ) ``` ## 读取File文本 通常在一些 反序列化 的场景中使用 ```kotlin fun loadData(file: File) { file.readText(StandardCharsets.UTF_8).let { text -> ShopManager.goods.add( Yaml.decodeFromString(ShopGoodsBaseData.serializer(), text) ) } } ``` ## 根据File转化为配置文件 有些时候 我们是只能拿到对象 拿不到文件的路径的(文件在内存中) 所以我们可以这样写 ```kotlin Configuration.loadFromFile(file, Type.YAML) ``` 还有其他类似方法 ```kotlin fun loadFromFile(file: File, type: Type? = null, concurrent: Boolean = true) fun loadFromReader(reader: Reader, type: Type = Type.YAML, concurrent: Boolean = true) fun loadFromString(contents: String, type: Type = Type.YAML, concurrent: Boolean = true) fun loadFromInputStream(inputStream: InputStream, type: Type = Type.YAML, concurrent: Boolean = true) ``` ## 从Bukkit平台加载配置文件 上文说到 不可以直接转换 需要通过一个方法转换 只要来源的那个配置文件类 包含 `saveToString` 方法 且是标准的 就可以进行读取 ```kotlin fun loadFromOther(otherConfig: Any, type: Type = Type.YAML, concurrent: Boolean = true) ``` ## 实现文件更新监听 通过 FileWatcher 自动识别文件是否更新 如果有更新则自动重新获取File ```kotlin object FileListener { private val listening = mutableSetOf() val watcher = FileWatcher.INSTANCE fun listener(file: File, runnable: File.() -> Unit) { watcher.addSimpleListener(file, runnable) listening.add(file) } fun clear() { listening.removeIf { val remove = !it.exists() if (remove) { watcher.removeListener(it) } remove } } fun load() { val file = File(getDataFolder(), "config.yml") listener(file) { info("监听文件重载了") } } } ``` ## 数据存储配置文件 如果想做本地数据存储 更快捷一点的 可以试试用这个方法 ```kotlin val database by lazy { createLocal("data/storage/data.yml", type = Type.YAML) } ``` 这样使用的时候 就会创建这个配置文件 然后这个配置文件会自动保存 所以 不可以手动更改配置文件 ## 拓展 - 读取文件夹里的所有Yaml并加载 ```kotlin val read = ArrayList() @Awake(LifeCycle.ENABLE) fun load() { read.clear() val file = newFolder(getDataFolder(), "marks", create = false) // 文件不存在则释放jar内的文件 if (!file.exists()) { file.mkdirs() releaseResourceFile("marks/test.yml") } file.walk() .filter { it.isFile } .filter { it.extension == "yaml" || it.extension == "yml" } .forEach { read.add(Configuration.loadFromFile(it)) } releaseResourceFolderAndRead("marks/"){ walk{ read.add(it) } } } ``` > 注意,其中 **releaseResourceFolderAndRead** 这个方法并不是原生 `Taboolib` 自带的功能 > 而是拓展库 [Arim](https://github.com/FxRayHughes/Arim) 里的方法 > 这个是由社区开发者 枫溪、嘿鹰、 WhiteSoul、Saukiya、坏黑、Mical 编写的