Purtmars Plugins
插件️Chemdah开始开发文档

存档键映射

存档键映射

本文由 AI 辅助生成,可能存在疏漏或与当前版本不一致。Chemdah 为闭源付费插件,请以你使用的版本、api 依赖与实际运行行为为准;疑问请联系作者或售后群(见 服务)。

关系型数据库(user_dataquest_datavariables 等表)落库时,Chemdah 在内存与脚本里始终使用逻辑键(例如 quest.complete.xxxlevel)。若需要在库里使用另一套存储键(加前缀、按表区分命名等),可实现 PersistenceKeyCodec 并通过 PersistenceKeyCodecs 注册。

未注册任何实现时,逻辑键与库表键一致,行为与旧版相同。

适用场景

  • 多插件共用同一数据库,希望 Chemdah 的键带统一前缀,避免与其它表的 key 冲突。
  • 运维侧按前缀批量检索或迁移数据。
  • 仅对某一类数据(例如只改玩家档案)做映射,任务键、全局变量键保持原样。

仅影响内置 SQL/SQLite 等关系型实现(DatabaseSQLDatabaseSQLite 及其子类)。若整库替换为自定义 Database 实现,是否走本 API 由该实现自行决定。

键空间

枚举对应数据
PLAYER玩家档案持久化数据(playerProfile.persistentDataContainer 等)
QUEST任务实例相关键
VARIABLE全局变量

三套键空间相互独立,同一逻辑名在不同 scope 下可以映射到不同的存储键,注册实现时请按 scope 分支处理。

注册时机

在附属插件 onLoad / onEnable 中注册即可,需早于玩家进服、且早于 Chemdah 完成数据库初始化。

import ink.ptms.chemdah.api.PersistenceKeyCodec
import ink.ptms.chemdah.api.PersistenceKeyCodecs
import ink.ptms.chemdah.api.PersistenceScope

class PlayerKeyPrefix(private val prefix: String) : PersistenceKeyCodec {

    override fun encode(scope: PersistenceScope, logicalKey: String): String {
        if (scope != PersistenceScope.PLAYER) {
            return logicalKey
        }
        return prefix + logicalKey
    }

    override fun decode(scope: PersistenceScope, storageKey: String): String? {
        if (scope != PersistenceScope.PLAYER) {
            return storageKey
        }
        if (!storageKey.startsWith(prefix)) {
            return null
        }
        return storageKey.removePrefix(prefix)
    }
}

override fun onEnable() {
    PersistenceKeyCodecs.register(PlayerKeyPrefix("p:"))
}

也可使用 Chemdah.registerPersistenceKeyCodec(codec),内部同样调用 PersistenceKeyCodecs.register

上例中逻辑键 level 写入库表为 p:level;Kether、脚本与 persistentDataContainer["level"] 仍使用 level

按 scope 使用不同前缀

object MyCodec : PersistenceKeyCodec {

    override fun encode(scope: PersistenceScope, logicalKey: String): String {
        return when (scope) {
            PersistenceScope.PLAYER -> "u/$logicalKey"
            PersistenceScope.QUEST -> "q/$logicalKey"
            PersistenceScope.VARIABLE -> "g/$logicalKey"
        }
    }

    override fun decode(scope: PersistenceScope, storageKey: String): String? {
        val p = when (scope) {
            PersistenceScope.PLAYER -> "u/"
            PersistenceScope.QUEST -> "q/"
            PersistenceScope.VARIABLE -> "g/"
        }
        if (!storageKey.startsWith(p)) {
            return null
        }
        return storageKey.removePrefix(p)
    }
}

API 说明

方法说明
PersistenceKeyCodecs.register(codec)注册实现;后注册者覆盖前者
PersistenceKeyCodecs.encode(scope, logicalKey)逻辑键 → 库表键(内部在 INSERT/UPDATE 前调用)
PersistenceKeyCodecs.decode(scope, storageKey)库表键 → 逻辑键(内部在 SELECT 后调用)

一般业务代码只需实现并注册 PersistenceKeyCodec,无需直接调用 encode / decode

decode 返回 null 时,Chemdah 会把读到的存储键原样当作逻辑键加载,用于兼容历史上未带前缀的旧数据。

注意事项

  • 库表 key / name 列长度通常为 64encode 结果过长会导致落库失败,请在实现中控制长度或制定截断策略。
  • 上线后修改映射规则时,库里已有行仍是旧存储键;无法识别的键会按上文兼容逻辑加载。若要彻底改名,需自行编写数据迁移脚本。
  • 同一时间仅有一个生效的 PersistenceKeyCodec(TabooLib PlatformFactory 注册),不要在多个插件里互相覆盖而不自知。

相关类型

  • ink.ptms.chemdah.api.PersistenceKeyCodecs — 注册与编解码入口
  • ink.ptms.chemdah.api.PersistenceKeyCodec — 自定义映射接口
  • ink.ptms.chemdah.api.PersistenceScope — 键空间枚举

On this page