Skip to content

数据同步 (CPDC)

CrossPlatformDataContainer -- 纵向(Server↔Client)对象级 KV 数据容器,支持同步与本地持久化。

前置知识

需要了解 网络系统 的 Wrapper 类型。横向跨服同步请查看 ServerSync

Quick Start

kotlin
val key = ResourceIdWrapper.of("myplugin", "player_level")

// 服务端写入 SYNC 数据 -> 自动同步到客户端
cpdc.setInt(key, 10)

// 任一端读取
val level = cpdc.getInt(key) ?: 1

API Reference

CrossPersistentPlatformDataContainer

方法参数返回值说明
getBoolean(key)ResourceIdWrapperBoolean?读取布尔值
getInt(key)ResourceIdWrapperInt?读取整数
getLong(key)ResourceIdWrapperLong?读取长整数
getDouble(key)ResourceIdWrapperDouble?读取双精度浮点
getString(key)ResourceIdWrapperString?读取字符串
getBytes(key)ResourceIdWrapperByteArray?读取字节数组
getObject(key)ResourceIdWrapperAny?读取对象
getKeys()Set<ResourceIdWrapper>获取所有键
setBoolean(key, value)ResourceIdWrapper, Boolean写入布尔值
setInt(key, value)ResourceIdWrapper, Int写入整数
setLong(key, value)ResourceIdWrapper, Long写入长整数
setDouble(key, value)ResourceIdWrapper, Double写入双精度浮点
setString(key, value)ResourceIdWrapper, String写入字符串
setBytes(key, value)ResourceIdWrapper, ByteArray写入字节数组
setObject(key, value)ResourceIdWrapper, Any写入对象
remove(key)ResourceIdWrapper删除键

CrossPlatformDataScope

说明
LOCAL本端持久化,每个端独立存储,不同步
SYNC服务端权威同步,自动推送到客户端

获取 CPDC 容器

Forge 客户端:

目标类型方法签名
物品ItemStack.getCrossPlatformDataContainer(scope)
实体Entity.getCrossPlatformDataContainer(scope)
区块LevelChunk.getCrossPlatformDataContainer(scope)
方块BlockPos.getCrossPlatformDataContainer(level, scope)
槽位物品AbstractContainerMenu.getCrossPlatformDataContainer(slotIndex, scope)
BUIServerAPI 存储getBUILocalStorageContainer(storeId)

Spigot 服务端:

目标类型方法签名
物品ItemStack.getCrossPlatformPersistentDataContainer(scope)
实体Entity.getCrossPlatformPersistentDataContainer(scope)
区块Chunk.getCrossPlatformPersistentDataContainer(scope)
方块Block.getCrossPlatformPersistentDataContainer(scope)

数据值类型

类型Kotlin 类说明
BoolCrossPlatformDataValue.Bool布尔值
Int32CrossPlatformDataValue.Int3232 位整数
Int64CrossPlatformDataValue.Int6464 位整数
Float64CrossPlatformDataValue.Float64双精度浮点
TextCrossPlatformDataValue.Text字符串
BytesCrossPlatformDataValue.Bytes字节数组
ObjectCrossPlatformDataValue.Object序列化对象(含 typeHint)

作用域详解

LOCAL - 本地数据

仅在当前端存储,不同步。

使用场景: 临时缓存、客户端 UI 状态、服务端内部状态。

kotlin
// 客户端:存储 UI 偏好
val cpdc = entity.getCrossPlatformDataContainer(CrossPlatformDataScope.LOCAL)
cpdc.setBoolean(showHudKey, true)

SYNC - 同步数据

服务端是权威,写入后自动同步到客户端。

使用场景: 需要双端访问的数据、UI 显示数据、游戏状态。

kotlin
// 服务端写入
val cpdc = entity.getCrossPlatformPersistentDataContainer(CrossPlatformDataScope.SYNC)
cpdc.setInt(levelKey, 10)
// -> 自动同步到客户端,客户端读取即可获得最新值

同步流程

完整示例

kotlin
// === 服务端(Spigot) ===
import com.behemiron.engine.spigot.util.crossplatform.*

@Service
class ItemDataService {
    private val rarityKey = ResourceIdWrapper.of("mygame", "rarity")
    private val levelKey = ResourceIdWrapper.of("mygame", "level")
    private val cacheKey = ResourceIdWrapper.of("mygame", "last_check")

    // 设置物品品质(SYNC -> 客户端可读取用于 UI 显示)
    fun setItemRarity(item: ItemStack, rarity: String) {
        val cpdc = item.getCrossPlatformPersistentDataContainer(CrossPlatformDataScope.SYNC)
        cpdc.setString(rarityKey, rarity)
        cpdc.setInt(levelKey, calculateLevel(rarity))
    }

    // 服务端内部缓存(LOCAL -> 仅服务端可见)
    fun markChecked(entity: Entity) {
        val cpdc = entity.getCrossPlatformPersistentDataContainer(CrossPlatformDataScope.LOCAL)
        cpdc.setLong(cacheKey, System.currentTimeMillis())
    }
}

// === 客户端(Forge) ===
import com.behemiron.engine.forge.util.crossplatform.*

class ItemTooltipRenderer {
    private val rarityKey = ResourceIdWrapper.of("mygame", "rarity")

    // 读取服务端同步过来的品质数据
    fun getRarity(itemStack: ItemStack): String {
        val cpdc = itemStack.getCrossPlatformDataContainer(CrossPlatformDataScope.SYNC)
        return cpdc.getString(rarityKey) ?: "common"
    }
}

注意事项

  • 物品 SYNC 写入限制:直接对 ItemStack 获取的 SYNC 容器是只读的。要写入物品的 SYNC 数据,必须通过 AbstractContainerMenu.getCrossPlatformDataContainer(slotIndex, SYNC) 使用槽位寻址。
  • 使用命名空间作为 key 前缀(ResourceIdWrapper.of("myplugin", "xxx")),避免与其他插件冲突。
  • 避免滥用 setObject,序列化开销较大,优先使用具体类型方法。
  • 对于多个数据变更,尽量批量提交以减少同步开销。