# 配置文件

# 介绍

EventBus 是 Bukkit开发核心内容之一

# 监听事件

通常情况下也就能使用到此功能
比如我们要监听玩家进入游戏的事件 应该如何书写?

@SubscribeEvent
fun hello(event: PlayerJoinEvent) {
    event.player.sendMessage("Hello, ${event.player.name}")
}

和原版的监听器相似 都是在方法上 进行标记 但是我们不需要去主类注册

# 注册事件

@Config("lib/test.yml")
lateinit var config: ConfigFile

那设置配置文件了如何保存呢?


fun test() {
    config.set("hello.hello", "value")
    // 等价于
    config["hello.hello"] = "value"
    config.saveToFile()
}

# 本地数据文件

createLocal( path, saveTime, type )
比如某些数据,我想通过本地配置文件保存
方法参数:

  1. path - 文件路径
  2. saveTime - 自动保存时间
  3. type - 文件类型
fun test() {
    val test = createLocal("test.yml")
    test[playerName, number]
    // 不需要写保存 会自动保存 当然也可以手动保存
    // createLocal.saveToFile()
}

# 创建配置文件

如果不想让TabooLib帮助你管理
比如你想自己在resources里手动创建好一个配置文件,然后在里面预设好配置这个配置文件
应该怎么写?

fun test() {
    val file = newFile(getDataFolder(), "path.yml", create = true)
    val loadFromFile = Configuration.loadFromFile(file, Type.YAML)
}

# 读取某个文件

如果有一个 yaml 并不是你创建的或者是你创建了但是没有缓存应该如何读取呢?
和创建方法相似但是我们不需要 create = true

fun test() {
    val file = newFile(getDataFolder(), "path.yml") ?: return
    val loadFromFile = Configuration.loadFromFile(file, Type.YAML)
}

一个小 tip 给不会使用Kotlin的读者
当你在一个变量后面写了 ?: return 的时候
当这个变量为空的时候 就自动结束方法

# 创建并写入File文本

通常是在一些 序列化 的场景中使用

newFile(getDataFolder(), it.path, create = true).writeText(
    Yaml.encodeToString(ShopGoodsBaseData.serializer(), it),
    StandardCharsets.UTF_8
)

# 读取File文本

通常在一些 反序列化 的场景中使用

fun loadData(file: File) {
    file.readText(StandardCharsets.UTF_8).let { text ->
        ShopManager.goods.add(
            Yaml.decodeFromString(ShopGoodsBaseData.serializer(), text)
        )
    }
}

# 根据File转化为配置文件

有些时候 我们是只能拿到对象 拿不到文件的路径的(文件在内存中) 所以我们可以这样写

Configuration.loadFromFile(file, Type.YAML)

还有其他类似方法

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 方法 且是标准的 就可以进行读取

fun loadFromOther(otherConfig: Any, type: Type = Type.YAML, concurrent: Boolean = true)

# 实现文件更新监听

通过 FileWatcher 自动识别文件是否更新
如果有更新则自动重新获取File

object FileListener {

    private val listening = mutableSetOf<File>()
    
    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("监听文件重载了")
        }
    }

}

# 数据存储配置文件

如果想做本地数据存储 更快捷一点的 可以试试用这个方法

val database by lazy {
    createLocal("data/storage/data.yml", type = Type.YAML)
}

这样使用的时候 就会创建这个配置文件 然后这个配置文件会自动保存
所以 不可以手动更改配置文件

# 拓展 - 读取文件夹里的所有Yaml并加载

val read = ArrayList<Configuration>()

@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 (opens new window) 里的方法
这个是由社区开发者 枫溪、嘿鹰、 WhiteSoul、Saukiya、坏黑、Mical 编写的

入门

20分钟

介绍

监听事件

注册事件

本地数据文件

创建配置文件

读取某个文件

创建并写入File文本

读取File文本

根据File转化为配置文件

从Bukkit平台加载配置文件

实现文件更新监听

数据存储配置文件

拓展 - 读取文件夹里的所有Yaml并加载