外观
🧵 Kotlin 委托属性
DelegatePropertyAddon 提供玩家字符串 KV 容器,可用于简单自定义计数。它是玩家同步数据,不是跨服实时共享缓存。
将 DSL 放在自己的插件里
InvSync 会 relocate 自己的 Kotlin 运行时。含 ReadWriteProperty、KProperty、函数类型的 DSL 不作为插件公开调用边界,请将下面的辅助类放到你自己的项目。
kotlin
import com.xbaimiao.invsync.api.delegate.DelegatePropertyAddon
import org.bukkit.entity.Player
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
// 在自己的插件中定义,避免链接到 InvSync 已 relocate 的 Kotlin DSL。
class SyncedLong(private val key: String) : ReadWriteProperty<Player, Long> {
override fun getValue(thisRef: Player, property: KProperty<*>): Long {
val map = DelegatePropertyAddon.playerDataMap(thisRef)
// 约定在正确的玩家线程访问,避免核心异步采集期间任意修改。
return map[key]?.toLongOrNull() ?: 0L
}
override fun setValue(thisRef: Player, property: KProperty<*>, value: Long) {
val map = DelegatePropertyAddon.playerDataMap(thisRef)
val old = map[key]
// 对未知格式不写默认值覆盖,交给专门迁移逻辑处理。
check(old == null || old.toLongOrNull() != null) { "计数字段格式未知" }
map[key] = value.toString()
}
}
var Player.killCount: Long by SyncedLong("myplugin:kill-count")
// 只在 InvSync 同步完成之后、正确玩家线程中进行业务修改。
fun recordKill(player: Player) {
player.killCount += 1
}边界
- 外层容器并发实现不代表返回的
HashMap可以跨线程任意读写。 - key 应使用自己插件前缀。委托容器内部 key 不要依赖不区分大小写的行为。
- 字符串通过 UTF 写入,不用于巨大 JSON、背包或任意大文本。
- 真正退出后核心会清理容器,不缓存旧 Map 引用;
removePlayer是内部生命周期方法,第三方不要调用。 - 读取默认值不表示数据已成功加载;先监听同步完成,加载失败不进行业务更新。
- 不能用它实现离线奖励、跨节点同时修改或原子经济余额。
复杂格式、并发控制和失败状态建议使用独立 Addon。上述代码是文档示例,未执行插件编译;按项目实际调度与业务生命周期接入。