nageyqma·git
HTTPS https://git.nageyqma.icu/nageyqma/odin_next.git SSH git@git.nageyqma.icu:nageyqma/odin_next.git

HTTPS 链接可直接 git clone;推送代码请使用 SSH。

3.9 KB · 92 行raw
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
package com.odtheking.odin.config

import com.google.gson.reflect.TypeToken
import com.odtheking.odin.OdinMod.mc
import com.odtheking.odin.features.impl.dungeon.dungeonwaypoints.DungeonWaypoints.DungeonWaypoint
import com.odtheking.odin.utils.modMessage
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import net.minecraft.util.FileUtil
import java.io.File

private typealias PackMap = MutableMap<String, MutableList<DungeonWaypoint>>

object WaypointPackFileUtils {

    private val legacyConfigFile = File(mc.gameDirectory, "config/odin/dungeon-waypoint-config.json")
    val packsFolder = File(mc.gameDirectory, "config/odin/dungeon-waypoints").apply { mkdirs() }
    private val packType = object : TypeToken<PackMap>() {}.type

    init {
        if (listPackNames().isEmpty()) runCatching {
            val content = legacyConfigFile.takeIf(File::exists)?.readText() ?: DungeonWaypointConfig.gson.toJson(emptyPack())
            packFile("default").writeText(content)
        }.onFailure { it.printStackTrace() }
    }

    private fun packFile(name: String) = File(packsFolder, "$name.json")
    private fun emptyPack(): PackMap = mutableMapOf()

    fun listPackNames(): List<String> =
        packsFolder.listFiles { f -> f.extension == "json" }?.map { it.nameWithoutExtension }?.sorted() ?: emptyList()

    suspend fun loadPack(packName: String): PackMap = withContext(Dispatchers.IO) {
        runCatching {
            packFile(packName).takeIf(File::exists)?.readText()
                ?.let { DungeonWaypointConfig.gson.fromJson<PackMap>(it, packType) } ?: emptyPack()
        }.getOrElse { it.printStackTrace(); emptyPack() }
    }

    suspend fun savePack(packName: String, waypoints: PackMap) = withContext(Dispatchers.IO) {
        runCatching { packFile(packName).writeText(DungeonWaypointConfig.gson.toJson(waypoints)) }.onFailure { it.printStackTrace() }
    }

    suspend fun createPack(packName: String): Boolean = withContext(Dispatchers.IO) {
        val file = packFile(packName)
        when {
            !isValidPackName(packName) -> fail("Invalid pack name!")
            file.exists() -> fail("Pack '$packName' already exists!")
            else -> attempt("Created new pack: $packName", "Failed to create pack!") {
                file.writeText(DungeonWaypointConfig.gson.toJson(emptyPack()))
            }
        }
    }

    suspend fun deletePack(packName: String): Boolean = withContext(Dispatchers.IO) {
        val file = packFile(packName)
        when {
            !file.exists() -> fail("Pack '$packName' does not exist!")
            else -> attempt("Deleted pack: $packName", "Failed to delete pack!") {
                check(file.delete()) { "Failed to delete ${file.path}" }
            }
        }
    }

    suspend fun renamePack(oldName: String, newName: String): Boolean = withContext(Dispatchers.IO) {
        val oldFile = packFile(oldName)
        val newFile = packFile(newName)
        when {
            !isValidPackName(newName) -> fail("Invalid pack name!")
            !oldFile.exists() -> fail("Pack '$oldName' does not exist!")
            newFile.exists() -> fail("Pack '$newName' already exists!")
            else -> attempt("Renamed pack from '$oldName' to '$newName'", "Failed to rename pack!") {
                check(oldFile.renameTo(newFile)) { "Failed to rename ${oldFile.path}" }
            }
        }
    }

    private fun fail(message: String): Boolean {
        modMessage("§c$message")
        return false
    }

    private fun attempt(successMessage: String, failureMessage: String, action: () -> Unit): Boolean =
        runCatching(action).fold(
            onSuccess = { modMessage("§a$successMessage"); true },
            onFailure = { it.printStackTrace(); fail(failureMessage) }
        )

    private fun isValidPackName(name: String) =
        name.isNotBlank() && FileUtil.sanitizeName(name) == name && FileUtil.isPathPartPortable(name)
}