Files
minecraft_protocol/packets/catalog-control-states.md
T
claude-timemachine 90b711d12a packets/: packet model + catalogs + wire-format deep-dives
Control-state catalogs (handshake/status/login/config), categorized Play
catalog (~182 packets), and deep-dives on the four hard formats: chunk data
(paletted containers + light), entity metadata (type registry), slot/structured
components, command graph (Brigadier). Sourced from minecraft-data + ViaVersion.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 15:15:26 +02:00

180 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Packet Catalog — Control States
Complete packet tables for the small, fully-enumerable states: **Handshaking, Status, Login, Configuration**.
> **Baseline:** 1.21.1 (protocol 773). Version deltas noted inline.
> **Sources:**
> - `minecraft-data/data/pc/1.21.1/protocol.json` — IDs and field types (machine-readable ground truth)
> - ViaVersion `ClientboundLoginPackets.java`, `ServerboundLoginPackets.java` — enum ordinal cross-check
> - ViaVersion `ClientboundConfigurationPackets1_20_2.java`, `1_20_5.java`, `ServerboundConfigurationPackets1_20_2.java`, `1_20_5.java` — version delta cross-check
> - minecraft.wiki/w/Java_Edition_protocol/Packets — field names and semantic descriptions
>
> **See also:** [../03-handshake.md](../03-handshake.md) · [../04-status-ping.md](../04-status-ping.md) · [../05-login-encryption.md](../05-login-encryption.md) · [../06-configuration.md](../06-configuration.md)
---
## Handshaking State
The handshaking state has **no clientbound packets**. There is exactly one modern serverbound packet; the legacy ping byte is a legacy artifact that predates the formal state machine.
### Serverbound
| ID | Name | Direction | Field summary |
|--------|------------------------|-----------|---------------|
| `0x00` | Handshake | C→S | `protocolVersion` (VarInt), `serverHost` (String ≤255), `serverPort` (u16), `nextState` (VarInt: 1=Status, 2=Login, 3=Transfer¹) |
| `0xFE` | Legacy Server List Ping | C→S | `payload` (u8, always `0x01`); pre-1.7 clients only — modern servers recognize and respond with legacy format² |
¹ `nextState=3` (Transfer) added in 1.20.5 (protocol 766).
² `0xFE` is outside the normal VarInt packet-ID space; servers detect it by the raw byte value.
Source: `minecraft-data/data/pc/1.21.1/protocol.json``handshaking.toServer.types` mappings `{"0x00": "set_protocol", "0xfe": "legacy_server_list_ping"}`.
---
## Status State
Two packets in each direction. IDs are stable since 1.7.
### Serverbound
| ID | Name | Direction | Field summary |
|--------|----------------|-----------|---------------|
| `0x00` | Status Request | C→S | No fields; triggers Status Response |
| `0x01` | Ping Request | C→S | `time` (i64, ms timestamp) |
### Clientbound
| ID | Name | Direction | Field summary |
|--------|-----------------|-----------|---------------|
| `0x00` | Status Response | S→C | `response` (String; JSON with version, players, description, favicon) |
| `0x01` | Pong Response | S→C | `time` (i64; echo of Ping Request's timestamp) |
Source: `minecraft-data/data/pc/1.21.1/protocol.json``status.toServer` / `status.toClient` mappings.
---
## Login State
Login was extended in **1.20.2** (Login Acknowledged) and **1.20.5** (Cookie Request/Response).
### Serverbound
| ID | Name | Direction | Since | Field summary |
|--------|------------------------|-----------|---------|---------------|
| `0x00` | Login Start | C→S | 1.7 | `username` (String ≤16), `playerUUID` (UUID) |
| `0x01` | Encryption Response | C→S | 1.7 | `sharedSecret` (ByteArray, VarInt-length-prefixed; RSA-encrypted), `verifyToken` (ByteArray, VarInt-length-prefixed; RSA-encrypted) |
| `0x02` | Login Plugin Response | C→S | 1.13 | `messageId` (VarInt; echoes request), `data` (optional restBuffer; absent if unhandled) |
| `0x03` | Login Acknowledged | C→S | 1.20.2 | No fields; transitions server to Configuration state |
| `0x04` | Cookie Response | C→S | 1.20.5 | `key` (String; resource location), `value` (optional ByteArray ≤5120 bytes) |
### Clientbound
| ID | Name | Direction | Since | Field summary |
|--------|------------------------|-----------|---------|---------------|
| `0x00` | Disconnect (Login) | S→C | 1.7 | `reason` (String; JSON text component) |
| `0x01` | Encryption Request | S→C | 1.7 | `serverId` (String, always `""` in modern protocol¹), `publicKey` (ByteArray; DER-encoded RSA), `verifyToken` (ByteArray; random nonce), `shouldAuthenticate` (bool; false = offline-mode) |
| `0x02` | Login Success | S→C | 1.7 | `uuid` (UUID), `username` (String ≤16), `properties` (Array of {name:String, value:String, signature:Optional\<String\>}), `strictErrorHandling` (bool; added 1.20.5²) |
| `0x03` | Set Compression | S→C | 1.8 | `threshold` (VarInt; packets ≥ this size get compressed; 1 = disable) |
| `0x04` | Login Plugin Request | S→C | 1.13 | `messageId` (VarInt; unique per request), `channel` (String; resource location), `data` (restBuffer; plugin-defined payload) |
| `0x05` | Cookie Request (Login) | S→C | 1.20.5 | `cookie` (String; resource location key) |
¹ Server ID was used for session-server auth in very old versions; now always empty string.
² `strictErrorHandling` field added in 1.20.5 — older clients receive a shorter Login Success.
Source: `minecraft-data/data/pc/1.21.1/protocol.json``login.toServer` / `login.toClient` mappings.
ViaVersion cross-check: `ClientboundLoginPackets.java` ordinals 05 match; `ServerboundLoginPackets.java` ordinals 04 match.
---
## Configuration State
**Added in 1.20.2 (protocol 764).** Not present in 1.20 or earlier.
The Configuration state runs between Login Acknowledged and Finish Configuration. Its purpose: push registry data, feature flags, resource packs, and tags before the client enters Play. The state can be re-entered from Play (server sends `Start Configuration`).
The packet set expanded again in **1.20.5 (protocol 766)**: Cookie, Transfer, Store Cookie, resource-pack split (push/pop vs. unified), Select Known Packs, Custom Report Details, Server Links were added, shifting most IDs.
### Serverbound
| ID | Name | Direction | Since | Field summary |
|--------|------------------------------|-----------|---------|---------------|
| `0x00` | Client Information | C→S | 1.20.2 | `locale` (String ≤16), `viewDistance` (i8), `chatFlags` (VarInt), `chatColors` (bool), `skinParts` (u8 bitmask), `mainHand` (VarInt: 0=left,1=right), `enableTextFiltering` (bool), `allowServerListings` (bool) |
| `0x01` | Cookie Response | C→S | 1.20.5 | `key` (String; resource location), `value` (optional ByteArray ≤5120 bytes) |
| `0x02` | Plugin Message | C→S | 1.20.2 | `channel` (String; resource location), `data` (restBuffer; `minecraft:brand` → UTF-8 VarInt-prefixed client brand string) |
| `0x03` | Acknowledge Finish Configuration | C→S | 1.20.2 | No fields; transitions to Play state |
| `0x04` | Keep Alive | C→S | 1.20.2 | `keepAliveId` (i64; echoes server's value) |
| `0x05` | Pong | C→S | 1.20.2 | `id` (i32; echoes server's Ping id) |
| `0x06` | Resource Pack Response | C→S | 1.20.2 | `uuid` (UUID; 1.20.5+¹), `result` (VarInt: 0=Success,1=Declined,2=Failed,3=Accepted,4=Downloaded,5=InvalidUrl,6=FailedReload,7=Discarded) |
| `0x07` | Select Known Packs | C→S | 1.20.5 | `packs` (Array of {namespace:String, id:String, version:String}) |
| `0x08` | Custom Report Details | C→S | 1.21 | `details` (Array of {key:String, value:String}; debug crash info)² |
| `0x09` | Server Links Response | C→S | 1.21 | `links` (Array; echoes known-type or custom-text link list)² |
¹ In 1.20.21.20.4 the resource pack response had no UUID field; UUID was added when resource-pack-push/pop split was introduced in 1.20.5.
² IDs `0x08` and `0x09` are present in 1.21.1 per `protocol.json` (`custom_report_details`, `server_links`) but absent from earlier ViaVersion 1.20.5 enum — confirm exact introduction version.
<!-- UNCONFIRMED: Exact first version for SB Custom Report Details (0x08) and Server Links Response (0x09) — protocol.json shows them in 1.21.1; ViaVersion 1_20_5 SB enum only lists 8 entries (0x000x07). Likely 1.21.0 or 1.21.1. -->
**ID shift note (1.20.2 → 1.20.5 serverbound):**
| ID (1.20.2) | Name | ID (1.20.5+) |
|-------------|------------------|--------------|
| `0x00` | Client Information | `0x00` (no change) |
| `0x01` | Plugin Message | `0x02` (+1) |
| `0x02` | Finish Configuration | `0x03` (+1) |
| `0x03` | Keep Alive | `0x04` (+1) |
| `0x04` | Pong | `0x05` (+1) |
| `0x05` | Resource Pack | `0x06` (+1) |
| — | Cookie Response | `0x01` (new) |
| — | Select Known Packs | `0x07` (new) |
Source: `minecraft-data/data/pc/1.21.1/protocol.json``configuration.toServer`; `ViaVersion/.../ServerboundConfigurationPackets1_20_2.java` vs `ServerboundConfigurationPackets1_20_5.java`.
---
### Clientbound
| ID | Name | Direction | Since | Field summary |
|--------|------------------------|-----------|---------|---------------|
| `0x00` | Cookie Request | S→C | 1.20.5 | `cookie` (String; resource location key to retrieve) |
| `0x01` | Plugin Message | S→C | 1.20.2 | `channel` (String), `data` (restBuffer; `minecraft:brand` sends server brand) |
| `0x02` | Disconnect | S→C | 1.20.2 | `reason` (anonymousNbt; text component as NBT, not JSON string) |
| `0x03` | Finish Configuration | S→C | 1.20.2 | No fields; server signals config complete, waits for SB Acknowledge |
| `0x04` | Keep Alive | S→C | 1.20.2 | `keepAliveId` (i64; client must echo within ~30s or be kicked) |
| `0x05` | Ping | S→C | 1.20.2 | `id` (i32; client echoes in Pong) |
| `0x06` | Reset Chat | S→C | 1.20.2 | No fields; clears client chat session state |
| `0x07` | Registry Data | S→C | 1.20.2 | `id` (String; registry resource location), `entries` (Array of {key:String, value:Optional\<anonymousNbt\>}); one packet per registry |
| `0x08` | Remove Resource Pack | S→C | 1.20.5 | `uuid` (optional UUID; absent = remove all) |
| `0x09` | Add Resource Pack | S→C | 1.20.5 | `uuid` (UUID), `url` (String), `hash` (String, SHA-1 hex), `forced` (bool), `promptMessage` (Optional\<anonymousNbt\> text component) |
| `0x0A` | Store Cookie | S→C | 1.20.5 | `key` (String; resource location), `value` (ByteArray ≤5120 bytes) |
| `0x0B` | Transfer | S→C | 1.20.5 | `host` (String), `port` (VarInt); redirects client to another server |
| `0x0C` | Feature Flags | S→C | 1.20.2 | `features` (Array\<String\>; resource location list of active experimental features) |
| `0x0D` | Update Tags | S→C | 1.20.2 | `tags` (Array of {tagType:String, tags:Array of {tagName:String, entries:Array\<VarInt\>}}) |
| `0x0E` | Select Known Packs | S→C | 1.20.5 | `packs` (Array of {namespace:String, id:String, version:String}); client replies SB Select Known Packs |
| `0x0F` | Custom Report Details | S→C | 1.21 | `details` (Array of {key:String, value:String}); appears in crash reports¹ |
| `0x10` | Server Links | S→C | 1.21 | `links` (Array of {hasKnownType:bool, knownType:ServerLinkType (if known), unknownType:NbtComponent (if custom), url:String})¹ |
¹ `0x0F` and `0x10` present in 1.21.1 `protocol.json`; not in ViaVersion 1.20.5 CB enum (15 entries, 0x000x0E). Likely introduced 1.21.0 or 1.21.1.
<!-- UNCONFIRMED: Exact first version for CB Custom Report Details (0x0F) and Server Links (0x10) — same tracking note as SB counterparts above. -->
**ID shift note (1.20.2 → 1.20.5 clientbound):**
| ID (1.20.2) | Name | ID (1.20.5+) |
|-------------|-------------------|--------------|
| `0x00` | Plugin Message | `0x01` (+1) |
| `0x01` | Disconnect | `0x02` (+1) |
| `0x02` | Finish Configuration | `0x03` (+1) |
| `0x03` | Keep Alive | `0x04` (+1) |
| `0x04` | Ping | `0x05` (+1) |
| `0x05` | Registry Data | `0x07` (+2) |
| `0x06` | Resource Pack | split: `0x08`/`0x09` |
| `0x07` | Feature Flags | `0x0C` (+5) |
| `0x08` | Update Tags | `0x0D` (+5) |
| — | Cookie Request | `0x00` (new) |
| — | Reset Chat | `0x06` (new) |
| — | Store Cookie | `0x0A` (new) |
| — | Transfer | `0x0B` (new) |
| — | Select Known Packs | `0x0E` (new) |
Source: `minecraft-data/data/pc/1.21.1/protocol.json``configuration.toClient`; `ViaVersion/.../ClientboundConfigurationPackets1_20_2.java` vs `ClientboundConfigurationPackets1_20_5.java`.