本章仅简单分析从玩家连接到服务器到玩家生成世界(Player spawned)之间的数据包交换
- Minecraft 客户端版本:
Bedrock 1.20.80 (模拟客户端, 离线)
- Minecraft 服务器版本:
Bedrock Dedicated Server 1.21.81 (离线)
连接服务器
- 客户端发送
request_network_settings 数据包,包含客户端协议版本,请求建立连接
- 服务器收到
request_network_settings 后发送 network_settings 数据包,包含数据压缩配置信息
- 客户端收到
network_settings 后,发送 login 数据包,包含协议版本和登录 Token (Mojang Key),请求登录到服务器
- 服务器收到
login 后,验证登录(正版需要向 Microsoft 请求),验证通过发送 server_to_client_handshake 数据包,包含通信令牌 JWToken
- 客户端收到
server_to_client_handshake 后,配置连接,发送 client_to_server_handshake 数据包,结束握手
- 服务器收到
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' }
|
加载资源包
- 客户端收到
play_status 后,发送 client_cache_status 数据包,包含客户端是否启用缓存
- 服务器收到
client_cache_status 后,发送 resource_packs_info 和 resource_pack_stack (可能不发送) 数据包,包含服务器资源包信息
- 客户端收到
resource_pack_stack 后,根据情况下载资源包,完成后发送 resource_pack_client_response 数据包,response_status 为 completed,包含资源包的 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: [] }
|
定位服务器
- 服务器收到
resource_pack_client_response 数据包,发送 player_list(包含玩家信息、皮肤等), level_event_generic, set_time 等数据包,同步世界状态
- 服务器发送
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 ..., ... }
|
生成世界
- 客户端收到
start_game 后,发送 request_chunk_radius 数据包,请求区块信息
- 服务器收到
request_chunk_radius 后,发送基本世界信息
- 服务器发送大量区块信息,并开始同步世界状态
- 等待所有区块信息发送完成,服务器发送
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
参考文献