204 lines
5.4 KiB
Markdown
204 lines
5.4 KiB
Markdown
---
|
||
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<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("监听文件重载了")
|
||
}
|
||
}
|
||
|
||
}
|
||
```
|
||
|
||
## 数据存储配置文件
|
||
|
||
如果想做本地数据存储 更快捷一点的 可以试试用这个方法
|
||
```kotlin
|
||
val database by lazy {
|
||
createLocal("data/storage/data.yml", type = Type.YAML)
|
||
}
|
||
```
|
||
这样使用的时候 就会创建这个配置文件 然后这个配置文件会自动保存
|
||
所以 不可以手动更改配置文件
|
||
|
||
## 拓展 - 读取文件夹里的所有Yaml并加载
|
||
```kotlin
|
||
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](https://github.com/FxRayHughes/Arim) 里的方法
|
||
> 这个是由社区开发者 枫溪、嘿鹰、 WhiteSoul、Saukiya、坏黑、Mical 编写的
|
||
|