Minecraft Bedrock 网络数据包分析

本章仅简单分析从玩家连接到服务器到玩家生成世界(Player spawned)之间的数据包交换

  • Minecraft 客户端版本: Bedrock 1.20.80 (模拟客户端, 离线)
  • Minecraft 服务器版本: Bedrock Dedicated Server 1.21.81 (离线)

连接服务器

  1. 客户端发送 request_network_settings 数据包,包含客户端协议版本,请求建立连接
  2. 服务器收到 request_network_settings 后发送 network_settings 数据包,包含数据压缩配置信息
  3. 客户端收到 network_settings 后,发送 login 数据包,包含协议版本和登录 Token (Mojang Key),请求登录到服务器
  4. 服务器收到 login 后,验证登录(正版需要向 Microsoft 请求),验证通过发送 server_to_client_handshake 数据包,包含通信令牌 JWToken
  5. 客户端收到 server_to_client_handshake 后,配置连接,发送 client_to_server_handshake 数据包,结束握手
  6. 服务器收到 client_to_server_handshake 后,发送 play_status 数据包,状态为 login_success,结束登录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
C -> S: request_network_settings {
client_protocol: 671
}
S -> C: network_settings {
compression_threshold: 512,
compression_algorithm: 'deflate',
client_throttle: false,
client_throttle_threshold: 0,
client_throttle_scalar: 0
}
C -> S: login {
protocol_version: 671,
tokens: {
identity: 'TOKEN_LOGIN_CHAIN',
client: 'TOKEN_CLIENT'
}
}
S -> C: server_to_client_handshake {
token: 'TOKEN'
}
C -> S: client_to_server_handshake {}
S -> C: play_status {
status: 'login_success'
}

加载资源包

  1. 客户端收到 play_status 后,发送 client_cache_status 数据包,包含客户端是否启用缓存
  2. 服务器收到 client_cache_status 后,发送 resource_packs_inforesource_pack_stack (可能不发送) 数据包,包含服务器资源包信息
  3. 客户端收到 resource_pack_stack 后,根据情况下载资源包,完成后发送 resource_pack_client_response 数据包,response_statuscompleted,包含资源包的 ID,结束资源包加载
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
C -> S: client_cache_status {
enabled: true
}
S -> C: resource_packs_info {
must_accept: false,
has_addons: false,
has_scripts: false,
force_server_packs: false,
behaviour_packs: [],
texture_packs: [],
resource_pack_links: []
}
S -> C: resource_pack_stack {
must_accept: false,
behavior_packs: [],
resource_packs: [],
game_version: '*',
experiments: [],
experiments_previously_used: false,
has_editor_packs: false
}
C -> S: resource_pack_client_response {
response_status: 'completed',
resourcepackids: []
}

定位服务器

  1. 服务器收到 resource_pack_client_response 数据包,发送 player_list(包含玩家信息、皮肤等), level_event_generic, set_time 等数据包,同步世界状态
  2. 服务器发送 start_game 数据包,包含大量游戏参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
S -> C: player_list {
records: [
PlayerListRecord ...,
PlayerListRecord ...,
...
]
}
S -> C: level_event_generic {
event_id: int ...,
nbt: [
Nbt('int', 'ableToSleep', 1),
Nbt('int', 'overworldPlayerCount', 2),
Nbt('int', 'sleepingPlayerCount', 0)
]
}
S -> C: set_time {
time: int ...
}
S -> C: start_game {
entity_id: BigInt ...,
runtime_entity_id: int ...,
player_gamemode: string ...,
...
}

生成世界

  1. 客户端收到 start_game 后,发送 request_chunk_radius 数据包,请求区块信息
  2. 服务器收到 request_chunk_radius 后,发送基本世界信息
  3. 服务器发送大量区块信息,并开始同步世界状态
  4. 等待所有区块信息发送完成,服务器发送 set_health 数据包,设置玩家血量,和 play_status 数据包,状态为 player_spawn,玩家生成
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
C -> S: request_chunk_radius {
chunk_radius: int ...,
max_radius: int ...
}
S -> C: sync_entity_property { ... }
S -> c: set_spawn_position { ... }
S -> C: set_time { ... }
S -> C: set_difficulty {
difficulty: int ...
}
S -> C: set_commands_enabled {
enabled: boolean ...
}
S -> C: update_adventure_settings { ... }
S -> C: update_abilities { ... }
S -> C: game_rules_changed { ... }
S -> C: biome_definition_list {...}
S -> C: available_entity_identifiers { ... }
S -> C: player_fog {
stack: [ ... ]
}
S -> C: camera_presets {
presets: [ ... ]
}
S -> C: update_attributes { ... }
S -> C: creative_content { ... }
S -> C: trim_data { ... }
S -> C: inventory_content { ... }
S -> C: player_hotbar {
selected_slot: int ...,
window_id: 'inventory',
select_slot: true
}
S -> C: crafting_data { ... }
S -> C: available_commands { ... }
S -> C: clientbound_map_item_data { ... }
S -> C: respawn {
position: Vec3 ...,
state: int ...,
runtime_entity_id: BigInt ...
}
S -> C: network_chunk_publisher_update { ... }
S -> C: add_entity { ... }
S -> C: mob_equipment { ... }
S -> C: add_item_entity { ... }
S -> C: set_entity_data { ... }
S -> C: entity_event { ... }
// 开始同步世界状态
...
S -> C: level_chunk { ... }
...
S -> C: move_entity_delta { ... }
...
S -> C: set_health {
health: float ...,
}
S -> C: play_status {
status: 'player_spawn'
}

后记

具体的日志信息可以参考 bedrock-relay/examples/server-client_logs at main · 1503Dev/bedrock-relay 或自己抓包
数据包信息可参考 Data documentation

参考文献