update protocol, add some doc

This commit is contained in:
extremeheat 2021-02-07 19:45:46 -05:00
commit 1a7205b3d1
5 changed files with 456 additions and 48 deletions

View file

@ -14,138 +14,356 @@ nbt: native
!import: packet_map.yml
!StartDocs: Packets
# # Login Sequence
# The login process is as follows:
#
# C→S: [Login](#packet_login)
# S→C: [Server To Client Handshake](#packet_server_to_client_handshake)
# C→S: [Client To Server Handshake](#packet_client_to_server_handshake)
# S→C: [Play Status (Login success)](#packet_play_status)
# To spawn, the following packets should be sent, in order, after the ones above:
#
# S→C: [Resource Packs Info](#packet_resource_packs_info)
# C→S: [Resource Pack Client Response](#packet_resource_pack_client_response)
# S→C: [Resource Pack Stack](#packet_resource_pack_stack)
# C→S: [Resource Pack Client Response](#packet_resource_pack_client_response)
# S→C: [Start Game](#packet_start_game)
# S→C: [Creative Content](#packet_creative_content)
# S→C: [Biome Definition List](#packet_biome_definition_list)
# S→C: [Chunks](#packet_level_chunk)
# S→C: [Play Status (Player spawn)](#packet_play_status)
# If there are no resource packs being sent, a Resource Pack Stack can be sent directly
# after Resource Packs Info to avoid the client responses.
packet_login:
!id: 0x01
!bound: client
protocol_version: i32
# The combined size of the `chain` and `client_data`
payload_size: varint
# JSON array of JWT data: contains the display name, UUID and XUID
# It should be signed by the Mojang public key
chain: LittleString
# Skin related data
client_data: LittleString
packet_play_status:
!id: 0x02
!bound: server
status: i32
status: i32 =>
# Sent after Login has been successfully decoded and the player has logged in
0: login_success
# Displays "Could not connect: Outdated client!"
1: failed_client
# Displays "Could not connect: Outdated server!"
2: failed_spawn
# Sent after world data to spawn the player
3: player_spawn
# Displays "Unable to connect to world. Your school does not have access to this server."
4: failed_invalid_tenant
# Displays "The server is not running Minecraft: Education Edition. Failed to connect."
5: failed_vanilla_edu
# Displays "The server is running an incompatible edition of Minecraft. Failed to connect."
6: failed_edu_vanilla
# Displays "Wow this server is popular! Check back later to see if space opens up. Server Full"
7: failed_server_full
packet_server_to_client_handshake:
!id: 0x03
!bound: server
# Contains the salt to complete the Diffie-Hellman key exchange
token: string
# Sent by the client in response to a Server To Client Handshake packet
# sent by the server. It is the first encrypted packet in the login handshake
# and serves as a confirmation that encryption is correctly initialized client side.
# It has no fields.
packet_client_to_server_handshake:
!id: 0x04
!bound: client
# Sent by the server to disconnect a client.
packet_disconnect:
!id: 0x05
!bound: server
# Specifies if the disconnection screen should be hidden when the client is disconnected,
# meaning it will be sent directly to the main menu.
hide_disconnect_reason: bool
# An optional message to show when disconnected.
message: string
packet_resource_packs_info:
!id: 0x06
!bound: server
# If the resource pack requires the client accept it.
must_accept: bool
# If scripting is enabled.
has_scripts: bool
# A list of behaviour packs that the client needs to download before joining the server.
# All of these behaviour packs will be applied together.
behaviour_packs: BehaviourPackInfos
# A list of resource packs that the client needs to download before joining the server.
# The order of these resource packs is not relevant in this packet. It is however important in the Resource Pack Stack packet.
texture_packs: TexturePackInfos
packet_resource_pack_stack:
!id: 0x07
!bound: server
# If the resource pack must be accepted for the player to join the server.
must_accept: bool
# [inline]
behavior_packs: ResourcePackIdVersions
# [inline]
resource_packs: ResourcePackIdVersions
game_version: string
experiments: Experiments
experiments_previously_toggled: bool
experiments: Experiments # ??? such random fields
experiments_previously_used: bool
packet_resource_pack_client_response:
!id: 0x08
!bound: client
response_status: u8
response_status: u8 =>
0: none
1: refused
2: send_packs
3: have_all_packs
4: completed
# All of the pack IDs.
resourcepackids: ResourcePackIds
# Sent by the client to the server to send chat messages, and by the server to the client
# to forward or send messages, which may be chat, popups, tips etc.
## https://github.com/pmmp/PocketMine-MP/blob/a43b46a93cb127f037c879b5d8c29cda251dd60c/src/pocketmine/network/mcpe/protocol/TextPacket.php
## https://github.com/Sandertv/gophertunnel/blob/05ac3f843dd60d48b9ca0ab275cda8d9e85d8c43/minecraft/protocol/packet/text.go
packet_text:
!id: 0x09
!bound: both
type: u8
type: u8 =>
0: raw
1: chat
2: translation
3: popup
4: jukebox_popup
5: tip
6: system
7: whisper
8: announcement
9: json_whisper
10: json
# NeedsTranslation specifies if any of the messages need to be translated. It seems that where % is found
# in translatable text types, these are translated regardless of this bool. Translatable text types
# include TextTypeTip, TextTypePopup and TextTypeJukeboxPopup.
needs_translation: bool
_: type?
if chat or whisper or announcement:
sourceName: string
if raw or tip or system or json_whisper or json:
message: string
if translation or popup or jukebox_popup:
message: string
paramaters: string[]varint
# The XUID of the player who sent this message.
xuid: string
# PlatformChatID is an identifier only set for particular platforms when chatting (presumably only for
# Nintendo Switch). It is otherwise an empty string, and is used to decide which players are able to
# chat with each other.
platform_chat_id: string
# For additional information and examples of all the chat types above, see here: https://imgur.com/a/KhcFscg
# Sent by the server to update the current time client-side. The client actually advances time
# client-side by itself, so this packet does not need to be sent each tick. It is merely a means
# of synchronizing time between server and client.
packet_set_time:
!id: 0x0a
!bound: server
# Time is the current time. The time is not limited to 24000 (time of day), but continues
# progressing after that.
time: zigzag32
# Sent by the server to send information about the world the player will be spawned in.
packet_start_game:
!id: 0x0b
!bound: server
# The unique ID of the player. The unique ID is a value that remains consistent across
# different sessions of the same world, but most unofficial servers simply fill the
# runtime ID of the entity out for this field.
entity_id: zigzag64
# The runtime ID of the player. The runtime ID is unique for each world session,
# and entities are generally identified in packets using this runtime ID.
runtime_entity_id: varint
player_gamemode: zigzag32
# The spawn position of the player in the world. In servers this is often the same as the
# world's spawn position found below.
spawn: vec3f
# The pitch and yaw of the player
rotation: vec3f
# The seed used to generate the world. Unlike in Java edition, the seed is a 32bit Integer here.
seed: zigzag32
biome_type: li16
biome_name: string
# Dimension is the ID of the dimension that the player spawns in. It is a value from 0-2,
# with 0 being the overworld, 1 being the nether and 2 being the end.
dimension: zigzag32
# Generator is the generator used for the world. It is a value from 0-4, with 0 being old
# limited worlds, 1 being infinite worlds, 2 being flat worlds, 3 being nether worlds and
# 4 being end worlds. A value of 0 will actually make the client stop rendering chunks you
# send beyond the world limit.
generator: zigzag32
# The game mode that a player gets when it first spawns in the world. It is shown in the
# settings and is used if the Player Gamemode is set to 5.
gamemode: zigzag32
# Difficulty is the difficulty of the world. It is a value from 0-3, with 0 being peaceful,
# 1 being easy, 2 being normal and 3 being hard.
difficulty: zigzag32
x: zigzag32
y: varint
z: zigzag32
# The block on which the world spawn of the world. This coordinate has no effect on the place
# that the client spawns, but it does have an effect on the direction that a compass poInts.
spawn_position: BlockCoordinates
# Defines if achievements are disabled in the world. The client crashes if this value is set
# to true while the player's or the world's game mode is creative, and it's recommended to simply
# always set this to false as a server.
has_achievements_disabled: bool
# The time at which the day cycle was locked if the day cycle is disabled using the respective
# game rule. The client will maIntain this time as Boolean as the day cycle is disabled.
day_cycle_stop_time: zigzag32
# Some Minecraft: Education Edition field that specifies what 'region' the world was from,
# with 0 being None, 1 being RestOfWorld, and 2 being China. The actual use of this field is unknown.
edu_offer: zigzag32
# Specifies if the world has education edition features enabled, such as the blocks or entities
# specific to education edition.
has_edu_features_enabled: bool
edu_product_uuid_: string
# The level specifying the Intensity of the rain falling. When set to 0, no rain falls at all.
rain_level: lf32
lightning_level: lf32
# The level specifying the Intensity of the thunder. This may actually be set independently
# from the rain level, meaning dark clouds can be produced without rain.
has_confirmed_platform_locked_content: bool
# Specifies if the world is a multi-player game. This should always be set to true for servers.
is_multiplayer: bool
# Specifies if LAN broadcast was Intended to be enabled for the world.
broadcast_to_lan: bool
# The mode used to broadcast the joined game across XBOX Live.
xbox_live_broadcast_mode: varint
# The mode used to broadcast the joined game across the platform.
platform_broadcast_mode: varint
# If commands are enabled for the player. It is recommended to always set this to true on the
# server, as setting it to false means the player cannot, under any circumstance, use a command.
enable_commands: bool
# Specifies if the texture pack the world might hold is required, meaning the client was
# forced to download it before joining.
is_texturepacks_required: bool
# Defines game rules currently active with their respective values. The value of these game
# rules may be either 'bool', 'Int32' or 'Float32'. Some game rules are server side only,
# and don't necessarily need to be sent to the client.
gamerules: GameRules
experiments: Experiments
experiments_previously_toggled: bool
experiments_previously_used: bool
# Specifies if the world had the bonus map setting enabled when generating it.
# It does not have any effect client-side.
bonus_chest: bool
# Specifies if the world has the start with map setting enabled, meaning each
# joining player obtains a map. This should always be set to false, because the
# client obtains a map all on its own accord if this is set to true.
map_enabled: bool
# The permission level of the player. It is a value from 0-3, with 0 being visitor,
# 1 being member, 2 being operator and 3 being custom.
permission_level: zigzag32
# The radius around the player in which chunks are ticked. Most servers set this value
# to a fixed number, as it does not necessarily affect anything client-side.
server_chunk_tick_range: li32
# Specifies if the texture pack of the world is locked, meaning it cannot be disabled
# from the world. This is typically set for worlds on the marketplace that have a dedicated
# texture pack.
has_locked_behavior_pack: bool
# Specifies if the texture pack of the world is locked, meaning it cannot be disabled from the
# world. This is typically set for worlds on the marketplace that have a dedicated texture pack.
has_locked_resource_pack: bool
# Specifies if the world from the server was from a locked world template.
# For servers this should always be set to false.
is_from_locked_world_template: bool
msa_gamertags_only: bool
# Specifies if the world from the server was from a locked world template.
# For servers this should always be set to false.
is_from_world_template: bool
# Specifies if the world was a template that locks all settings that change properties
# above in the settings GUI. It is recommended to set this to true for servers that
# do not allow things such as setting game rules through the GUI.
is_world_template_option_locked: bool
# A hack that Mojang put in place to preserve backwards compatibility with old villagers.
# The his never actually read though, so it has no functionality.
only_spawn_v1_villagers: bool
# The version of the game from which Vanilla features will be used.
# The exact function of this field isn't clear.
game_version: string
limited_world_width_: li32
limited_world_length_: li32
is_new_nether_: bool
experimental_gameplay_override: bool
# A base64 encoded world ID that is used to identify the world.
level_id: string
# The name of the world that the player is joining. Note that this field shows up
# above the player list for the rest of the game session, and cannot be changed.
# Setting the server name to this field is recommended.
world_name: string
# A UUID specific to the premium world template that might have been used to
# generate the world. Servers should always fill out an empty String for this.
premium_world_template_id: string
# Specifies if the world was a trial world, meaning features are limited and there
# is a time limit on the world.
is_trial: bool
movement_type: zigzag32
# Specifies if the client or server is authoritative over the movement of the player,
# meaning it controls the movement of it.
## https://github.com/pmmp/PocketMine-MP/blob/a43b46a93cb127f037c879b5d8c29cda251dd60c/src/pocketmine/network/mcpe/protocol/types/PlayerMovementType.php#L26
movement_authority: zigzag32 =>
0: client
1: server
# PlayerAuthInputPacket + a bunch of junk that solves a nonexisting problem
2: server_v2_rewind
# The total time in ticks that has elapsed since the start of the world.
current_tick: li64
# The seed used to seed the random used to produce enchantments in the enchantment table.
# Note that the exact correct random implementation must be used to produce the correct
# results both client- and server-side.
enchantment_seed: zigzag32
block_palette: BlockPalette
## This is not sent anymore in protocol versions > 419 (Bedrock Edition v1.16.100)
## A list of all blocks registered on the server.
## block_palette: BlockPalette
# A list of all items with their legacy IDs which are available in the game.
# Failing to send any of the items that are in the game will crash mobile clients.
itemstates: Itemstates
# A unique ID specifying the multi-player session of the player.
# A random UUID should be filled out for this field.
multiplayer_correlation_id: string
server_authoritative_inventory: bool
packet_add_player:
!id: 0x0c
!bound: server
# UUID is the UUID of the player. It is the same UUID that the client sent in the
# Login packet at the start of the session. A player with this UUID must exist
# in the player list (built up using the Player List packet) for it to show up in-game.
uuid: uuid
# Username is the name of the player. This username is the username that will be
# set as the initial name tag of the player.
username: string
# The unique ID of the player. The unique ID is a value that remains consistent
# across different sessions of the same world, but most unoffical servers simply
# fill the runtime ID of the player out for this field.
entity_id_self: zigzag64
# The runtime ID of the player. The runtime ID is unique for each world session,
# and entities are generally identified in packets using this runtime ID.
runtime_entity_id: varint
# An identifier only set for particular platforms when chatting (presumably only for
# Nintendo Switch). It is otherwise an empty string, and is used to decide which players
# are able to chat with each other.
platform_chat_id: string
x: lf32
y: lf32

View file

@ -1,3 +1,5 @@
!StartDocs: Types
BehaviourPackInfos: []li16
uuid: string
version: string
@ -18,8 +20,11 @@ TexturePackInfos: []li16
rtx_enabled: bool
ResourcePackIdVersions: []varint
# The ID of the resource pack.
uuid: string
# The version of the resource pack.
version: string
# The subpack name of the resource pack.
name: string
ResourcePackIds: string[]varint

View file

@ -2361,7 +2361,22 @@
[
{
"name": "status",
"type": "i32"
"type": [
"mapper",
{
"type": "i32",
"mappings": {
"0": "login_success",
"1": "failed_client",
"2": "failed_spawn",
"3": "player_spawn",
"4": "failed_invalid_tenant",
"5": "failed_vanilla_edu",
"6": "failed_edu_vanilla",
"7": "failed_server_full"
}
}
]
}
]
],
@ -2436,7 +2451,7 @@
"type": "Experiments"
},
{
"name": "experiments_previously_toggled",
"name": "experiments_previously_used",
"type": "bool"
}
]
@ -2446,7 +2461,19 @@
[
{
"name": "response_status",
"type": "u8"
"type": [
"mapper",
{
"type": "u8",
"mappings": {
"0": "none",
"1": "refused",
"2": "send_packs",
"3": "have_all_packs",
"4": "completed"
}
}
]
},
{
"name": "resourcepackids",
@ -2459,7 +2486,178 @@
[
{
"name": "type",
"type": "u8"
"type": [
"mapper",
{
"type": "u8",
"mappings": {
"0": "raw",
"1": "chat",
"2": "translation",
"3": "popup",
"4": "jukebox_popup",
"5": "tip",
"6": "system",
"7": "whisper",
"8": "announcement",
"9": "json_whisper",
"10": "json"
}
}
]
},
{
"name": "needs_translation",
"type": "bool"
},
{
"anon": true,
"type": [
"switch",
{
"compareTo": "type",
"fields": {
"chat": [
"container",
[
{
"name": "sourceName",
"type": "string"
}
]
],
"whisper": [
"container",
[
{
"name": "sourceName",
"type": "string"
}
]
],
"announcement": [
"container",
[
{
"name": "sourceName",
"type": "string"
}
]
],
"raw": [
"container",
[
{
"name": "message",
"type": "string"
}
]
],
"tip": [
"container",
[
{
"name": "message",
"type": "string"
}
]
],
"system": [
"container",
[
{
"name": "message",
"type": "string"
}
]
],
"json_whisper": [
"container",
[
{
"name": "message",
"type": "string"
}
]
],
"json": [
"container",
[
{
"name": "message",
"type": "string"
}
]
],
"translation": [
"container",
[
{
"name": "message",
"type": "string"
},
{
"name": "paramaters",
"type": [
"array",
{
"countType": "varint",
"type": "string"
}
]
}
]
],
"popup": [
"container",
[
{
"name": "message",
"type": "string"
},
{
"name": "paramaters",
"type": [
"array",
{
"countType": "varint",
"type": "string"
}
]
}
]
],
"jukebox_popup": [
"container",
[
{
"name": "message",
"type": "string"
},
{
"name": "paramaters",
"type": [
"array",
{
"countType": "varint",
"type": "string"
}
]
}
]
]
},
"default": "void"
}
]
},
{
"name": "xuid",
"type": "string"
},
{
"name": "platform_chat_id",
"type": "string"
}
]
],
@ -2524,16 +2722,8 @@
"type": "zigzag32"
},
{
"name": "x",
"type": "zigzag32"
},
{
"name": "y",
"type": "varint"
},
{
"name": "z",
"type": "zigzag32"
"name": "spawn_position",
"type": "BlockCoordinates"
},
{
"name": "has_achievements_disabled",
@ -2600,7 +2790,7 @@
"type": "Experiments"
},
{
"name": "experiments_previously_toggled",
"name": "experiments_previously_used",
"type": "bool"
},
{
@ -2684,8 +2874,18 @@
"type": "bool"
},
{
"name": "movement_type",
"type": "zigzag32"
"name": "movement_authority",
"type": [
"mapper",
{
"type": "zigzag32",
"mappings": {
"0": "client",
"1": "server",
"2": "server_v2_rewind"
}
}
]
},
{
"name": "current_tick",
@ -2695,10 +2895,6 @@
"name": "enchantment_seed",
"type": "zigzag32"
},
{
"name": "block_palette",
"type": "BlockPalette"
},
{
"name": "itemstates",
"type": "Itemstates"

View file

@ -25,17 +25,6 @@ function createDeserializer() {
return new Parser(proto, 'mcpe_packet');
}
const PLAY_STATUS = {
'LoginSuccess': 0,
'LoginFailedClient': 1,
'LoginFailedServer': 2,
'PlayerSpawn': 3,
'LoginFailedInvalidTenant': 4,
'LoginFailedVanillaEdu': 5,
'LoginFailedEduVanilla': 6,
'LoginFailedServerFull': 7
}
class Player extends Connection {
constructor(server, connection, options) {
super()
@ -55,11 +44,11 @@ class Player extends Connection {
const clientVer = body.protocol_version
if (this.server.options.version) {
if (this.server.options.version < clientVer) {
this.sendDisconnectStatus(PLAY_STATUS.LoginFailedClient)
this.sendDisconnectStatus(failed_client)
return
}
} else if (clientVer < MIN_VERSION) {
this.sendDisconnectStatus(PLAY_STATUS.LoginFailedClient)
this.sendDisconnectStatus(failed_client)
return
}
@ -91,7 +80,7 @@ class Player extends Connection {
// Client to Server handshake response. This indicates successful encryption
onHandshake() {
// https://wiki.vg/Bedrock_Protocol#Play_Status
this.write('play_status', { status: PLAY_STATUS.LoginSuccess })
this.write('play_status', { status: 'login_success' })
this.emit('join')
}
@ -181,4 +170,4 @@ class Server extends EventEmitter {
}
}
module.exports = { Server, Player, PLAY_STATUS }
module.exports = { Server, Player }

View file

@ -33,7 +33,7 @@ server.on('connect', ({ client }) => {
'resource_packs': [],
'game_version': '',
'experiments': [],
'experiments_previously_toggled': false
'experiments_previously_used': false
})
client.once('resource_pack_client_response', async (packet) => {