Difference between revisions of "Pocket Edition Protocol Documentation"

From wiki.vg
Jump to navigation Jump to search
m
m (Remove colon)
 
(30 intermediate revisions by 8 users not shown)
Line 1: Line 1:
This is the (unofficial) protocol docs for Minecraft: PE. The protocol currently uses UDP for communication, different from PC (TCP). The usual UDP issues are still here (lost packets, wrong order, etc.), but the protocol solves a few of those problems using special packet encapsulation, based on TCP. The Minecraft: PE client uses RakNet for it's networking library. Even though it uses RakNet, you can still write software without the library.
+
{{Box
 +
  |BORDER = #9999FF
 +
  |BACKGROUND = #99CCFF
 +
  |WIDTH = 100%
 +
  |ICON =
 +
  |HEADING = Heads up!
 +
  |CONTENT = This is information for Minecraft Pocket Edition before it became Bedrock Edition.'''. For the latest Bedrock Edition protocol documentation see [[Bedrock Protocol]].
 +
}}
  
 +
This is the (unofficial) protocol documentation for {{Minecraft Wiki|Minecraft Pocket Edition}}. The protocol currently uses [[Wikipedia:UDP|UDP]] for communication, different from PC (which uses [[Wikipedia:TCP|TCP]]). The usual UDP issues are still here (lost packets, wrong order, etc.), but the protocol solves a few of those problems using special packet encapsulation, based on TCP. The Minecraft: PE client uses [http://www.raknet.com/ RakNet] as its networking library. Even though it uses RakNet, you can still write software without the library.
 +
 +
Currently, the game's default port is 19132. It is recommended to use this when possible because processes such as server discovering will not work otherwise.
  
 
== Data Types ==
 
== Data Types ==
Line 14: Line 24:
 
! class="col0 centeralign" | byte
 
! class="col0 centeralign" | byte
 
| class="col1 centeralign" | 1
 
| class="col1 centeralign" | 1
| class="col2" | -128 to 127
+
| class="col2" | 0 to 255
 
| class="col3" | <code></code>
 
| class="col3" | <code></code>
 
|- class="row2"
 
|- class="row2"
 +
! class="col0 centeralign" | boolean
 +
| class="col1 centeralign" | 1
 +
| class="col2" | 0 or 1
 +
| class="col3" | <code>A byte treated as a boolean, 0 is false but anything greater than that is true.</code>
 +
|
 +
|- class="row3"
 
! class="col0 centeralign" | short
 
! class="col0 centeralign" | short
 
| class="col1 centeralign" | 2
 
| class="col1 centeralign" | 2
 
| class="col2" | -32768 to 32767
 
| class="col2" | -32768 to 32767
 
| class="col3" | <code></code>
 
| class="col3" | <code></code>
|- class="row3"
+
|- class="row4"
! class="col0 centeralign" | Integer
+
! class="col0 centeralign" | uint24le
 +
| class="col1 centeralign" | 3
 +
| class="col2" | 0 to 16777216
 +
| class="col3" | Little-Endian 24-bit unsigned integer. Commonly used by RakNet for counters.
 +
|- class="row5"
 +
! class="col0 centeralign" | int
 
| class="col1 centeralign" | 4
 
| class="col1 centeralign" | 4
 
| class="col2" | -2147483648 to 2147483647
 
| class="col2" | -2147483648 to 2147483647
 
| class="col3" | <code></code>
 
| class="col3" | <code></code>
|- class="row4"
+
|- class="row6"
! class="col0 centeralign" | Long
+
! class="col0 centeralign" | long
 
| class="col1 centeralign" | 8
 
| class="col1 centeralign" | 8
 
| class="col2" |  
 
| class="col2" |  
 
| class="col3" | <code></code>
 
| class="col3" | <code></code>
|- class="row5"
+
|- class="row7"
 
! class="col0 centeralign" | MAGIC
 
! class="col0 centeralign" | MAGIC
 
| class="col1 centeralign" | 16
 
| class="col1 centeralign" | 16
 
| class="col2" | <code>0x00ffff00fefefefefdfdfdfd12345678</code>
 
| class="col2" | <code>0x00ffff00fefefefefdfdfdfd12345678</code>
 
| class="col3" | always those hex bytes, corresponding to RakNet's default OFFLINE_MESSAGE_DATA_ID
 
| class="col3" | always those hex bytes, corresponding to RakNet's default OFFLINE_MESSAGE_DATA_ID
|- class="row6"
+
|- class="row8"
 
! class="col0 centeralign" | string
 
! class="col0 centeralign" | string
| class="col1 centeralign" | short + string
+
| class="col1 centeralign" | unsigned short + string
 
| class="col2" | N/A
 
| class="col2" | N/A
 
| class="col3" | Prefixed by a short containing the length of the string in characters. It appears that only the following ASCII characters can be displayed: !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
 
| class="col3" | Prefixed by a short containing the length of the string in characters. It appears that only the following ASCII characters can be displayed: !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
 +
|- class="row9"
 +
! class="col0 centeralign" | address
 +
| class="col1 centeralign" | 7
 +
| class="col2" | N/A
 +
| class="col3" | IP Address and port. First byte is the version (0x04), then come the address bytes and finally an unsigned short for the port.
 +
|-
 +
! NBT
 +
| N/A
 +
| N/A
 +
| NBT data in PE is always ''little-endian''. This includes short, int, long, float, double tags and the length headers for arrays, strings and lists.
 +
|-
 +
! Item Stack
 +
| N/A
 +
| N/A
 +
| First short is the item ID. If this is not 0, then follows the item count ubyte. If this is also not 0, then follows the item data short and a ''little-endian'' short denoting the length of the following NBT data, or 0 for no NBT. Then follows an NBT tag described above of that length.
 +
|-
 +
! UUID
 +
| 16
 +
| 00000000-0000-0000-0000-000000000000
 +
to ffffffff-ffff-ffff-ffff-ffffffffffff
 +
|
 +
|-
 +
! Position
 +
| 12
 +
| N/A
 +
| Three consecutive floats for x, y and z respectively.
 +
|-
 +
! Block Position
 +
| 12
 +
| N/A
 +
| Three consecutive ints for x, y and z respectively.
 
|}
 
|}
  
 +
== Packet format ==
 +
All packets in Minecraft: Pocket Edition start with their ID, which is an unsigned byte. If you are using a language which does not support unsigned types such as Java, you can do (byte & 0xFF) to get the unsigned version.
 +
 +
== RakNet protocol ==
 +
 +
The source code for the RakNet Library can be found [https://github.com/OculusVR/RakNet here].
 +
 +
Other implementations exist, such as [https://github.com/jython234/JRakLibPlus JRakLibPlus] and [https://github.com/PocketMine/RakLib RakLib].
 +
 +
=== Connected Ping ===
 +
 +
{| class="wikitable"
 +
! Packet ID
 +
! Field Name
 +
! Field Type
 +
! Notes
 +
|-
 +
| 0x00
 +
| Time
 +
| long
 +
|
 +
|}
 +
 +
=== Unconnected Ping ===
 +
{| class="wikitable"
 +
! Packet ID
 +
! Field Name
 +
! Field Type
 +
! Notes
 +
|-
 +
|rowspan="2"| 0x01, 0x02
 +
| Time
 +
| long
 +
|
 +
|-
 +
| MAGIC
 +
| magic
 +
|
 +
|}
 +
 +
<code>0x02</code> is only replied to if there are open connections to the server. '''Note:''' as of 0.15.6 it seems that the game refreshes it's LAN world list every 4-5 seconds, however it seems the game will still ping in 1 second intervals.
 +
 +
=== Connected Pong ===
 +
{| class="wikitable"
 +
! Packet ID
 +
! Field Name
 +
! Field Type
 +
! Notes
 +
|-
 +
|rowspan="2"| 0x03
 +
| Ping Time
 +
| long
 +
|
 +
|-
 +
| Pong Time
 +
| long
 +
|
 +
|}
 +
 +
=== Offline Connection Request 1 ===
 +
{| class="wikitable"
 +
! Packet ID
 +
! Field Name
 +
! Field Type
 +
! Notes
 +
|-
 +
|rowspan="3"| 0x05
 +
| Magic
 +
| MAGIC
 +
|
 +
|-
 +
| Protocol version
 +
| byte
 +
| Currently 7
 +
|-
 +
| MTU
 +
| mtu-46 zero bytes
 +
| The MTU sent in the response appears to be somewhere around the size of this padding + 46 (28 udp overhead, 1 packet id, 16 magic, 1 protocol version)
 +
|}
 +
 +
The client sends these to the target server with ever decreasing MTU until the server responds. This is used to discover the MTU size for the connection. If the RakNet protocol does not match your own, respond with the Incompatible protocol packet
 +
 +
=== Offline Connection Response 1 ===
 +
{| class="wikitable"
 +
! Packet ID
 +
! Field Name
 +
! Field Type
 +
! Notes
 +
|-
 +
|rowspan="4"| 0x06
 +
| Magic
 +
| MAGIC
 +
|
 +
|-
 +
| Server GUID
 +
| long
 +
|
 +
|-
 +
| Use security
 +
| boolean
 +
| Make sure this is false, it is vital for the login sequence to continue!
 +
|
 +
|-
 +
| MTU
 +
| short
 +
| see Offline Connection Request 1
 +
|}
 +
 +
=== Offline Connection Request 2 ===
 +
{| class="wikitable"
 +
! Packet ID
 +
! Field Name
 +
! Field Type
 +
! Notes
 +
|-
 +
|rowspan="4"| 0x07
 +
| Magic
 +
| MAGIC
 +
|
 +
|-
 +
| Server Address
 +
| address
 +
|
 +
|-
 +
| MTU
 +
| short
 +
|
 +
|-
 +
| Client GUID
 +
| long
 +
|
 +
|}
 +
 +
=== Offline Connection Response 2 ===
 +
{| class="wikitable"
 +
! Packet ID
 +
! Field Name
 +
! Field Type
 +
! Notes
 +
|-
 +
|rowspan="5"| 0x08
 +
| Magic
 +
| MAGIC
 +
|
 +
|-
 +
| Server GUID
 +
| long
 +
|
 +
|-
 +
| Client Address
 +
| address
 +
|
 +
|-
 +
| MTU
 +
| short
 +
|
 +
|-
 +
| Encryption enabled?
 +
| byte
 +
| 0 for disabled.
 +
|}
 +
 +
=== Online Connection Request ===
 +
{| class="wikitable"
 +
! Packet ID
 +
! Field Name
 +
! Field Type
 +
! Notes
 +
|-
 +
|rowspan="2"| 0x09
 +
| GUID
 +
| long
 +
|
 +
|-
 +
| Time
 +
| long
 +
|
 +
|}
 +
 +
=== Online Connection Request Accepted ===
 +
{| class="wikitable"
 +
! Packet ID
 +
! Field Name
 +
! Field Type
 +
! Notes
 +
|-
 +
|rowspan="5"| 0x10
 +
| Client address
 +
| address
 +
|
 +
|-
 +
| System index
 +
| short
 +
| Unknown what this does. 0 works as a value.
 +
|-
 +
| Internal IDs
 +
| 10x address
 +
| Unknown what these do. 255.255.255.255:19132 for all of them seems to work, any other address will probably work as well.
 +
|-
 +
| Request time
 +
| long
 +
|
 +
|-
 +
| Time
 +
| long
 +
|
 +
|}
 +
 +
=== Incompatible protocol ===
 +
{| class="wikitable"
 +
! Packet ID
 +
! Field Name
 +
! Field Type
 +
! Notes
 +
|-
 +
|rowspan="4"| 0x19
 +
| Protocol
 +
| byte
 +
|
 +
|-
 +
| Magic
 +
| MAGIC
 +
|
 +
|-
 +
| Server GUID
 +
| long
 +
|
 +
|-
 +
|}
 +
 +
=== Unconnected Ping ===
 +
{| class="wikitable"
 +
! Packet ID
 +
! Field Name
 +
! Field Type
 +
! Notes
 +
|-
 +
|rowspan="2"| 0x01, 0x02
 +
| Time
 +
| long
 +
|
 +
|-
 +
| GUID
 +
| long
 +
|
 +
|}
 +
 +
=== Frame Set Packet ===
 +
{| class="wikitable"
 +
! Packet ID
 +
!colspan="3"| Field Name
 +
! Field Type
 +
! Notes
 +
|-
 +
|rowspan="11"| 0x80..0x8d
 +
|colspan="3"| Frame Set index
 +
| uint24le
 +
|
 +
|-
 +
|rowspan="10"| Frames
 +
|colspan="2"| Flags
 +
| byte
 +
| Top 3 bits are reliability type, fourth bit is 1 when the frame is fragmented and part of a compound.
 +
|-
 +
|colspan="2"| Length IN BITS
 +
| short
 +
| Length of the body in bits.
 +
|-
 +
|colspan="2"| Reliable frame index
 +
| uint24le
 +
| only if reliable
 +
|-
 +
|colspan="2"| Sequenced frame index
 +
| uint24le
 +
| only if sequenced
 +
|-
 +
|rowspan="2"| Order
 +
| Ordered frame index
 +
| uint24le
 +
|rowspan="2"| only if ordered
 +
|-
 +
| Order channel
 +
| byte
 +
|-
 +
|rowspan="3"| Fragment
 +
| Compound size
 +
| int
 +
|rowspan="3"| only if fragmented
 +
|-
 +
| Compound ID
 +
| short
 +
|-
 +
| Index
 +
| int
 +
|-
 +
| Body
 +
| ceil(length/8) bytes
 +
|}
 +
 +
The reliability types are as follows:
 +
 +
{| class="wikitable"
 +
! style="text-align: center; font-weight: bold;" | ID
 +
! style="font-weight: bold;" | Name
 +
! style="text-align: center; font-weight: bold;" | Reliable
 +
! style="text-align: center; font-weight: bold;" | Ordered
 +
! style="text-align: center; font-weight: bold;" | Sequenced
 +
|-
 +
| style="text-align: center;" | 0
 +
| unreliable
 +
| style="text-align: center;" |
 +
| style="text-align: center;" |
 +
| style="text-align: center;" |
 +
|-
 +
| style="text-align: center;" | 1
 +
| unreliable sequenced
 +
| style="text-align: center;" |
 +
| style="text-align: center;" | x
 +
| style="text-align: center;" | x
 +
|-
 +
| style="text-align: center;" | 2
 +
| reliable
 +
| style="text-align: center;" | x
 +
| style="text-align: center;" |
 +
| style="text-align: center;" |
 +
|-
 +
| style="text-align: center;" | 3
 +
| reliable ordered
 +
| style="text-align: center;" | x
 +
| style="text-align: center;" | x
 +
| style="text-align: center;" |
 +
|-
 +
| style="text-align: center;" | 4
 +
| reliable sequenced
 +
| style="text-align: center;" | x
 +
| style="text-align: center;" | x
 +
| style="text-align: center;" | x
 +
|-
 +
| style="text-align: center;" | 5
 +
| unreliable (+ ACK receipt)
 +
| style="text-align: center;" |
 +
| style="text-align: center;" |
 +
| style="text-align: center;" |
 +
|-
 +
| style="text-align: center;" | 6
 +
| reliable (+ ACK receipt)
 +
| style="text-align: center;" | x
 +
| style="text-align: center;" |
 +
| style="text-align: center;" |
 +
|-
 +
| style="text-align: center;" | 7
 +
| reliable ordered (+ ACK receipt)
 +
| style="text-align: center;" | x
 +
| style="text-align: center;" | x
 +
| style="text-align: center;" |
 +
|}
 +
 +
Sequenced implies ordered.
 +
 +
=== Game Packet ===
 +
{| class="wikitable"
 +
! Packet ID
 +
! Field Name
 +
! Field Type
 +
! Notes
 +
|-
 +
| 0x8e
 +
| Body
 +
| bytes
 +
| Single packet of the GAME protocol.
 +
|}
 +
 +
=== NACK ===
 +
{| class="wikitable"
 +
! style="font-weight: bold;" | Packet ID
 +
! colspan="3" style="font-weight: bold;" | Field Name
 +
! style="font-weight: bold;" | Field Type
 +
! style="font-weight: bold;" | Notes
 +
|-
 +
| 0xa0
 +
| colspan="3" | Record count
 +
| short
 +
|
 +
|-
 +
|
 +
| rowspan="4" | Record
 +
| colspan="2" | Is Range?
 +
| byte
 +
| 0 for range, 1 for no range
 +
|-
 +
|
 +
| No Range
 +
| Index
 +
| uint24le
 +
|
 +
|-
 +
|
 +
| rowspan="2" | Range
 +
| Start Index
 +
| uint24le
 +
|
 +
|-
 +
|
 +
| End Index
 +
| uint24le
 +
|
 +
|}
 +
 +
=== ACK ===
 +
{| class="wikitable"
 +
! style="font-weight: bold;" | Packet ID
 +
! colspan="3" style="font-weight: bold;" | Field Name
 +
! style="font-weight: bold;" | Field Type
 +
! style="font-weight: bold;" | Notes
 +
|-
 +
| 0xc0
 +
| colspan="3" | Record count
 +
| short
 +
|
 +
|-
 +
|
 +
| rowspan="4" | Record
 +
| colspan="2" | Is Range?
 +
| byte
 +
| 0 for range, 1 for no range
 +
|-
 +
|
 +
| No Range
 +
| Index
 +
| uint24le
 +
|
 +
|-
 +
|
 +
| rowspan="2" | Range
 +
| Start Index
 +
| uint24le
 +
|
 +
|-
 +
|
 +
| End Index
 +
| uint24le
 +
|
 +
|}
 +
 +
== RakNet Reliability ==
 +
 +
RakNet reliability and ordering is handled on multiple levels.
 +
 +
=== Frame set reliability ===
 +
FrameSetPackets carry a unique index. This index may only appear once in a connection (per direction). Getting the same index twice means you have received a duplicate datagram - ignore one.
 +
 +
Upon receiving a frame set, an ACK packet for that frame set is sent back. Since the frame set index is a sequential counter, you can deduce which frame sets are missing, for which a NACK packet is sent. For every received frame set, RakNet sends at most one NACK and one ACK.
 +
 +
Frame sets consist of frames. Internally, raknet uses a "resend queue" (priority heap / priority queue) of frames it needs to send. This queue is ordered by targeted send time. Whenever possible, raknet takes the top few sendable frames from this resend queue and combines them into a frame set smaller than the MTU. It then moves the ''reliable'' frames further down the queue by setting their resend time to a bunch of milliseconds in the future. ''unreliable'' frames are discarded after being first sent.
 +
 +
When an ACK is received, all frames of the container indices in that ACK packet are removed from the resend queue because they arrived safely on the client and don't need a resend.
 +
 +
When a NACK is received, all frames of the container indices in that NACK packet are moved to the top of the resend queue by setting their targeted resend time to the present or past.
 +
 +
To send a frame, raknet simply adds it to the resend queue with the present as the targeted send time. It is then intermixed with normal resends and other frames for the next frame set packet.
 +
 +
=== Fragmentation ===
 +
 +
Some packets (notably chunks) are larger than the MTU. These are split up into a ''compound''. You need to consider the frame and frame set overhead when fragmenting frames. A fragmented frame contains the ''compound ID'' (reusable when compound is complete), ''compound size'' (in fragments) and ''index'' (0 up to compound size exclusive). All fragments of a compound share the same order and sequencing information, if any. All fragmented frames are also reliable.
 +
 +
=== Order and Sequencing ===
 +
 +
Some frames are ordered or sequenced. For order and sequencing, there exist ''order channels''. These act independently. Since all sequenced reliability types are also ordered, an order channel is present for every ordered or sequenced frame.
 +
 +
''Ordered'' means that frames with higher order indices are ''always'' handled after frames with lower order indices. Higher order index frames are withheld until their lower peers arrive and it's their turn.
 +
 +
''Sequenced'' means that frames with lower sequence indices are ''never'' handled after frames with higher sequence indices. Lower sequence index frames are ''discarded'' if their higher index frames have already been handled.
 +
 +
Sequenced frames also include an order index. It is unknown how the order index influences handling, and this should be researched at some point.
 +
 +
== Game Protocol ==
 +
 +
The game protocol is described here: https://confluence.yawk.at/display/PEPROTOCOL and an autoatically generated version for 0.15 is also available in from MiNET at https://github.com/NiclasOlofsson/MiNET/blob/master/src/MiNET/MiNET/Net/MCPE%20Protocol%20Documentation.md
  
== Reference ==
+
== References ==
  
The latest version of the protocol is not fully documented yet, but an automatically generated specification of many of the packages can be found in the MiNET server code  https://github.com/NiclasOlofsson/MiNET/blob/master/src/MiNET/MiNET/Net/MCPE%20Protocol%20Documentation.md
+
* RakNet datagram and message header information: http://jenkinssoftware.com/raknet/manual/systemoverview.html
 +
* Packets can be found in the [http://dragonet.org Dragonet] server code  https://github.com/DragonetMC/Dragonet/tree/master/src/main/java/org/dragonet/net/packet
 +
* There is also an automatically generated specification of many of the packages can be found in the MiNET server code  https://github.com/NiclasOlofsson/MiNET/blob/master/src/MiNET/MiNET/Net/MCPE%20Protocol%20Documentation.md  
 +
* The MiNET wiki also contain development notes around some functionality https://github.com/NiclasOlofsson/MiNET/wiki These will be migrated to this wiki in due time.
 +
* https://confluence.yawk.at/display/PEPROTOCOL

Latest revision as of 11:03, 8 June 2020

Heads up!

This is information for Minecraft Pocket Edition before it became Bedrock Edition.. For the latest Bedrock Edition protocol documentation see Bedrock Protocol.

This is the (unofficial) protocol documentation for Minecraft Pocket Edition. The protocol currently uses UDP for communication, different from PC (which uses TCP). The usual UDP issues are still here (lost packets, wrong order, etc.), but the protocol solves a few of those problems using special packet encapsulation, based on TCP. The Minecraft: PE client uses RakNet as its networking library. Even though it uses RakNet, you can still write software without the library.

Currently, the game's default port is 19132. It is recommended to use this when possible because processes such as server discovering will not work otherwise.

Data Types

Minecraft packets use different data types to communicate with each other. The documented ones are listed below:

Size Range Notes
byte 1 0 to 255
boolean 1 0 or 1 A byte treated as a boolean, 0 is false but anything greater than that is true.
short 2 -32768 to 32767
uint24le 3 0 to 16777216 Little-Endian 24-bit unsigned integer. Commonly used by RakNet for counters.
int 4 -2147483648 to 2147483647
long 8
MAGIC 16 0x00ffff00fefefefefdfdfdfd12345678 always those hex bytes, corresponding to RakNet's default OFFLINE_MESSAGE_DATA_ID
string unsigned short + string N/A Prefixed by a short containing the length of the string in characters. It appears that only the following ASCII characters can be displayed: !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
address 7 N/A IP Address and port. First byte is the version (0x04), then come the address bytes and finally an unsigned short for the port.
NBT N/A N/A NBT data in PE is always little-endian. This includes short, int, long, float, double tags and the length headers for arrays, strings and lists.
Item Stack N/A N/A First short is the item ID. If this is not 0, then follows the item count ubyte. If this is also not 0, then follows the item data short and a little-endian short denoting the length of the following NBT data, or 0 for no NBT. Then follows an NBT tag described above of that length.
UUID 16 00000000-0000-0000-0000-000000000000

to ffffffff-ffff-ffff-ffff-ffffffffffff

Position 12 N/A Three consecutive floats for x, y and z respectively.
Block Position 12 N/A Three consecutive ints for x, y and z respectively.

Packet format

All packets in Minecraft: Pocket Edition start with their ID, which is an unsigned byte. If you are using a language which does not support unsigned types such as Java, you can do (byte & 0xFF) to get the unsigned version.

RakNet protocol

The source code for the RakNet Library can be found here.

Other implementations exist, such as JRakLibPlus and RakLib.

Connected Ping

Packet ID Field Name Field Type Notes
0x00 Time long

Unconnected Ping

Packet ID Field Name Field Type Notes
0x01, 0x02 Time long
MAGIC magic

0x02 is only replied to if there are open connections to the server. Note: as of 0.15.6 it seems that the game refreshes it's LAN world list every 4-5 seconds, however it seems the game will still ping in 1 second intervals.

Connected Pong

Packet ID Field Name Field Type Notes
0x03 Ping Time long
Pong Time long

Offline Connection Request 1

Packet ID Field Name Field Type Notes
0x05 Magic MAGIC
Protocol version byte Currently 7
MTU mtu-46 zero bytes The MTU sent in the response appears to be somewhere around the size of this padding + 46 (28 udp overhead, 1 packet id, 16 magic, 1 protocol version)

The client sends these to the target server with ever decreasing MTU until the server responds. This is used to discover the MTU size for the connection. If the RakNet protocol does not match your own, respond with the Incompatible protocol packet

Offline Connection Response 1

Packet ID Field Name Field Type Notes
0x06 Magic MAGIC
Server GUID long
Use security boolean Make sure this is false, it is vital for the login sequence to continue!
MTU short see Offline Connection Request 1

Offline Connection Request 2

Packet ID Field Name Field Type Notes
0x07 Magic MAGIC
Server Address address
MTU short
Client GUID long

Offline Connection Response 2

Packet ID Field Name Field Type Notes
0x08 Magic MAGIC
Server GUID long
Client Address address
MTU short
Encryption enabled? byte 0 for disabled.

Online Connection Request

Packet ID Field Name Field Type Notes
0x09 GUID long
Time long

Online Connection Request Accepted

Packet ID Field Name Field Type Notes
0x10 Client address address
System index short Unknown what this does. 0 works as a value.
Internal IDs 10x address Unknown what these do. 255.255.255.255:19132 for all of them seems to work, any other address will probably work as well.
Request time long
Time long

Incompatible protocol

Packet ID Field Name Field Type Notes
0x19 Protocol byte
Magic MAGIC
Server GUID long

Unconnected Ping

Packet ID Field Name Field Type Notes
0x01, 0x02 Time long
GUID long

Frame Set Packet

Packet ID Field Name Field Type Notes
0x80..0x8d Frame Set index uint24le
Frames Flags byte Top 3 bits are reliability type, fourth bit is 1 when the frame is fragmented and part of a compound.
Length IN BITS short Length of the body in bits.
Reliable frame index uint24le only if reliable
Sequenced frame index uint24le only if sequenced
Order Ordered frame index uint24le only if ordered
Order channel byte
Fragment Compound size int only if fragmented
Compound ID short
Index int
Body ceil(length/8) bytes

The reliability types are as follows:

ID Name Reliable Ordered Sequenced
0 unreliable
1 unreliable sequenced x x
2 reliable x
3 reliable ordered x x
4 reliable sequenced x x x
5 unreliable (+ ACK receipt)
6 reliable (+ ACK receipt) x
7 reliable ordered (+ ACK receipt) x x

Sequenced implies ordered.

Game Packet

Packet ID Field Name Field Type Notes
0x8e Body bytes Single packet of the GAME protocol.

NACK

Packet ID Field Name Field Type Notes
0xa0 Record count short
Record Is Range? byte 0 for range, 1 for no range
No Range Index uint24le
Range Start Index uint24le
End Index uint24le

ACK

Packet ID Field Name Field Type Notes
0xc0 Record count short
Record Is Range? byte 0 for range, 1 for no range
No Range Index uint24le
Range Start Index uint24le
End Index uint24le

RakNet Reliability

RakNet reliability and ordering is handled on multiple levels.

Frame set reliability

FrameSetPackets carry a unique index. This index may only appear once in a connection (per direction). Getting the same index twice means you have received a duplicate datagram - ignore one.

Upon receiving a frame set, an ACK packet for that frame set is sent back. Since the frame set index is a sequential counter, you can deduce which frame sets are missing, for which a NACK packet is sent. For every received frame set, RakNet sends at most one NACK and one ACK.

Frame sets consist of frames. Internally, raknet uses a "resend queue" (priority heap / priority queue) of frames it needs to send. This queue is ordered by targeted send time. Whenever possible, raknet takes the top few sendable frames from this resend queue and combines them into a frame set smaller than the MTU. It then moves the reliable frames further down the queue by setting their resend time to a bunch of milliseconds in the future. unreliable frames are discarded after being first sent.

When an ACK is received, all frames of the container indices in that ACK packet are removed from the resend queue because they arrived safely on the client and don't need a resend.

When a NACK is received, all frames of the container indices in that NACK packet are moved to the top of the resend queue by setting their targeted resend time to the present or past.

To send a frame, raknet simply adds it to the resend queue with the present as the targeted send time. It is then intermixed with normal resends and other frames for the next frame set packet.

Fragmentation

Some packets (notably chunks) are larger than the MTU. These are split up into a compound. You need to consider the frame and frame set overhead when fragmenting frames. A fragmented frame contains the compound ID (reusable when compound is complete), compound size (in fragments) and index (0 up to compound size exclusive). All fragments of a compound share the same order and sequencing information, if any. All fragmented frames are also reliable.

Order and Sequencing

Some frames are ordered or sequenced. For order and sequencing, there exist order channels. These act independently. Since all sequenced reliability types are also ordered, an order channel is present for every ordered or sequenced frame.

Ordered means that frames with higher order indices are always handled after frames with lower order indices. Higher order index frames are withheld until their lower peers arrive and it's their turn.

Sequenced means that frames with lower sequence indices are never handled after frames with higher sequence indices. Lower sequence index frames are discarded if their higher index frames have already been handled.

Sequenced frames also include an order index. It is unknown how the order index influences handling, and this should be researched at some point.

Game Protocol

The game protocol is described here: https://confluence.yawk.at/display/PEPROTOCOL and an autoatically generated version for 0.15 is also available in from MiNET at https://github.com/NiclasOlofsson/MiNET/blob/master/src/MiNET/MiNET/Net/MCPE%20Protocol%20Documentation.md

References