Difference between revisions of "Talk:Protocol"

From wiki.vg
Jump to navigation Jump to search
 
(4 intermediate revisions by 2 users not shown)
Line 822: Line 822:
 
I received this packet the first time I tried talking to a server. It's packet type 0x1A, but neither of the type 0x1A listed seem to match it. New discovery?
 
I received this packet the first time I tried talking to a server. It's packet type 0x1A, but neither of the type 0x1A listed seem to match it. New discovery?
  
1A
+
<pre>
9B 01
+
1A                                               (packet ID)
7B 22 74 72 61 6E 73 6C 61 74 65 22 3A 22 64 69  
+
9B 01                                             (length of following string data, varint 155)
 +
7B 22 74 72 61 6E 73 6C 61 74 65 22 3A 22 64 69   (The data is a JSON payload telling me why the server is disconnecting me...)
 
73 63 6F 6E 6E 65 63 74 2E 67 65 6E 65 72 69 63  
 
73 63 6F 6E 6E 65 63 74 2E 67 65 6E 65 72 69 63  
 
52 65 61 73 6F 6E 22 2C 22 77 69 74 68 22 3A 5B  
 
52 65 61 73 6F 6E 22 2C 22 77 69 74 68 22 3A 5B  
Line 834: Line 835:
 
78 63 65 70 74 69 6F 6E 3A 20 56 61 72 49 6E 74  
 
78 63 65 70 74 69 6F 6E 3A 20 56 61 72 49 6E 74  
 
20 74 6F 6F 20 62 69 67 22 5D 7D  
 
20 74 6F 6F 20 62 69 67 22 5D 7D  
 
+
</pre>
The data is a JSON payload telling me why the server is disconnecting me.
 
  
 
Currently we say "the protocol immediately switches to a different state after the client sends the first packet", but what if the first packet is invalid?
 
Currently we say "the protocol immediately switches to a different state after the client sends the first packet", but what if the first packet is invalid?
Line 841: Line 841:
 
What I sent:
 
What I sent:
  
00                                       (packet ID, handshake)
+
<pre>
FF FF FF FF 0F                           (protocol version -1)
+
00                                               (packet ID, handshake)
0C 31 39 32 2E 31 36 38 2A 31 2E 35 36   (hostname, in this case a local network ip addr)
+
FF FF FF FF 0F                                   (protocol version -1)
63 DD                                     (port, 25565)
+
0C 31 39 32 2E 31 36 38 2A 31 2E 35 36           (hostname, in this case a local network ip addr)
01                                       (next state, Status)
+
63 DD                                           (port, 25565)
 +
01                                               (next state, Status)
 +
</pre>
 +
 
 +
[[User:Trejkaz|Trejkaz]] ([[User talk:Trejkaz|talk]]) 14:55, 11 July 2024 (UTC)
  
 +
: First of all, you're probably using an older Minecraft version. The newest version I found where 0x1A means Disconnect is 1.20; there may be others too. That would explain the weird packet ID. Second, are you sending a packet length field (not included in the dump shown)? If not, that might be it (the FF FF FF FF 0F gets parsed as a length, which is too long for the special 1-3 byte length field VarInt parser), though the response from 1.20 is slightly different (<code>{"translate":"disconnect.genericReason","with":["Internal Exception: io.netty.handler.codec.CorruptedFrameException: length wider than 21-bit"]}</code>), so it would have to have been a different version if that were the case. However, it does indeed use the Play protocol packet ID for Disconnect (0x1A), unlike newer versions I tested (which just silently disconnect). This again suggests use of an old version. After adding a length field the packet worked fine on 1.20, 1.20.4 and 1.21 (the handshake and status protocols are deliberately backward and forward-compatible, it's just that the older server was leaking the Disconnect packet from its incompatible play protocol to the handshake phase). So either the length field is wrong or missing, or there's a bug causing the sent packet to be different from what you showed. --[[User:LassiPulkkinen|LassiPulkkinen]] ([[User talk:LassiPulkkinen|talk]]) 19:53, 11 July 2024 (UTC)
  
[[User:Trejkaz|Trejkaz]] ([[User talk:Trejkaz|talk]]) 14:55, 11 July 2024 (UTC)
+
:: As far as my API currently treats it, the size is written before the packet, which is why it isn't in that dump. [[User:Trejkaz|Trejkaz]] ([[User talk:Trejkaz|talk]]) 10:41, 12 July 2024 (UTC)

Latest revision as of 10:42, 12 July 2024

Contents

zlib compress instead of deflate? (0x33)

Whilst implementing chunk creation server side in PHP I've found deflate does not work, however the zlib compressed format does. Can anyone else confirm this? --ody

I can confirm it uses zlib. I'm using the Ionic Zlib library. Using deflate makes the Minecraft client show the error "Bad compressed data format." dotMaiku 10:13, 23 October 2011 (MST)

Just strip the first 2 chars... then it works (Java deflate issue) --Shoghicp 14:21, 12 December 2011 (MST)

Too Large?

MediaWiki gave me a warning about this page being too large for some browsers. Perhaps it should be split in half? --SpaceManiac 00:44, 6 November 2010 (EDT)

Don't hit Edit for the entire page :P -- Jailout2000 04:48, 2 January 2012 (MST)

Player Position (0x0B) really absolute position?

As of version 1.2.0_02, I was watching the packets my server software was receiving while walking around, and the xyz coordinates of packet type 0x0b appear to correlate 1:1 with where a player is in block coordinates, not pixel coordinates. Yen

Absolute position position is specified as block coordinates, It appears this has changed before the move, I put in these definitions originally to clarify such things, absolute double's should be block coordinates, with the fraction being the offset in the block. ReDucTor

So "Absolute" is in meters, but "Absolute integer" is in pixels? Can't we come up with better names? I propose we name coordinates by the size of 1 unit. We change the names like this: Absolute -> meters; Absolute integer -> pixels; Block -> meters; Chunk -> chunks. Currently, the only two "units of measurement" with the same name are in fact different units of measurement. The focus of the current names seems to be the precision of the types, which seems less important to convey to readers than the scale of each unit relative to one another. --Thejoshwolfe 22:55, 25 January 2011 (MST)

New Server Packet 0x1c

The 11/10/2010 update has a new server to client packet (0x1c) 11 bytes long, the first field appears to be an EID. The packet is sent when a pickup is spawned in the world, either by throwing something, or mining. If the packet is ignored, the pickups never appear on the client. Jorgon3d 20:34, 10 November 2010 (EST)

New Client Packet 0x15

The 11/10/2010 update has a new client to server packet (0x15). It appears to be exactly as the Server to Client packet "Pickup Spawn". Jorgon3d 20:34, 10 November 2010 (EST)

Version 4

I've added the new packets from Version 4, and what I believe they match with, if people could please match these with what they see. And a Grammar Nazi fix up my failures. Please join irc.esper.net / #mcc to discuss this new protocol. ReDucTor

C->S Block change with direction=-1

(Client to server) It appears now after a block change is sent there is another block change that follows this with all values -1 except block id of the change, from what I can determine this causes the players selected inventory to be changed if needed from this block change. Anyone looked into this? ReDucTor

New packets introduced in SMP Health update

Looking at the new server JAR I've seen three new packets. IDs are 0x08(<byte>), 0x09(), and 0x26(<int>,<byte>).

0x08 I'm thinking could be the players health update packet, 0x26 perhaps the 'hit entity' packet, 0x09 I'm not sure.

I'll confirm what these packets do tonight when I get back from work.

The 0x09 packet is for respawning. It is sent in both directions for when the player should respawn. 0x08 is the health, yes. Haven't gotten to 0x26 yet. Blixt 08:17, 24 November 2010 (EST)
Packet 0x07 from client to server has a new field of 1 byte. Its value is usually 1 which would make your client try to read a 0x01 packet, which includes a string, so that explains why you're getting errors about negative lengths, unicode or simply if the client stops reading more data. Blixt 10:01, 24 November 2010 (EST)
I believe I found a VERY subtle change that caused my client to crash when proxied through a wrapper that reads and writes packets: The packet for animating (0x12) now supports values other than 0 and 1 (bool): I got 2 for some packets. Blixt 10:14, 24 November 2010 (EST)
The 0x07 packet has a new bool for attacking_animal. It is 0 when using things vs air or blocks, and 1 when used on zombies, animals, and probably players (haven't tested yet). benmanns 10:24, 24 November 2010 (EST)
0x07 is never sent when you hit normal blocks or air. It's for interacting with an entity (thus it also has an entity id). I do get true whenever I hit a mob though, so that part seems correct. Blixt 10:59, 24 November 2010 (EST)
0x26 appears to be sent when an entity dies. The last byte seems to be 3 most of the time. No idea what that means. My wrapper (http://github.com/blixt/pyminecraft) is working fine now, but there seems to be a few bugs relating to burning mobs... don't know why. Blixt 10:59, 24 November 2010 (EST)
Never mind, I was forcing the client to think it was day, so during the night (on the server) the client thought the monsters should burn so they started burning, then the server said they weren't burning so they stopped burning. :) Blixt 14:15, 24 November 2010 (EST)

Complex entity packet (0x3B) client->server

Is this new? Wasn't it only server->client before? The client is sending 0x3B to the server whenever you put stuff in a chest now, anyways. Blixt 11:37, 29 November 2010 (EST)

Nov 30 update

Today's update seems to change the following:

  • The 0x26 packet now sends values other than 3 for the byte field. The value 2 means an entity was hurt. The value 3 means an entity died. The value 4 is sent the moment a creeper starts flashing.
  • There is a new packet 0x3C. I haven't investigated this yet but my guess is it's got to do with sound. It appears to be sent when a creeper is about to explode.
  • There are a lot of new values for packet 0x12 (animate), such as 104 for crouching, 105 for standing up.

- Blixt 17:58, 30 November 2010 (EST)

Has anyone looked into this? I am starting to suspect that 0x3C is a packet specific to explosions... It seems to have a structure similar to 0x34 / Multi Block Change. – Blixt 05:12, 1 December 2010 (EST)
The packet structure is like this: double, double, double, float, n = integer, n * 3 bytes. The first three doubles correspond well with X, Y, Z. The float is currently unknown. It was 3.0 for me, might be a radius or something. The list of bytes appears to be a bunch of block offsets, presumably the blocks that were destroyed in the explosion. The range of the values seems to be a bit strange though, I got the X offset as -6 up to 3, which means the explosion wouldn't be centered on the X, Y, Z coordinates. Also, the list seems to include air blocks, which seems a bit unnecessary. More investigation needed. – Blixt 18:04, 1 December 2010 (EST)

Map chunks vs. mini chunks

I'd like to make a distinction between "mini chunks" and "map chunks". Mini chunks are updates that have the same purpose as "multi block updates". The X/Y/Z size and position can be anything. Map chunks are complete 16x128x16 pieces of the map. Mini-chunk updates can arrive before map chunk updates.

"Prechunk" packet marks where a map chunk will be visible to the client, eventually. It can come well before the client should draw, though. My client will only draw a map chunk that has had a full 16x128x16 chunk update (loaded), and a prechunk packet (visible). Mini-chunks might come before prechunks, and prechunks usually come before map chunks, but both sides have to be flexible. I *have* seen mini-chunks cross map chunk boundaries, but it might be a bug in my client ;p

Example: 6x4x5 mini-chunk sent for [-1022, 20, 50]. Prechunk sent for [-1024/16, 48/16]. 16x128x16 map chunk sent for [-1024, 0, 48], overwriting the mini-chunk. Now it's drawn, because client has prechunk and full map chunk. Remember, chunk sizes are encoded as size-1.

Currently unlisted packets.

Some packets are listed as only going in one direction, but are actually sent the other too. To my knowledge, these are:

  • S->C 0x0a
  • S->C 0x0b
  • C->S 0x3b (mentioned above)

The packets are identical to their counterparts. Barneygale 17:02, 15 December 2010 (EST)


Were you connecting to a standard server? I've only received 0xa and 0xb from unofficial servers. --Axus 13:21, 16 December 2010 (EST)

beta update December 20, 2010

Someone pasted some notes about the protocol changes here: http://pastebin.com/YfR9XgC2

Question: Does 0x0D Player Position and Look Client->Server still differ from Server->Client?

I haven't seen any differences in how player position works. I've updated my wrapper and server to work with the new protocol and everything seems fine. See this diff for most packet changes: https://github.com/blixt/pyminecraft/commit/af4c9f6b9b2387e429fa425dd5061ef01e03c5aa#diff-1Blixt 10:30, 21 December 2010 (EST)
I updated the packets that were missing information, and changed the notion from "inventories" to "windows" as that makes more sense. I also believe that's the term used by Notch when he mentioned his implementation in some blog post. - Blixt 19:25, 21 December 2010 (EST)
Sorry, the term he used was "popup", not "window". But still, the way the packets work is popup/window-centric, not inventory/container-centric (since every time a popup/window is opened, it gets a new id, the ids are not specific to which container/inventory is opened - except for the player inventory of course). - Blixt 07:18, 22 December 2010 (EST)

Note! As of 1.1, the Transaction packet goes in both direction (previously it was only sent by the server). - Blixt 09:56, 22 December 2010 (EST)

Why the merge?

I noticed the client/server and server/client sections were merged - why was this? It makes it difficult to tell the difference between packet directions when they're unidirectional. --SpaceManiac 13:31, 21 December 2010 (EST)

I don't mind the merge so much (the page is quite a bit shorter), but we should have a list or table of C<->S mapping. Having quick access to that makes writing an inbound {client, server} decoder much easier. --kev009

Actually, a merge makes sense, since the original Minecraft server itself does not differ between directions when defining its packets (that's why there are two unused fields in each direction for the handshake packet, for example). But yes, a notion on which direction(s) a packet can be sent would make sense, possibly with a simple table for each direction at the top for a quick reference on all packets for one direction. - Blixt 19:23, 21 December 2010 (EST)

Y/Stance

Two things.. The "Y" and "Stance" are, for Client->Server at least, in the same order in both 0B and 0D packets. Perhaps the discrepancy has been fixed in a recent protocol version, but I haven't checked Server->Client yet.

Also the F3 Coordinate display in Minecraft shows, for Y, what we are calling "Stance" on the page. The server uses "stance" to mean neither coordinate, but in fact the difference between the two, ie, the height of the player. This would make more sense as something to be called "stance" too.

So, I would say the upper of the two coordinates (currently called "stance") should be called "Y", and the lower (currently called "Y") should be "foot height" or something like that. Neither should be called "stance". Moo 10:15, 1 January 2011 (MST)


I like having "Y" correspond to player's foot position. What happens if player is standing at Y=127? Eye height becomes 128.62, which maps out of the normal chunk coordinates. Items and monsters give Y at their foot position, doing the same with players would be consistent. --Axus 07:16, 3 January 2011 (MST)


"What happens if player is standing at Y=127? Eye height becomes 128.62," Minecraft itself shows the player's Y coordinate as 129.62 when as high as can currently be reached. Monsters and items don't have a camera/eye position to account for, so that would probably explain why they use the "foot position". Moo 16:15, 6 January 2011 (MST)
I agree with Axus that "Y" should be the foot position to be consistent with mobs and such. But "Stance" is really the wrong name for the field in the Player Position messages. Like Moo said, the server calls "stance" the difference between the eyes and feet. The fields in the Player Position messages should be "Y" and "Eye Y". Note that Eye Y is NOT the top of the player's bounding box. Players are 1.74 meters tall, and foot-to-eye distance only goes up to 1.65 meters. Also changing your Eye Y does not make you appear to crouch according to my experiments. --Thejoshwolfe 04:35, 9 February 2011 (MST)

Connection "hash" somewhat misleading?

I know some guys who are writing server software for Minecraft, and I know one thing they were confused about was how to generate the connection "hash". Was it an MD5 hash or a SHA1 hash or what? I looked into it for them and discovered that it wasn't actually what we considered a hash at all. Instead, it was a random long in hexadecimal form. Literally. Take a look at this code:

public void a(h paramh) {

 if (this.e.l) {
   this.i = Long.toHexString(d.nextLong());
   this.b.a(new h(this.i));
 } else {
   this.b.a(new h("-"));
 }

}

h turns out to be the handshake packet class. this.b.a() appears to send the client a packet, and this.d (referred to as just d) is a Random object. this.e.l is the variable in the MinecraftServer object that tells whether 'online-mode' is on or off. All I'm asking is for there to be a little clarification on what exactly the connection "hash" is, as not everyone can go trudging through obfuscated code to find how it's generated. Is it alright for me to do this? AnonymousJohn 21:21, 9 January 2011 (MST)

Beta 1.2 Update

Lots of "interesting" things.

The most "interesting" is what looks like "Custom mob data" at the end of Mob Spawn 0x18 and new packet 0x28 (Mob Update?). The "Custom mob data" is a byte stream with each data type encoded in a byte. According to pastebin:

The "metadata" byte is split this way:

  • j: First 3 bits, data type
  • k: Last 5 bits, data key

"j" data type:

  • 0: byte
  • 1: short
  • 2: int
  • 3: float
  • 4: string (short, bytes)
  • 5: inventory item (short, byte, short)

After the "metadata" byte is data of the "data type".

Example:

  • 0x00, 0x00, 0x7F:
    • j = 0, k = 0. Key = 0, byte value = 0x00.
    • End of stream marked by 0x7F.
  • 0x00, 0x00, 0x10, 0xFF, 0x7F:
    • j = 0, k = 0. Key = 0, byte value = 0x00.
    • j = 0, k = 16. Key = 16, byte value = 255.
    • End of stream marked by 0x7F.

Packet ID datatype explanation

The page needs to mention what datatype the packet ID is. My experimentation has revealed it to be unsigned char, however I'm not sure whether this is correct, and if so, where it should appear on the page. --ElectronicsRules 04:40, 17 January 2011 (MST)

OK I added something. --Axus 05:24, 17 January 2011 (MST)

Signed/Unsigned Byte Values

Section #SizeX.2C_SizeY.2C_SizeZ in the Map Chunk section says that bytes can be values up to 255. There needs to be clarification when bytes are signed and when they're unsigned. Java's bytes are always signed. --Thejoshwolfe 20:31, 23 January 2011 (MST)

Absolute integer relation to absolute position

The formula is currently stated as:

absolute_int = (int)(absolute_double / 32.0);

But in my understanding it should be:

absolute_int = (int)(absolute_double * 32.0);


I think you're correct. You have to divide "absolute int" by 32 to get the block position, and "absolute double" is block position with extra precision --Axus 08:44, 30 January 2011 (MST)

Oops. Good catch. Thanks. --Thejoshwolfe 16:19, 30 January 2011 (MST)

Packet 0xA

I've removed the note about this packet being used for speedhacking detection as it doesn't really make sense considering it is a client-to-server packet. The client is authoritative on movement of the player. Note that the "Player moved wrongly" server console warning is based on movement delta thresholds and not ground/airborne state, which seems to be used exclusively for fall damage application (try forcing the "on ground" state to be True in all c>s player movement packets) --Entity 06:05, 5 February 2011 (MST)

Forcing 'on ground' state to be True on all c->s movement does indeed eliminate fall damage. However, when 'on ground' is forced True, you cannot ride minecarts - I haven't tested this yet for boats. Coldelectrons 09:00, 1 May 2011 (MST)

big endian conversion c++

converting integer types from big endian to little endian and vice versa is rather simple

when using visual studio this might need some adjusting thou please make sure you understand this and reimplement it to fit your needs, this is basically just pseudo code that could be compiled with a c++ compiler

#include <endian.h>

int32_t toInt(char* somedata)
{
  int32_t result = *((int32_t*)somedata);
  result = be32toh(result);
  return result;
}

//for doubles and floats you need some more pointer magic (I know it's evil)

float toFloat(char* somedata)
{
  int32_t result = *((int32_t*)somedata);
  float* result_pointer = & result;
  result = be32toh(result);
  return *result_pointer;
}

--Ker 14:53, 17 February 2011 (MST)

Wolves metadata

I'm handling metadata as explained here http://mc.kev009.com/Protocol#Metadata When i do byte y = x >> 5; i keep getting -4 for wolves. New type of metadata, or is it just my fault? --Ligustah 04:18, 1 April 2011 (MST)

Not necessarily wrong, X might really be 0xFFC?????, which would make Y look like "-4". Need to be checked of course. --Axus 08:03, 2 April 2011 (MST)

I did a little more testing: https://gist.github.com/900428 I added metadata packets that i received in different situations. --Ligustah 06:35, 3 April 2011 (MST)

The -4 mentioned earlier was actually my bad. I was using a byte to hold my x while it should have been an unsigned byte. I also updated the paste above and added all indices i observed with this packet. --Ligustah 08:16, 3 April 2011 (MST)

Version 11 (Beta 1.5)

Changes I've noticed so far:

All strings in packets are now 2-byte Big-Endian Unicode. The string length prefix value specifies #of chars not bytes;

Packet 0x64 appears all different. String remains Modified-UTF. That's a big consistency WTF.

Packet 0x66 gained a byte between Action and Item ID

Login 0x01 response from server now appears EID (int) followed by 11 bytes (in my case); Looks like short,string,long,byte and that the second string was dropped. Total packet len 16 + (2 * strSize).

Weather Event Packet 0x47 (71). (int, byte, int, int, int)
So far this packet has only shown itself for a lightning strike. The value of the byte was then always 1. During all other events (rain start/stop) this packet was nowhere to be seen whether during gameplay or when logging to SMP during a rainstorm. The first int appears to be an Entity ID as it always grew with every new strike. Last 3 ints were the X,Y,Z coords respectively of the strike on the ground. It appears to be only S->C --xiix 11:19, 20 April 2011 (MST)

Packet 0x46 was also updated. The packet is the ba class. I grepped for "new ba" and got 3 hits

The first 2 are in the dg class. These extends the da class which has code that seems to slowly change the raining state.

protected void i()
{
   boolean bool = v();
   super.i();
   
   if (bool != v())
     if (bool)
       this.z.f.a(new ba(2));
     else
       this.z.f.a(new ba(1));
}

The call to v() checks if it is still raining and the call to i() updates the raining counter.

This basically says that if the rain state changes, send a 0x46 packet.

1 = begin raining

2 = end raining

The next hit is in the du class.

 if (this.e.e.v()) {
   localgj.b(new ba(1));
 }

this.e is the MinecraftServer and this.e.e is of type dg. This says that if it is raining, then send a packet with code 1. This method seems to be for logging in.

The final hit is in the ep class.

   if (localaq2 != null) {
     localdc.c(localaq2.a + 0.5F, localaq2.b + 0.1F, localaq2.c + 0.5F, 0.0F, 0.0F);
     localdc.a(localaq1);
   } else {
     localdc.a.b(new ba(0));
   }

The is probably the bed case.

So, anyway, the possible values would be:

Code Effect
0 Invalid Bed
1 Begin raining
2 End raining

Tested and confirmed --xiix 15:30, 23 April 2011 (MST)

The reason byte is a public variable, so it is possible that the code is set from other places. However, since the string array only has 3 values, that suggests that these are the 3 valid values.

Btw, what is the policy on editing the main protocol page itself? --Raphfrk 13:57, 23 April 2011 (MST)

Mystery packet 0xC8 (200). Follows hitting entities (cows and whatnot) or destroying/placing anything else:

  • bool : 0 entity destroyed; 1 otherwise, even if block is dug out it still exists so maybe that's why this one's always 1;
  • byte : 0 entity/block destroyed; 2 block or item placed;
  • byte : ???;
  • byte : block/item ID; for entities no clue;
  • byte : for bool=0 changes depending on what you hold, hit strength maybe;

Sent only Server->Client.

--xiix 18:20, 19 April 2011 (MST)

/* Item data type */

In my own code, I've simplified things by treating the 3 items (short, optional byte,short) as an Item. It makes my packet format definitions far more readable.

Any votes in favor of applying the Item definition to the existing page?

Size Range Notes
Item 2-5 N/A The structure is (short ItemID, [byte Count, short MetaDamage]). If ItemID == -1, the latter two items are omitted.

-- Coldelectrons

Would have been fine but 0x05 does not comply with this. Personally I'd rather deal with no rules than rules that have exceptions to them. --xiix 09:43, 20 April 2011 (MST)

0x01 Login C->S (Version 11)

Since I'm a n00b here I won't edit the wiki itself for the fear of being an idiot, but to whoever did: from my own packet analysis the 'Client->Server' login 0x01 packet remains unchanged except for the String8->String16 mod. Either Password (or other text) is still possibly sent (now empty) or it has 2 extra (0,0) bytes for whatever reason after username. So the makeup for my money is int, string16, string16, long, sbyte. The length of the packet remains 18 + len of string16's.

Also, re new String16 thing. Maybe this is common knowledge for java folk, but for us MS/.NET dweebs it is important to know that the new string16 is actually UTF-16BE, as UTF-16 (implies UTF-16LE) decode will render gibberish.

--xiix 09:38, 20 April 2011 (MST)

Note that it's actually big-endian UCS-2. Treating it as UTF-16 will likely work most of the time, except for crafted packets or otherwise misbehaving peers.

--Huin 14:22, 15 May 2011 (MST)

/* Byte-packed double? */

The 3 ints int the weather packet: Can someone please explain or link to an explanation of how it is you pack a double-precision floating point (8 bytes) number into an int (4 bytes)? Bonus points for why you would want to do it that way?

I might be wrong but I don't think it is a packed double in a true packing sense. What you do is in this instance is:

double = int / 32.0 --xiix 08:26, 21 April 2011 (MST)

0x32 (pre-chunk) packet optional?

I've tried sending 0x33 packets without 0x32 packets to a 1.5 Beta client on initial connection - the client simply doesn't like it, and just jiggles up and down and the chunks are not visible.

Sending the same 0x33 packets with 0x32 packets following results in the client falling, but the chunks being completely air-blocks.

The chunks only appear to load correctly if each 0x33 packet is preceded by the corresponding 0x32 packet (even if not immediately preceding).

Any other observations on this matter? It appears to me that the 0x32 packet to initialize the chunk is always required, rather than optional as the current text about packet 0x33 might suggest.

--Huin 14:19, 15 May 2011 (MST)

It might only matter on chunks close to the player. I think the "optional" note was more for client writers to allow strange exceptions from Notch's server, than for letting server writers take it easy ;) --Axus 16:03, 16 May 2011 (MST)

Perhaps the times when the notchian server *doesn't* send the 0x32 is when the 0x33 packet is for a subset of the chunk (that is: an already loaded chunk). It would be nice to back this up with evidence of course. --Huin 14:24, 21 May 2011 (MST)

0x18 - Where does the 'Index' come from? + Metadata String

Can somebody tell me where the index come from? Is this a byte in the metastream or what ?

Additionally there is no information about the width of the string chars in a metastream.

--Chrisliebaer 11:39, 22 May 2011 (MST)

0x47 - Weather?

22 May 2011 - Just started writing a library to read and write packets. Tried to follow the spec for 0x47 on the page, and kept getting errors. Looked at a Wireshark capture, and I see the 0x47 packet as being 8 bytes long (9 with the header). The first four bytes look to be an int related to location? It was negative in my capture. The next three bytes were all 0's, then a 0x02. --User:Nyasara

Map data (0x83)

It seems like there is a new packet 0x83 which I can't figure out. Decompiling it reveals four possible forms: http://pastie.org/1975651 --Sadimusi 04:10, 26 May 2011 (MST)

I wonder if it handles something related to Nether travel (probably reaching).

I guess the respawn packet with the new field might be all that was added for handling this.

Does the Nether have any use for a new world seed? If not, then I guess adding the Nether didn't require that a "change world seed" packet was created. If so, that is pretty disappointing. This would have been a perfect time to add a way to update the client's world seed.

I am going to run a test tonight to see if the client can handle a second login packet after the update.

--Raphfrk 05:12, 26 May 2011 (MST)

Block Action? (0x3D)

This packet is

Int Int Byte Int Int

It seems to be related to opening doors

Int: 1003 (constant) Int: X position of door Byte: Y position of door Int: Z position of door Int: 0 (constant)

The packet is sent to all players except the player who opens the door. --Raphfrk 11:56, 26 May 2011 (MST)

It is also sent to all near players when a door is opened with a redstone current. --Sadimusi 12:39, 26 May 2011 (MST)


When a player opens a door with right click, the server receives Packet 0xF (block placement, but opens door)
When a player opens a door with left click, the server receives Packet 0xE+start digging
1.7.3
Ishinay 05:31, 27 August 2011 (MST)

Unknown fields in 0x17 may be trajectory.

Especially as there is no other packet to keep track of a ranged weapons trajectory, I deem it likely that the unknown fields encode the trajectory of the projectile. I haven't done any research into this yet, but I consider two methods of encoding likely:

If X, Y and Z mark the original start point of the projectile, the last three fields may hold the initial X, Y and Z velocities of the projectile while the integer field encodes the time the projectile has already travelled on that path.

If X, Y and Z mark the current position of the projectile, the unknown int could instead hold the velocity and the remaining shorts just encode the orientation of the projectile.

Another, though unlikely option would be to encode the coordinates of the trajectories zenith.

SlashLife 13:58, 28 May 2011 (MST)

The fact that these fields were added with the same update the map item was introduced suggests a connection between those two things. Projectiles were added a long time ago and worked without these fields. --Sadimusi 16:35, 28 May 2011 (MST)


The "Unknown flag int" actually seems to be the Shooter Entity Id, useful for differenciate the source of the damage. This code exemplifies:

 EntityFireball entityfireball = (EntityFireball) this.tracker;
 Packet23VehicleSpawn packet23vehiclespawn = new Packet23VehicleSpawn(this.tracker, 63, ((EntityFireball) this.tracker).shooter.id);

The other 3 int are taken from entity speed, so with much probability marks the initial trayectory tangent as a vector.

 double speedX = entity.speedX;
 double speedY = entity.speedY;
 double speedZ = entity.speedZ;
...
 this.trayectoryX = (int) (speedX * 8000.0D);
 this.trayectoryY = (int) (speedY * 8000.0D);
 this.trayectoryZ = (int) (speedZ * 8000.0D);

Ishinay 05:14, 27 August 2011 (MST)

0x3D packet specs

Packet 0x3D is used to make effects happen on the client.

Parameters: int - identifier for effect (client chooses effect using a switch). int - X int - Y int - Z int - extra data value (used for 3 effects).

Possible values: 1000 - plays the dispenser fire sound. 1001 - plays the empty dispenser fire sound. 1002 - plays the projectile fire sound (snowball, egg, bow). 1003 - plays the (trap)door open/close sound (50/50 chance of either). 1004 - plays the fire extinguish sound. 1005 - plays a record sound (using the extra data field as an item ID). 2000 - spawns a dispenser fire particle (uses the extra data field for direction, possible 9? values). 2001 - places dig effects on the block at the given location (uses the extra data field as a block ID).

0x6A - Inventory Transaction

The bool in packet 0x6A isn't as simple as 'True if accepted'. I've been playing with inventory logic a bit, and with Notchian client/server, the 'accepted' bool has no immediately discernible rhyme or reason from the server - simply, if a transaction has been accepted, there is a Transaction packet s->c, and if not, not. -- Coldelectrons 19:40, 11 June 2011 (MST)

I tend to agree that its effect is non-obvious. I have noted that sending a "false" for that field results in the client replying with a transaction packet with "true". Beats me what it means :) --Huin 13:37, 17 June 2011 (MST)

further observations

  • When a click leaves an inventory slot empty (picking up a whole stack or item), or when the click changes the amount of the stack in the inventory slot (depositing a single item into a stack), or swapping items, the S->C accepted==False.
  • When a click puts something into an empty slot (a single item or dropping one off of a stack with right-click), the S->C accepted==True

These two could probably be simplified to "If the slot is empty when it is clicked, S->C accepted=True, else it is False". I haven't observed all conditions in all window types, so some collaboration would be helpful.

  • When the server sends accepted==False, the client will respond with a transaction packet with the same action number, but with accepted==True
  • When the server sends accepted==True, the client does not respond further.

Coldelectrons 15:44, 17 June 2011 (MST)

Decimal packet numbers?

Since the Packet classes in the minecraft source (as decompiled by mcp) are named with Decimal numbers it is kind of a hassle when trying to correlate those classes with this list of packets which only have the packet ID shown in hex. Any chance the decimal number could be included in here? In the section heading preferably so it can be seen in the index.

Entity Action ??? (0x13)

Seem to be having trouble getting this to work this is sent when someone crouches but it causes a packet error in 1.7.2 was something added? --Faith2712 19:01, 6 July 2011 (MST)

I believe you have to send the crouch in an entitymetadata packet rather than entityaction (apply the crouch flag to the metadata, then send the edited data).

Sneaking is definitely sent with 0x13 as you can see in this (unobscured) snippet from 1.7.3: http://pastie.org/2209271 --Sadimusi 14:15, 13 July 2011 (MST)
 : Faith2712 is definitely correct about it being sent from the server as entitymetadata (0x28). Packet 0x13 is client to server only.
 : The byte array for crouching would be: "0x28, [player id(4 bytes)], 0x00, 0x02, 0x7F". 0x02 can be 0x00 (for no animations), 0x01 (for fire), 0x02 (for crouch), 0x03 (for crouch and fire a same time).
 : --Jasonbay13 17:01, 11 August 2011 (MST)

Piston Direction

Should piston direction 5 not be South? East is in there twice, and south is missed out. I am not certain that it is 5 though, so I have not edited it.

Entity Status (0x26)

I've been looking into bukkit stuff today and I think I know what packet 0x26 is! It is sent any time an entity does some animation, especially I noticed with wolves:

   	HURT (2),
   	DEATH (3),
   	SMOKE (6),
   	HEARTS (7),
   	WATER (8),

This is what I've tested out so far. Smoke, Hearts, and water are mainly for wolfie animations. Note that I got these by testing and looking through the minecraft code. That's allowed, right? So far these are the only ones that are sent by the server. --Zonedabone 18:08, 12 August 2011 (MST)

Yaw diagram needs correcting

While I get the impression from Minecraft's code that some people *cough* can't tell up from down, left from right, or South from West, we here should be able to.

The unit circle by the Player Look packet description needs to be changed to reflect what you actually encounter in the game and code.

I have here a modest example:

Back Arsewards

Coldelectrons 14:45, 24 August 2011 (MST)

1.8 Pre-release changes

When refreshing the server list, packet 0xfe is sent. Its length is 1 byte. The server answers with a Kick(0xff) packet with the motd and player amount in the kick message with the format

Motd§0§20

for a server with 0 players, 20 slots, and motd set to Motd.

--Zhuowei 17:42, 9 September 2011 (MST)

Added, thanks :) Barneygale 23:32, 9 September 2011 (MST)

Creative inventory action (0x6B)

Creative inventory action (0x6B) is sent by the client when the user clicks on a quickbar-slot

Mob ID for endermen?

I'm pretty sure it's 58, can anyone confirm? Origamiguy 08:57, 16 September 2011 (MST)

Yep, 58. The code:
addMapping(net.minecraft.src.EntityEnderman.class, "Enderman", 58);
(the number is the mob ID). --DuckDuckGo 13:50, 29 December 2011 (MST)

Add Object/Vehicle correct?

About a week ago, I tried to figure out the last four fields in the Add Object/Vehicle (0x17) packet. Can someone check that I got it right? --Krenair 08:28, 25 September 2011 (MST)

0x02 (Server to Client), description misunderstunding

The current description is: "This is the first packet sent when the client connects and is used for Authentication. If the hash is '-', then the client continues without doing name authentication. If the hash is a '+', there is currently no way to send a password in at least version 1.8.1. It should be treated similarly to '+'."

But the meaning of the sentences is not clear.

  • The fact that '+' is used for password authentication is implied by the reader.
  • "It should be treated similarly to '+'." Meaning '+' similar to '+'? I guess it was supposed to be "...similarly to '-'."

Am i correct on the above assumptions?

Server poll not working in 1.0?

I've recently converted my software to match up with MC 1.0, but it doesn't seem to be working: it gives me a communication error, as if the packet's contents are incorrect. I'm currently using my 1.8 system, where the 254 packet is received and I immediately respond by sending the 255 Kick packet, with a string, such as MyServer§0§16. Any ideas? Has the protocol changed in this sense since 1.0 was released?

Fixed: I forgot that my encoder was automatically generating the packet header for packet 254 in response rather than just sending packet 255. It was generating two headers, then the payload, haha. Fixed.

More explanations!

I, for one, would be interested to know whether the animation packet is validated in any way by the server. For instance, could you send the eat animation to the server with something other than food in your hand? --DuckDuckGo 13:47, 29 December 2011 (MST)

Try it and see --Barneygale 23:07, 29 December 2011 (MST)

World height and indexing problem

I was working with Realcraft earlier tonight, rewriting it and all (I lost the source due to a HDD failure), and I got it working back to the point that it was at when I left it so long ago. I've seemed to have stumbled upon an issue. Only a world height of 128 (Size_Y=127) will work with the indexing (index = y + (z * (Size_Y+1)) + (x * (Size_Y+1) * (Size_Z+1))), any other height and the Minecraft client will show erroneous chunks. Perhaps a new indexing scheme is in order? -- Jailout2000 04:52, 2 January 2012 (MST)

Support for different world heights is only partially implemented in the protocol, e.g. the Player Digging packet has Y as a byte, meaning you're constrained to 127. --Barneygale 12:49, 2 January 2012 (MST)

1.1 changes

The protocol version number for 1.1 is 23.

Also a new string is inserted into the middle of the login packet after the Map Seed field. That increases the size of the packet to 25 plus length of strings.

Packet directon changes

Recently there were a lot of packet direction changes from Client to Server into Two-way mainly with the Player* packets.

As far as my proxy implementation goes it has never received those packages from the Notchian server so I will change it back.

--Ceiru 13:30, 17 March 2012 (MST)

Removed the last two "this command is not fully understood"

So if anyone needs to copy-paste it for new packets, here it is:

 [[File:Icon_exclaim.gif|:!:]] This command is not fully understood.

Probably should be a template, but given how advanced our tools are (like burger) and how easy it is to get official explanations from the devs, I doubt anyone will need this again. --Dx 00:58, 13 June 2012‎ (MST)

This is a relic of when I created this page. My own wiki uses DokuWiki, which provides handy icons like above. Looks like someone downloaded it and re-added it as a media upload when it was copied over. I'd advise not using it again, and instead mention it in the channel and someone will take the time to clarify before ever making a change. TkTech 01:54, 13 June 2012 (MST)

Strange Packets

At first, everything goes as it says in the documentation. As soon as I send the encrypted login request packet, though, I start getting random packets.

Strange Packets

Can someone please tell me what I'm doing wrong?


Minecraft uses AES-128-CFB8. Not AES-128-CFB128 (happened to me). Check if this happens
Shoghicp (talk) 12:36, 23 November 2012 (MST)


OK, after some analysis, I have realized that the problem is in the specification, not my code. It is actually similar to your issue.

The specs should say that you don't start over counting to 16 when you get a new packet, but rather have to accumulate 16-byte chunks to decrypt (regardless of logical or network packet boundaries).

CFB8 means that it has a block size (for encrypt/decrypt) of 1 byte, so you're able to encrypt/decrypt on the fly, and without having to wait for more data. The specifications allow variable block size for CFB, since you only have to xor the generated key with the plaintext.
Shoghicp (talk) 05:51, 24 November 2012 (MST)

Join us on IRC, freenode #mcdevs if you need help md_5 (talk) 05:02, 25 November 2012 (MST)

Packet 0x1E description

The description of packet 0x1E probably needs to be revised. The official server doesn't initialize this packet's class directly anymore, and it can therefore be assumed that this packet doesn't get sent by the official server anymore. The official client should theoretically handle this packet the same as either one of packets 0x1F, 0x20 or 0x21 with additional fields set to 0. 14mRh4X0r (talk) 18:33, 17 January 2013 (MST)

Ambiguity and Typos?

I feel that some of the information on the Protocol page is ambiguous and contains typos

  1. Player Digging (0x0E) - The field Y states the field type is "byte", which according to Data Types only ranges from -127 to 127. However, as of 1.4.7 (current version at time of writing) I am able to dig blocks up to 255. Should the field type for field Y be changed to "unsigned byte" similar to Player Block Placement (0x0F)?
    • Use Bed (0x11) has the same issue described above, and possible others too.
  2. Player Position and Look (0x0D) says that it is Two-Way. However, Player Position (0x0B) and Player Look (0x0C) say only Client to Server. Shouldn't this be changed to Client to Server, or can the server actually send Player Position and Look (0x0D)?
  3. Player Look (0x0C) is unclear. With Entity packets (server to client), there is Entity Look (0x20) and Entity Head Look (0x23), but only a single Look packet for the Player (client to server). How should a server implementing the protocol deal with sending Entity Look and Head Look of other players to clients?

--Greenegg (talk) 09:02, 19 February 2013 (MST)

The server sends 0x0D packets (with reversed Y and Stance) when the player makes an invalid move; Player Look is C->S, Entity Look is S->C. ZioCrocifisso (talk)

Why is "float" in 0x08 bold?

Does it mean anything or may be safely removed? http://wiki.vg/Protocol#0x08

Rename category to state

Should we rename the Category column to State? This would make it clearer that the packet type depends on both the packet ID and the current state. —Fenhl 03:32, 21 January 2015 (UTC)

String terminator

For strings, I understand that there's a VarInt for the length of the string, and the string itself. This means a null terminator isn't needed to specify the end of the string. Should my code include a null terminator, or should it trim that final character? I'm trying to mirror the behavior of the Notchian client/server. NickNackGus (talk) 13:22, 25 May 2016 (UTC)

What happends if you don't send CPacketConfirmTeleport / what does it do and what are the effects of sending it? (serverbound-related)

I'm just curious.

Click Window

The documentation says "Slot" is a short. So I used PacketContainer#getShorts().read(0), but after some tests I realized that the index 0 was actually "ActionNumber". To fix it, I changed to PacketContainer#getIntegers().read(1). --RoinujNosde

The documentation is about what is delivered in the network stream and not how minecraft is saving the data in the Packet objects, which is what you get when using ProtocolLib. --Janmm14 (talk) 17:32, 16 October 2019 (UTC)

Can't make a valid chunkdata packet (0x21)

Hi i'm stuck with this packet, i can't manage to make a valid packet for the client, i think it's due to my height map wich may not be valid but i don't understand how to make it valid using the doc

here i try to send this packet to the client (all is 0, i just want to understand the formating before using real data) (in hex, the heightmap is in bold) c0 02 21 00 00 01 01 0a 00 0c 00 0f 4d 4f 54 49 4f 4e 5f 42 4c 4f 43 4b 49 4e 47 00 00 00 24 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

i get this error with the client : Internal Exe... io.netty.handler.codec.EncoderException: java.io.EOFException: fieldSize is too long! Lenght is 21577, but maximun is 306

from my understanding of nbt i don't see how could it read this value somewhere

i've also tried with a Heightmaps named coumpound

Let's disect your packet:
   c0 02 # Packet Length
   21 # Packet ID
   00 00 01 01 # Chunk X
   0a 00 0c 00 # Chunk Z
   0f # Full Chunk? (Should be 1 or 0)
   4d # Primary BitMask
   4f # NBT Tag (Invalid)
   54 49 # NBT Tag Name Length (0x5449 = 21577), all NBT data is implicitly inside a Compound
   ... # Client probably doesn't even read the rest, it knows Packet Length < NBT Tag Name Length
You seem to be writing your chunk coordinates as VarInts, when they are specified on the wiki as Ints.
YoYoYonnY (talk) 12:19, 22 April 2020 (UTC)

oh thx for the response i've made it work since then, and found out that this packet has great potential to crash clients :)

Little bug?

In the 'Dimension type' Section:

Name Type Meaning Values
coordinate_scale TAG_Float The multiplier applied to coordinates when traveling to the dimension. 1: true, 0: false.

Should it be "1: true, 0: false."?

Sorry for my poor English.

Handshake and Login both in 1 packet?

Hi, I'm writing a proxy for inspecting the minecraft protocol. This page has been incredibly helpful, but i've noticed that when my 1.16.5 client wants to connect my server it sends a packet like this:

10 00 F2 05 09 6C 6F 63 61 6C 68 6F 73 74 1B 39 02 0A 00 08 6B 61 62 6F 75 74 65 72

that represents the following values:

size: 0x10
Packet ID: 0x0
Protocol Version: 754
Server Address: localhost
Server Port: 6969
Next State: 2

and according to the described protocol this should be all the values, but my client also sends

0A 00 08 6B 61 62 6F 75 74 65 72

I don't have a clue about the first two characters but from 08 and after is my username encoded as a String: kabouter The server responds with what looks to be an Protocol#Encryption_Request Does anyone know about this way to login?

There can be multiple Minecraft protocol-level packets in one TCP packet (and one Minecraft packet can be split across multiple TCP packets). What you're seeing is Handshake followed by Login Start. --Pokechu22 (talk) 01:27, 15 June 2021 (UTC)

Specify the specific DER encoding

I struggled for a while with the DER encoding for Encryption Request because I thought it was PKCS#1 but it's actually PKIX. Could we specify that? Mattf (talk) 19:10, 6 February 2022 (UTC)

Differentiation between multiple Minecraft protocol level packets in one TCP packet

I've noticed (and confirmed from this section: https://wiki.vg/Talk:Protocol#Handshake_and_Login_both_in_1_packet.3F) that multiple Minecraft protocol level packets can be put into one TCP packet, and sometimes they can be split across multiple packets. Is there a good way for differentiating between packets/grouping them together? From what I understand there isn't really an "end of packet" marker so it's hard to tell if the client is sending multiple packets or just more data.

You should ignore individual tcp packets and jsut see the input as a stream of bytes. Before each packet there is the packet format stuff. You are to expect that after you read all bytes of a minecraft packet (determined by the length varint), that the next bytes are the length of the next minecraft packet. Janmm14 (talk) 23:25, 16 March 2023 (UTC)

LEB128

I've been implementing LEB128 VarInt in Java using a combination of this video, https://www.youtube.com/watch?v=GuuhUwn-8ug, and the sample values on this page. I've discovered a discrepancy that I'm hoping to find some clarity on. The Sample VarInts show the decimal value 127 being represented as 0x7f, which is true for unsigned integers, however, it seems that the Minecraft protocol expects integers to be signed, and the signed representation of 127 is 0xff 0x00 to account for the sign bit which is expected to be one position lower than the continuation bit in the last byte. Since the binary representation of 127 is 0b0111 1111, the sign bit is active which would be interpreted as negative according to the LEB128 specification. For this reason, an empty byte is added to show that it is positive, hence 0xff 0x00. A similar thing is true for 2097151. Any positive number where the last byte is 127/0x7f requires an additional byte to account for the sign. This statement, "Because Minecraft uses the normal encoding instead of ZigZag encoding, negative values always use the maximum number of bytes," is also not true if, in fact, Minecraft follows LEB128. As long as the negative number can be represented by fewer than 7 bits, the sign bit can be on in the first byte which will yield the correct number when decoded. This seems pretty clear from LEB128, so do these examples need to be updated, or do we need to remove the statement that Minecraft follows LEB128 (with the 5 byte limit imposed on it)? Of course, it could also just be the case that Minecraft VarInts are actually unsigned LEB128 integers. That would render all the statements true requiring that things are updated to drop sign.

World Event packet update

Taking a look at the source code of Minecraft 1.20.4, it seems the events for opening and closing doors (event IDs 1005-1008 and 1011-1014) have been removed. Event ID 1011 is now in use to stop a currently playing record, while event ID 1010 can no longer be used to achieve this.

0x4A identifiers can be arbitrary

"Select Advancements Tab" says that the Identifier can be any of the five vanilla root advancements, but in fact, judging from the identifiers matching the vanilla datapack, it seems that the identifier can be any arbitrary root that client knows about.WithLithum (talk) 03:05, 10 June 2024 (UTC)

New packet 0x1A?

I received this packet the first time I tried talking to a server. It's packet type 0x1A, but neither of the type 0x1A listed seem to match it. New discovery?

1A                                                (packet ID)
9B 01                                             (length of following string data, varint 155)
7B 22 74 72 61 6E 73 6C 61 74 65 22 3A 22 64 69   (The data is a JSON payload telling me why the server is disconnecting me...)
73 63 6F 6E 6E 65 63 74 2E 67 65 6E 65 72 69 63 
52 65 61 73 6F 6E 22 2C 22 77 69 74 68 22 3A 5B 
22 49 6E 74 65 72 6E 61 6C 20 45 78 63 65 70 74 
69 6F 6E 3A 20 69 6F 2E 6E 65 74 74 79 2E 68 61 
6E 64 6C 65 72 2E 63 6F 64 65 63 2E 44 65 63 6F 
64 65 72 45 78 63 65 70 74 69 6F 6E 3A 20 6A 61 
76 61 2E 6C 61 6E 67 2E 52 75 6E 74 69 6D 65 45 
78 63 65 70 74 69 6F 6E 3A 20 56 61 72 49 6E 74 
20 74 6F 6F 20 62 69 67 22 5D 7D 

Currently we say "the protocol immediately switches to a different state after the client sends the first packet", but what if the first packet is invalid?

What I sent:

00                                               (packet ID, handshake)
FF FF FF FF 0F                                   (protocol version -1)
0C 31 39 32 2E 31 36 38 2A 31 2E 35 36           (hostname, in this case a local network ip addr)
63 DD                                            (port, 25565)
01                                               (next state, Status)

Trejkaz (talk) 14:55, 11 July 2024 (UTC)

First of all, you're probably using an older Minecraft version. The newest version I found where 0x1A means Disconnect is 1.20; there may be others too. That would explain the weird packet ID. Second, are you sending a packet length field (not included in the dump shown)? If not, that might be it (the FF FF FF FF 0F gets parsed as a length, which is too long for the special 1-3 byte length field VarInt parser), though the response from 1.20 is slightly different ({"translate":"disconnect.genericReason","with":["Internal Exception: io.netty.handler.codec.CorruptedFrameException: length wider than 21-bit"]}), so it would have to have been a different version if that were the case. However, it does indeed use the Play protocol packet ID for Disconnect (0x1A), unlike newer versions I tested (which just silently disconnect). This again suggests use of an old version. After adding a length field the packet worked fine on 1.20, 1.20.4 and 1.21 (the handshake and status protocols are deliberately backward and forward-compatible, it's just that the older server was leaking the Disconnect packet from its incompatible play protocol to the handshake phase). So either the length field is wrong or missing, or there's a bug causing the sent packet to be different from what you showed. --LassiPulkkinen (talk) 19:53, 11 July 2024 (UTC)
As far as my API currently treats it, the size is written before the packet, which is why it isn't in that dump. Trejkaz (talk) 10:41, 12 July 2024 (UTC)