Files
claude-timemachine a3d5f64ef5 verify pass: resolve VERIFY flags (corrections + citations + honest UNCONFIRMED)
Corrected real errors: several 1.7.x release dates, resource_pack_send version,
config packet ordering, structured-component count (56), PLAYER_LOADED (1.21.4),
entity_sound_effect field order. Confirmed+cited the rest; remaining ~19 items
re-marked UNCONFIRMED (third-party/ViaLegacy/26.2 internals unreachable from refs).

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

15 KiB
Raw Permalink Blame History

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), 1 (add), 2 (remove). When action = 0 the packet sends two arrays; for 1 or 2 it sends only recipes1. Confirmed from two sources: (a) minecraft-data/data/pc/1.12/protocol.json packet_unlock_recipesrecipes2 field uses "switch": {"compareTo": "action", "fields": {"0": [array]}, "default": "void"}, meaning it is present only when action = 0; (b) Protocol1_12_2To1_13.java line 384: for (int i = 0; i < (action == 0 ? 2 : 1); i++) — iterates twice for action 0, once otherwise. The labels "init/add/remove" for values 0/1/2 are the conventional wiki.vg names; ViaVersion treats actions 1 and 2 identically in translation (both produce one array), consistent with the distinction being server-side semantics only.

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 (20172020) 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.