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>
15 KiB
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.javalines 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 0x17cancelServerbound(ServerboundPackets1_12.SEEN_ADVANCEMENTS)— drops 0x19- Locale truncation:
CLIENT_INFORMATIONmax locale length raised 7→16 in 1.12; ViaVersion truncates back to 7 when downgrading (line 131-134) - Bed chunk injection: injects fake
minecraft:bedNBT block-entity withcolor:14for 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;
getNewSoundIdremaps 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.
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.12a92e75b8c— Properly track minecart object entity types in ≤1.12.2e965e9713— 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.javalines 34-47: registers explicit mappings for both directions:map(Types.VAR_INT, Types.LONG)(CB) andmap(Types.LONG, Types.VAR_INT)(SB).minecraft-data/data/pc/1.12.2/protocol.json:packet_keep_aliveCB and SB both show{name: "keepAliveId", type: "i64"}, vs VarInt indata/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:
- 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.
- 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
colorfield) 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_INFORMATIONlocale 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_INTon 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.javadoes this withmap(Types.VAR_INT, Types.LONG)(CB) andmap(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.