minecraft_protocol: foundation + per-version protocol docs 1.7.10->26.2
8 topical docs (overview, data types, lifecycle, handshake, status/ping, login+encryption, configuration, version-differences) + proxy-forwarding set + 16 per-version release-line docs, sourced from minecraft.wiki, ViaVersion (source + commits), minecraft-data, node-minecraft-protocol, Velocity, BungeeCord. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,174 @@
|
||||
# 1.12.x — World of Color Update
|
||||
|
||||
**Protocols:** 335 (1.12), 338 (1.12.1), 340 (1.12.2)
|
||||
**Release dates:** 1.12 — 2017-06-07 · 1.12.1 — 2017-08-03 · 1.12.2 — 2017-09-18
|
||||
**Minecraft wiki release articles:**
|
||||
- <https://minecraft.wiki/w/Java_Edition_1.12> (fetched 2026-06-19)
|
||||
- <https://minecraft.wiki/w/Java_Edition_1.12.1> (fetched 2026-06-19)
|
||||
- <https://minecraft.wiki/w/Java_Edition_1.12.2> (fetched 2026-06-19)
|
||||
**Protocol version numbers confirmed:** `ProtocolVersion.java` lines 57-59: `register(335, "1.12")`, `register(338, "1.12.1")`, `register(340, "1.12.2")` — `/tmp/mcproto-refs/ViaVersion/api/src/main/java/com/viaversion/viaversion/api/protocol/version/ProtocolVersion.java`; cross-checked by `/tmp/mcproto-refs/minecraft-data/data/pc/1.12*/version.json`.
|
||||
**ViaVersion packages:**
|
||||
- `v1_11_1to1_12` — `/tmp/mcproto-refs/ViaVersion/common/src/main/java/com/viaversion/viaversion/protocols/v1_11_1to1_12/`
|
||||
- `v1_12to1_12_1` — `…/protocols/v1_12to1_12_1/`
|
||||
- `v1_12_1to1_12_2` — `…/protocols/v1_12_1to1_12_2/`
|
||||
**minecraft-data sources:** `data/pc/1.12/`, `data/pc/1.12.1/`, `data/pc/1.12.2/` — `/tmp/mcproto-refs/minecraft-data/`
|
||||
|
||||
---
|
||||
|
||||
## Headline changes
|
||||
|
||||
1.12 ("World of Color Update") shipped 2017-06-07. The two largest protocol additions are the **recipe book** and the **advancements system**, each requiring a new cluster of packets.
|
||||
|
||||
The recipe book is a server-driven crafting UI: the client receives a list of unlocked recipe IDs via `Unlock Recipes` (0x30 in 335; shifted to 0x31 in 338) and can request that a recipe's ingredients be placed in a crafting grid via a new serverbound packet. In 1.12 this was `Prepare Crafting Grid` (0x01 SB); the interaction was redesigned in 1.12.1 into `Place Recipe` (0x12 SB, replaces 0x01) and a new server echo `Craft Recipe Response` (0x2B CB).
|
||||
|
||||
Advancements replace the pre-1.12 achievement system. Rather than a statistics-based one-time trigger, advancements are a DAG of progress nodes stored on the server and pushed to the client. The `Update Advancements` packet (0x4C in 335; 0x4D in 338) carries a full reset flag, a map of advancement keys to display data and criteria, a list of removed advancements, and a progress map. A companion `Select Advancements Tab` (0x36 in 335; 0x37 in 338) drives the tab UI clientbound. The serverbound `Seen Advancements` (0x19 in both) carries the player's tab-open/tab-close action and current tab ID.
|
||||
|
||||
Gameplay additions visible at the protocol level: parrots (new entity type 105 in `EntityTypes1_12`, `ABSTRACT_SHOULDER_RIDING`); coloured beds (the bed block entity now requires a colour field — ViaVersion injects a fake NBT tag with `color:14` for red into chunk data sent to 1.11 clients, `Protocol1_11_1To1_12.java:94-106`); and 33 new parrot sounds (handled via numeric remapping in `getNewSoundId`, `Protocol1_11_1To1_12.java:147-167`). A `Knowledge Book` item was added (items 235-252 and 453 are unknown to 1.11 servers; ViaVersion replaces them with stone, `ItemPacketRewriter1_12.java:65-72`).
|
||||
|
||||
---
|
||||
|
||||
## Protocol changes vs 1.11 (335 vs 315/316)
|
||||
|
||||
Source: diff of `ClientboundPackets1_9_3` (the enum used through 1.11.x) against `ClientboundPackets1_12` and `ServerboundPackets1_9_3` against `ServerboundPackets1_12`; cross-confirmed by `minecraft-data` diff of `data/pc/1.11/protocol.json` vs `data/pc/1.12/protocol.json` which shows +3 CB and +3 SB net-new packets.
|
||||
|
||||
### Clientbound play — new packets (1.12 = protocol 335)
|
||||
|
||||
| ID | Name (ViaVersion enum / minecraft-data) | Notes |
|
||||
|---|---|---|
|
||||
| `0x30` | `RECIPE` / `unlock_recipes` | Pushes the list of unlocked recipe IDs to the client; controls recipe-book state (open, filter). Fields: action (VarInt), craftingBookOpen (bool), filteringCraftable (bool), recipes1 array (VarInt IDs), optional recipes2 array for "init" action. |
|
||||
| `0x36` | `SELECT_ADVANCEMENTS_TAB` / `select_advancement_tab` | Tells the client which advancement tab to show. Field: optional String tab-id. |
|
||||
| `0x4C` | `UPDATE_ADVANCEMENTS` / `advancements` | Full advancement sync. Fields: reset (bool), advancement-map (key→display+criteria+requirements), list of removed keys, progress-map (key→criterion-timestamps). |
|
||||
|
||||
All three shift IDs for packets above them: `REMOVE_ENTITIES` moves from 0x30 to 0x31, `SELECT_ADVANCEMENTS_TAB` inserts at 0x36 pushing `SET_BORDER` from 0x36 to 0x37, and `UPDATE_ADVANCEMENTS` appends above `UPDATE_ATTRIBUTES` pushing it to 0x4D and `UPDATE_MOB_EFFECT` to 0x4E.
|
||||
|
||||
Sources: `ClientboundPackets1_12.java` (full enum with ordinal-derived IDs); `minecraft-data/data/pc/1.12/protocol.json` `.play.toClient`.
|
||||
|
||||
### Serverbound play — new packets (1.12 = protocol 335)
|
||||
|
||||
| ID | Name (ViaVersion enum / minecraft-data) | Notes |
|
||||
|---|---|---|
|
||||
| `0x01` | `CRAFTING_RECIPE_PLACEMENT` / `prepare_crafting_grid` | Client sends items to move into crafting slots. Fields: windowId (u8), actionNumber (u16), array of {item, craftingSlot, playerSlot} for both "return" and "prepare" lists. |
|
||||
| `0x17` | `RECIPE_BOOK_UPDATE` / `crafting_book_data` | Carries two sub-types: type 0 = displayed-recipe (i32 recipe ID); type 1 = crafting-book-open flag + filtering flag (bools). |
|
||||
| `0x19` | `SEEN_ADVANCEMENTS` / `advancement_tab` | Player opened/closed an advancements tab. Fields: action (VarInt: 0=opened tab, 1=closed screen), optional tabId String (only for action 0). |
|
||||
|
||||
These push `RESOURCE_PACK` from 0x16→0x18, `SET_CARRIED_ITEM` from 0x17→0x1A, `SET_CREATIVE_MODE_SLOT` from 0x18→0x1B, and so on, adding three net slots.
|
||||
|
||||
Sources: `ServerboundPackets1_12.java`; `minecraft-data/data/pc/1.12/protocol.json` `.play.toServer`.
|
||||
|
||||
ViaVersion strategy (1.11.1→1.12, `Protocol1_11_1To1_12.java`):
|
||||
- `cancelServerbound(ServerboundPackets1_12.CRAFTING_RECIPE_PLACEMENT)` — drops 0x01 (old server can't handle it)
|
||||
- `cancelServerbound(ServerboundPackets1_12.RECIPE_BOOK_UPDATE)` — drops 0x17
|
||||
- `cancelServerbound(ServerboundPackets1_12.SEEN_ADVANCEMENTS)` — drops 0x19
|
||||
- Locale truncation: `CLIENT_INFORMATION` max locale length raised 7→16 in 1.12; ViaVersion truncates back to 7 when downgrading (line 131-134)
|
||||
- Bed chunk injection: injects fake `minecraft:bed` NBT block-entity with `color:14` for every bed block (id 26) in chunk data, allowing old servers (which store no bed colour) to render correctly (lines 94-106)
|
||||
- Sound remapping: 1.12 added 33 parrot sounds + 2 end-portal sounds + block-note sounds + illager sounds; `getNewSoundId` remaps the 1.11 continuous ID space (lines 147-167)
|
||||
|
||||
### Packet format notes
|
||||
|
||||
**`Unlock Recipes` action field:** VarInt with values 0 (init — sends both recipes1 and recipes2 lists, the first being "currently unlocked", the second being "all you've ever unlocked"), 1 (add), 2 (remove). When action = 0 the packet sends two arrays; for 1 or 2 it sends only recipes1. <!-- VERIFY: exact action semantics for init vs add/remove from wiki -->
|
||||
|
||||
**`Update Advancements` structure:** Each advancement entry carries: parentId (optional String), optional displayData {title String, description String, icon Slot, frameType VarInt, flags VarInt, optional background String, x float, y float}, array of criterion keys, array of requirement arrays (AND of OR). Progress map entries carry criterion key → optional completion timestamp (Long).
|
||||
|
||||
---
|
||||
|
||||
## Per-patch sub-sections
|
||||
|
||||
### 1.12 — protocol 335 (2017-06-07)
|
||||
|
||||
The initial release. Adds the recipe book, advancements, and all associated packets described above. The three new clientbound and three new serverbound play packets define the 1.12 wire baseline.
|
||||
|
||||
**ViaVersion package:** `v1_11_1to1_12`
|
||||
**Key commits (git log `-- common/src/main/java/com/viaversion/viaversion/protocols/v1_11_1to1_12/`):**
|
||||
- `8f8f5e72c` — Default rewriter registrations across protocols (includes 1.12 migration)
|
||||
- `721e27eb3` — Rewrite show_item in translation components in 1.11.1->1.12
|
||||
- `a92e75b8c` — Properly track minecart object entity types in ≤1.12.2
|
||||
- `e965e9713` — Package/class renames and moves (original package creation)
|
||||
|
||||
### 1.12.1 — protocol 338 (2017-08-03)
|
||||
|
||||
**Net packet change: +1 CB, ±0 SB (swap of one packet).**
|
||||
|
||||
The recipe-book interaction was redesigned between 1.12 and 1.12.1. The `Prepare Crafting Grid` (0x01 SB) was dropped and replaced by two simpler packets:
|
||||
|
||||
**New clientbound:**
|
||||
|
||||
| ID | Name | Notes |
|
||||
|---|---|---|
|
||||
| `0x2B` | `PLACE_GHOST_RECIPE` (`craft_recipe_response` in minecraft-data) | Server echoes back a recipe ID to fill the crafting ghost items in the UI. Fields: windowId (i8), recipe (VarInt). Inserted between `OPEN_SIGN_EDITOR` and `PLAYER_ABILITIES`, shifting all higher IDs by +1 (PLAYER_ABILITIES 0x2B→0x2C, PLAYER_COMBAT 0x2C→0x2D, etc., through UPDATE_MOB_EFFECT 0x4E→0x4F). |
|
||||
|
||||
**Serverbound change:**
|
||||
|
||||
| Before (1.12, 335) | After (1.12.1, 338) | Notes |
|
||||
|---|---|---|
|
||||
| `0x01` `CRAFTING_RECIPE_PLACEMENT` (prepare_crafting_grid) | *(removed)* | Complex slot-shuffle packet dropped |
|
||||
| *(absent)* | `0x12` `PLACE_RECIPE` (craft_recipe_request) | Simpler request: just windowId (i8), recipe VarInt, makeAll bool. Client sends this to ask the server to fill the crafting grid with a specific recipe. |
|
||||
|
||||
`PLACE_RECIPE` slots in at 0x12 between `PADDLE_BOAT` and `PLAYER_ABILITIES`; `RECIPE_BOOK_UPDATE` and `SEEN_ADVANCEMENTS` stay at 0x17 and 0x19.
|
||||
|
||||
ViaVersion strategy: `Protocol1_12To1_12_1.java` — only `cancelServerbound(ServerboundPackets1_12_1.PLACE_RECIPE)` is registered, i.e. 1.12.1 clients talking to 1.12 servers have their `PLACE_RECIPE` dropped (the old server can't understand it; the UI degrades gracefully).
|
||||
|
||||
**Other fixes in 1.12.1 (wiki):** security vulnerability in recipe book system (MC-119011); performance fix for `Class.getSimpleName` on large block-entity counts (MC-117087); crafting bug where chat messages moved items into crafting slots (MC-119840).
|
||||
|
||||
**ViaVersion package:** `v1_12to1_12_1`
|
||||
**Key commits:**
|
||||
- `501f65e21` — Packet and entity type renames (Mojang-mapped name alignment)
|
||||
- `e965e9713` — Package/class renames and moves (original package creation)
|
||||
|
||||
### 1.12.2 — protocol 340 (2017-09-18)
|
||||
|
||||
**Net packet change: 0 CB, 0 SB. One field type change.**
|
||||
|
||||
The only wire-visible change in 1.12.2 is the **Keep Alive ID type**: both `KEEP_ALIVE` clientbound (0x1F) and `KEEP_ALIVE` serverbound (0x0B) changed their `keepAliveId` field from `VarInt` to `i64` (signed 64-bit little-endian long).
|
||||
|
||||
Confirmed by:
|
||||
- `Protocol1_12_1To1_12_2.java` lines 34-47: registers explicit mappings for both directions: `map(Types.VAR_INT, Types.LONG)` (CB) and `map(Types.LONG, Types.VAR_INT)` (SB).
|
||||
- `minecraft-data/data/pc/1.12.2/protocol.json`: `packet_keep_alive` CB and SB both show `{name: "keepAliveId", type: "i64"}`, vs VarInt in `data/pc/1.12.1/`.
|
||||
|
||||
No packets were added or removed. The 80 CB / 33 SB play-packet counts from 1.12.1 are unchanged in 1.12.2 (`minecraft-data` diff: empty).
|
||||
|
||||
**Why this matters for proxies:** A VarInt keep-alive value was always truncated to the range a VarInt can represent; the server's keep-alive ID generator could now use the full 64-bit space. Any proxy doing keep-alive termination that assumed VarInt must be updated, or it will corrupt the field when the server sends a value > 2^28.
|
||||
|
||||
ViaVersion: `Protocol1_12_1To1_12_2.java` handles the field-width translation inline without any per-packet enum change; it reuses `ClientboundPackets1_12_1` and `ServerboundPackets1_12_1` unchanged (class declaration line 26).
|
||||
|
||||
Other 1.12.2 changes (wiki): title screen now shows "Java Edition" subtitle; 12 bug fixes; Log4Shell security note (affects the embedded Log4j in the dedicated server, not the protocol).
|
||||
|
||||
**ViaVersion package:** `v1_12_1to1_12_2`
|
||||
**Key commits:**
|
||||
- `5286efde1` — Move type instances out of enclosing class (Types refactor)
|
||||
- `e965e9713` — Package/class renames and moves
|
||||
|
||||
---
|
||||
|
||||
## Why 1.12.2 is a common server baseline
|
||||
|
||||
1.12.2 (protocol 340) became the de-facto long-running server version for roughly three years (2017–2020) for two compounding reasons:
|
||||
|
||||
1. **The 1.13 "Flattening" was a breaking change.** 1.13 restructured the entire block/item ID space, introduced the text-component registry system, and shifted dozens of packets. The migration cost for modpacks and plugins was enormous. Many server operators held at 1.12.2 rather than upgrade.
|
||||
2. **Mod ecosystem stability.** Forge support for 1.12.2 matured to a very stable state. The Curse/CurseForge modpack ecosystem had thousands of packs targeting 1.12.2 exclusively. This concentrated a huge portion of the modded playerbase on protocol 340 for years.
|
||||
|
||||
The combination made 1.12.2 the last version before the Flattening and the most widely deployed Forge version in history. ViaVersion's `v1_12_2to1_13` package is one of the most complex in the codebase precisely because it had to bridge this gap for that entrenched server population.
|
||||
|
||||
---
|
||||
|
||||
## Proxy and translation impact
|
||||
|
||||
### What a ViaVersion-style proxy must do for 1.12.x clients connecting to ≤1.11 servers
|
||||
|
||||
- **Drop the three new SB packets** that 1.11 servers cannot parse: `CRAFTING_RECIPE_PLACEMENT` (0x01), `RECIPE_BOOK_UPDATE` (0x17), `SEEN_ADVANCEMENTS` (0x19). The client degrades gracefully when it receives no response.
|
||||
- **Remap sound IDs**: 1.12 added 33 parrot sounds, 7 illager sounds, and smaller groups of end-portal and block-note sounds. IDs above each insertion point must be shifted down when forwarding to 1.11 servers.
|
||||
- **Inject fake bed NBT**: 1.12 clients expect a bed block-entity (with `color` field) to accompany every bed block in chunk data; 1.11 servers do not send one. ViaVersion synthesises it from the palette.
|
||||
- **Item replacement**: Items 235-252 and 453 (coloured concrete variants, Knowledge Book) are unknown on 1.11 servers; replace with a safe item (e.g. stone).
|
||||
- **Locale truncation**: `CLIENT_INFORMATION` locale max length is 16 in 1.12 vs 7 in 1.11; truncate to 7 before forwarding.
|
||||
|
||||
### What a proxy must do for 1.12.1 clients connecting to 1.12 servers
|
||||
|
||||
- **Drop `PLACE_RECIPE` (0x12 SB)** — 1.12 servers do not understand it.
|
||||
- **Do not forward `PLACE_GHOST_RECIPE` (0x2B CB)** from 1.12 server to 1.12.1 client — this packet does not exist in 1.12; no action needed on that direction (1.12 server simply never sends it).
|
||||
|
||||
### What a proxy must do for 1.12.2 clients connecting to 1.12.1 servers
|
||||
|
||||
- **Translate Keep Alive ID width** in both directions: `LONG` (i64) ↔ `VAR_INT` on the server side. A 64-bit keep-alive ID from the server must be masked or truncated to VarInt range (max 5 bytes, effectively 28 usable bits) when forwarding to a 1.12.1 server; a VarInt from a 1.12.1 server must be zero-extended to i64 when forwarding to a 1.12.2 client. `Protocol1_12_1To1_12_2.java` does this with `map(Types.VAR_INT, Types.LONG)` (CB) and `map(Types.LONG, Types.VAR_INT)` (SB).
|
||||
|
||||
### Connecting ≥1.13 clients to 1.12.2 servers
|
||||
|
||||
The reverse direction (`v1_12_2to1_13` package) is the large one. 1.13 renamed every block, item, entity, and sound to namespaced strings; abolished numeric IDs for most registries; and overhauled chunk encoding. That is covered in `versions/1.13.md`.
|
||||
Reference in New Issue
Block a user