Bedrock Protocol
数据类型
| 类型 | 大小 | 说明 |
|---|---|---|
| i8 (字节) | 1 | |
| u8 (无符号字节) | 1 | |
| i16 (短整型) | 2 | 通常采用小端序编码,有时使用大端序 |
| u16 (无符号短整型) | 2 | 通常采用小端序编码,有时使用大端序 |
| i32 (整型) | 4 | 通常采用小端序编码,有时使用大端序 |
| u32 (无符号整型) | 4 | 通常采用小端序编码,有时使用大端序 |
| i64 (长整型) | 8 | 通常采用小端序编码,有时使用大端序 |
| u64 (无符号长整型) | 8 | 通常采用小端序编码,有时使用大端序 |
| varint i32 (变长整型) | 可变 | 可变长度编码的i32 |
| varint u32 (变长无符号整型) | 可变 | 可变长度编码的u32 |
| varint i64 (变长长整型) | 可变 | 可变长度编码的i64 |
| varint u64 (变长无符号长整型) | 可变 | 可变长度编码的u64 |
| f32 (单精度浮点数) | 4 | 始终采用小端序编码 |
| f64 (双精度浮点数) | 8 | 始终采用小端序编码 |
编码方式
Bedrock协议支持多种整数编码方式,包括:
- 小端序(Little Endian)
- 大端序(Big Endian)
- 变长整数(VarInts)
这些编码方式决定了整数的读写顺序。小端序和大端序都属于字节序(Endianness),主要区别在于字节的读取顺序。更多信息可参考维基百科。
而VarInts是一种可变长度编码方案,可以根据数值大小使用最少的字节数表示整数。与固定字节数(如32位整数固定使用4字节)不同,VarInts会根据数值大小动态调整字节数,这在编码较小数值时能有效节省空间。该编码方式被广泛应用于Google Protocol Buffers、Minecraft等协议中。更多细节请参阅Google Protocol Buffers文档。
游戏数据包头
在Bedrock协议中,GamePacket头部是数据包结构的关键部分。它包含了数据包的元信息,如长度、类型以及源客户端和目标客户端的信息。头部采用紧凑格式编码,通过使用变长整数来减少带宽占用。
GamePacket头部由以下部分组成:
- 数据包长度(varint u32):包含头部和有效载荷的总大小
- 数据包头(14位,编码为varint u32),包含:
- 数据包ID(10位):标识特定的数据包类型
- 发送方子客户端ID(2位):在多客户端场景中标识发送方
- 目标子客户端ID(2位):在多客户端场景中标识接收方
数据包ID最大为10位,意味着最多有2^10(1024)种可能的数据包ID。其中200-299号ID保留给衍生版本使用,可用于自定义数据包等用途。
子客户端字段(发送方和目标方)各占2位,取值范围0-3。这允许在多个玩家共享同一连接(如分屏游戏)的场景下区分最多4个不同客户端。
压缩
Bedrock协议经常使用数据压缩来优化网络性能并减少带宽占用。当出站数据包超过特定阈值大小时,就会启用压缩。压缩算法可根据实际需求配置,主要目标是在保证解压效率的前提下最小化数据大小。
Bedrock支持多种压缩算法,各算法在效率、速度和压缩率方面各有特点。每个连接可以协商使用的算法,不同压缩方法在通信时通过唯一标识符区分。主要使用的算法包括:
- Zlib: 广泛使用的压缩技术,提供可配置的压缩级别。该算法在速度和压缩率之间取得平衡,更高级别的压缩会产生更小的输出但需要更多计算资源。适合压缩大型数据包。
- Snappy: 专为高速压缩和解压设计的算法,更注重性能而非最高压缩率。通常在对速度要求较高的小型数据包场景中使用。
- 无压缩: 某些情况下(如小型数据包或调试目的)可能不需要压缩。如果数据包大小低于特定阈值,可能会完全跳过压缩以避免额外开销。
(简而言之...在生产环境中始终使用Zlib,因为它是最佳选择,其他算法要么存在问题,要么不适合生产环境)
只有当待压缩数据大小超过预设阈值时才会启用压缩。每个算法都有可配置的阈值,若数据大小低于此阈值,数据包将直接发送而不压缩。
在Bedrock中,每个数据包开头都包含压缩标识符,这是关键的元数据,用于指示数据包是否压缩以及使用的压缩算法。该标识符让接收端知道如何处理传入数据——是需要解压还是可以直接读取。
以下是可用压缩方法对应的标识符:
- Zlib: 0x00
- Snappy: 0x01
- 无压缩: 0xFF或0xFFFF(在网络设置中)
该压缩ID以u8类型存储在每个游戏数据包之前,在网络设置中则以u16类型存储,用于定义默认的压缩方法。
加密
待完善...
缓存
待完善...
登录流程
Bedrock协议的登录序列包含多个阶段:
- 预登录(PreLogin)
- 登录(Login)
- 生成(Spawn)
- 游戏(Play)
网络设置请求
(客户端 -> 服务器)
自v554(1.19.20)版本起,这是客户端发送的第一个数据包。NetworkSettingsRequestPacket仅包含一个字段,即客户端当前的协议版本。
这是第一个预登录阶段的数据包。
网络设置
(服务器 -> 客户端)
用于设置连接信息,这是初始化压缩配置的地方。有关压缩的更多信息,请参阅压缩部分。
这是最后一个预登录阶段的数据包。
登录
(客户端 -> 服务器)
LoginPacket包含大量客户端信息,如客户端协议版本(再次出现)。由于在新版本中已弃用,不应再使用此字段。
它还包含一个JSON格式的JWT数组(称为证书链),以字符串形式编码。这些JWT包含经过验证的客户端信息。该数组至少包含1个JWT(未通过Xbox Live服务认证),最多包含3个JWT(已通过Xbox Live服务认证)。它们存储了玩家显示名称、xuid和uuid等数据,认证状态下还会包含沙盒和标题ID。如果缺少第2和第3个JWT,则表示玩家未登录Xbox Live账户,当前未认证,因此发送的数据不可信任。
LoginPacket还包含另一个以字符串编码的JWT,即原始令牌(raw token)。它包含玩家相关信息,如:
- SelfSignedId
- ServerAddress = (未解析的URL,如适用)
- ClientRandomId
- 皮肤ID
- 皮肤数据
- 皮肤图像宽度
- 皮肤图像高度
- 披风数据
- 披风图像宽度
- 披风图像高度
- 皮肤资源补丁
- 皮肤几何数据
- 皮肤几何数据引擎版本
- 皮肤动画数据
- PlayFabId
- 动画图像数据 = 包含以下字段的数组:
- 类型
- 图像
- 图像宽度
- 图像高度
- 帧数
- 动画表达式
- 手臂尺寸
- 皮肤颜色
- 角色部件 = 包含以下字段的数组:
- 包ID
- 部件ID
- 是否默认
- 部件类型
- 产品ID
- 部件色调颜色 = 包含以下字段的数组:
- 部件类型
- 颜色 = 颜色十六进制字符串数组
- 是否教育版模式(如适用)
- 租户ID(教育版)
- AD角色(教育版)
- 是否编辑器模式
- 游戏版本
- 设备型号
- 设备操作系统 = (参见枚举:BuildPlatform)
- 默认输入模式 = (参见枚举:InputMode)
- 当前输入模式 = (参见枚举:InputMode)
- UI配置文件 = (参见枚举:UIProfile)
- GUI缩放比例
- 语言代码
- 平台用户ID
- 第三方名称
- 仅第三方名称
- 平台在线ID
- 平台离线ID
- 设备ID
- 受信任的皮肤
- 高级皮肤
- 角色皮肤
- 覆盖皮肤
- 经典皮肤上的披风
- 披风ID
- 兼容客户端区块生成
这是登录阶段的第一个数据包。
服务端到客户端握手(可选)
(服务器 -> 客户端)
如果发送此数据包,则会初始化加密。更多信息请参阅加密部分。
待完善...
客户端到服务端握手(可选)
(客户端 -> 服务器)
如果客户端正确初始化了加密,会通过此空数据包响应,表示握手成功。
资源包信息
(服务器 -> 客户端)
发送可用资源包和附加组件的元数据。如需发送任何类型的资源包,请参阅发送资源包部分。如果ResourcePacksInfo和ResourcePacksStack都为空,这些数据包可以批量处理。此时只需发送一个ClientCacheStatus(可选)和ResourcePackClientResponse。
客户端缓存状态(可选)
(客户端 -> 服务器)
如果客户端支持缓存,则会发送此数据包,包含一个布尔值表示缓存支持状态。缓存支持为协议启用了某些可能性,更多信息请参阅缓存部分。
资源包客户端响应
(客户端 -> 服务器)
对前一个ResourcePacksInfoPacket的响应,描述资源包下载的当前状态。如需发送任何类型的资源包,请参阅发送资源包部分。
资源包堆栈
(服务器 -> 客户端)
总是对ResourcePackClientResponse的回复,直到客户端下载完所有资源包。
资源包客户端响应
(客户端 -> 服务器)
对前一个ResourcePacksInfoPacket的响应,描述资源包下载的当前状态。如需发送任何类型的资源包,请参阅发送资源包部分。如果此数据包表明客户端已下载所有必需资源包,则可以继续登录流程。
游戏状态
(服务器 -> 客户端)
包含一个枚举值表示游戏状态(登录流程/阶段的进度)。如果登录阶段成功,枚举值应设置为LoginSuccess。
这是登录阶段的最后一个数据包。
开始游戏数据包
(服务器 -> 客户端)
这是生成阶段的第一个数据包。
游戏状态
包含一个枚举值表示游戏状态(登录流程/阶段的进度)。如果生成阶段成功,枚举值应设置为PlayerSpawn。
这是生成阶段的最后一个数据包。
发送资源包
待完善...
发送区块
待完善...
发送库存内容
待完善...
实现方案
并非所有内容都能通过文档详细解释,因此参考现有实现非常有帮助。以下是Bedrock协议的一些实现方案:
| 名称 | 描述 | 语言 |
|---|---|---|
| CloudburstMC/Protocol | Minecraft基岩版协议库 | Java |
| PMMP/BedrockProtocol | PHP实现的Minecraft基岩版协议 | PHP |
| gophertunnel | 用Go编写的Minecraft基岩版通用库 | Go |
| bedrockrs | Rust实现的MCBE通用库 | Rust |
本页面仍在完善中,欢迎贡献内容。

