Files
minecraft_protocol/versions/1.13.md
T
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

249 lines
25 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.
# 1.13.x — Update Aquatic / **The Flattening**
**Protocols:** 393 (1.13), 401 (1.13.1), 404 (1.13.2)
**Release dates:** 1.13 — 2018-07-18 · 1.13.1 — 2018-08-22 · 1.13.2 — 2018-10-22
**Minecraft wiki release articles:**
- <https://minecraft.wiki/w/Java_Edition_1.13> (fetched 2026-06-19) — release date 2018-07-18, protocol 393, data version 1519, data/resource pack format 4
- <https://minecraft.wiki/w/Java_Edition_1.13.1> (fetched 2026-06-19) — release date 2018-08-22, protocol 401
- <https://minecraft.wiki/w/Java_Edition_1.13.2> (fetched 2026-06-19) — release date 2018-10-22, protocol 404
**Protocol version numbers confirmed:** `ProtocolVersion.java` lines 60-62 — `register(393, "1.13")`, `register(401, "1.13.1")`, `register(404, "1.13.2")``/tmp/mcproto-refs/ViaVersion/api/src/main/java/com/viaversion/viaversion/api/protocol/version/ProtocolVersion.java`; cross-checked against `/tmp/mcproto-refs/minecraft-data/data/pc/1.13/version.json` (393), `1.13.1/version.json` (401), `1.13.2/version.json` (404); confirmed on <https://minecraft.wiki/w/Protocol_version> (fetched 2026-06-19).
**ViaVersion packages:**
- `v1_12_2to1_13``/tmp/mcproto-refs/ViaVersion/common/src/main/java/com/viaversion/viaversion/protocols/v1_12_2to1_13/`
- `v1_13to1_13_1``…/protocols/v1_13to1_13_1/`
- `v1_13_1to1_13_2``…/protocols/v1_13_1to1_13_2/`
**minecraft-data sources:** `data/pc/1.12.2/`, `data/pc/1.13/`, `data/pc/1.13.1/`, `data/pc/1.13.2/``/tmp/mcproto-refs/minecraft-data/`
---
## Headline changes — The Flattening
1.13 ("Update Aquatic", 2018-07-18) is the most structurally invasive release of the modern protocol era, and not primarily because of the gameplay (oceans, conduits, trident, swimming). The protocol-shattering part is **The Flattening**: Mojang abolished the legacy `id:metadata` block encoding and the numeric-with-data item encoding that had been the wire format since Beta, replacing it with **flat block-state IDs** and **renumbered item IDs**, and made **namespaced string IDs** (`minecraft:stone`) the source of truth for blocks, items, entities, sounds, particles, biomes, enchantments, statistics and plugin channels.
Before 1.13, a block on the wire was a 12-bit block id plus a 4-bit metadata nibble (e.g. wool was id 35, colour in the data nibble). After 1.13 every distinct visual/logical state is its own integer in a single flat namespace — roughly **8000+ block states** — with no metadata channel at all. The `v1_12_2to1_13` mapping table that ViaVersion uses to translate them is sized for **8582** block-state keys (`blockconnections/ConnectionData.java:57`, `KEY_TO_ID = new Object2IntOpenHashMap<>(8582)`). Item numeric IDs were likewise renumbered into a new contiguous space (ViaVersion carries an explicit `1.12 → 1.13` item bi-mapping, `data/MappingData1_13.java:144-156`).
On top of the ID rewrite, 1.13 added four wire-level systems:
1. **Declare Commands / Brigadier** — server-driven command *tree* (graph of nodes) replaces the flat string-list tab-complete model. New clientbound `Declare Commands` packet; tab-complete request/response reworked to be transaction-based.
2. **Tags** — a new clientbound `Tags` packet broadcasting block/item/fluid tag groups (`#minecraft:logs`, `#minecraft:wool`, …), which commands and recipes reference by tag.
3. **Declare Recipes** — recipes moved server-side and are pushed to the client as a registry (replaces the recipe-book ID list approach of 1.12).
4. **Strict JSON chat + namespaced plugin channels** — chat components are now strict JSON, scoreboard objective/team text fields became chat components, and the legacy `MC|Brand`, `MC|StopSound`, `MC|TrList`, … plugin channels were renamed to namespaced `minecraft:*` channels.
Sources: <https://minecraft.wiki/w/Java_Edition_1.13> (fetched 2026-06-19, "added data packs", "added many commands and changed the format of existing commands"); ViaVersion `v1_12_2to1_13` (below). The dedicated wiki flattening sub-article (`/w/Java_Edition_1.13/flattening`) returned 404 on 2026-06-19. The **8582 block-state count is confirmed** from two independent sources: (1) `ConnectionData.java:57``KEY_TO_ID = new Object2IntOpenHashMap<>(8582)` (initial capacity equals exact element count); (2) `minecraft-data/data/pc/1.13/blocks.json``maxStateId` across all 593 blocks = **8581**, meaning block-state IDs run 08581, totalling exactly 8582 states. These two sources agree. No Mojang-canonical public figure is available (the wiki sub-article 404s); the count 8582 is grounded in ViaVersion and minecraft-data primary sources.
---
## Protocol changes vs 1.12.2 (393 vs 340), by state
Source: diff of `ClientboundPackets1_12_1`/`ServerboundPackets1_12_1` (used through 1.12.2) against `ClientboundPackets1_13`/`ServerboundPackets1_13``/tmp/mcproto-refs/ViaVersion/common/src/main/java/com/viaversion/viaversion/protocols/v1_12_2to1_13/packet/`; cross-confirmed by `minecraft-data` packet-name set diff (`data/pc/1.12.2` vs `data/pc/1.13`): **+6 clientbound, +10 serverbound** net-new play packets, **0 removed**.
minecraft-data diff output (play state):
- CB added: `declare_commands`, `tags`, `declare_recipes`, `nbt_query_response`, `face_player`, `stop_sound`
- SB added: `query_block_nbt`, `query_entity_nbt`, `edit_book`, `pick_item`, `name_item`, `select_trade`, `set_beacon_effect`, `update_command_block`, `update_command_block_minecart`, `update_structure_block`
(`stop_sound` was a real packet in 1.13; in 1.12.2 it was the `MC|StopSound` plugin-message, so it shows as "added" in the diff. Likewise several SB additions were previously `MC|...` plugin messages — see Plugin-channel migration below.)
### Handshake / Status / Login
- **Status:** unchanged on the wire, but the favicon string in the status JSON is now newline-sensitive; ViaVersion strips `\n` from `favicon` when downgrading a 1.13 status response (`Protocol1_12_2To1_13.java:182-198`).
- **Login:** 1.13 adds **Login Plugin Request (CB 0x04) / Login Plugin Response (SB 0x02)** — a login-state custom-query channel (this is the mechanism Velocity-modern forwarding later rides on). ViaVersion notes the new CB 0x04 (`Protocol1_12_2To1_13.java:201` comment) and `cancelServerbound(State.LOGIN, ServerboundLoginPackets.CUSTOM_QUERY_ANSWER.getId())` to drop the SB answer when bridging to a 1.12.2 server (`:536`).
### Play — clientbound, new packets (1.13 = protocol 393)
IDs are the `ClientboundPackets1_13` enum ordinals (`packet/ClientboundPackets1_13.java`):
| ID | Enum (ViaVersion) | minecraft-data | Purpose |
|---|---|---|---|
| `0x11` | `COMMANDS` | `declare_commands` | The Brigadier command graph (see Declare Commands below). |
| `0x1D` | `TAG_QUERY` | `nbt_query_response` | Response to a block/entity NBT query (debug "pick" / `data get`). |
| `0x31` | `PLAYER_LOOK_AT` | `face_player` | Server rotates the client to look at a point/entity. |
| `0x4C` | `STOP_SOUND` | `stop_sound` | Promoted from the old `MC|StopSound` plugin message to a real packet. |
| `0x54` | `UPDATE_RECIPES` | `declare_recipes` | Full recipe registry pushed to the client. |
| `0x55` | `UPDATE_TAGS` | `tags` | Block/item/fluid tag groups (see Tags below). |
The two terminal packets `UPDATE_RECIPES` (0x54) and `UPDATE_TAGS` (0x55) are the new high-ID additions; the Declare Commands packet `COMMANDS` slots in at 0x11, shifting every higher clientbound ID. Note `PLACE_GHOST_RECIPE` is at 0x2D in 1.13 (`ClientboundPackets1_13.java:69`).
Beyond the new packets, **many existing clientbound packets changed field types** because of the Flattening and strict-JSON chat — these don't change the packet *set* but are heavy translation work:
- `BLOCK_UPDATE`, `MULTI_BLOCK_CHANGE` (`CHUNK_BLOCKS_UPDATE`), `LEVEL_CHUNK`, `BLOCK_EVENT`, `EXPLODE` now carry **flat block-state IDs**, not id+data (`rewriter/WorldPacketRewriter1_13.java`).
- `SET_OBJECTIVE` (0x45) and `SET_PLAYER_TEAM` (0x47): objective value, team display name, prefix and suffix became **chat components** (`Protocol1_12_2To1_13.java:399-468`, `ComponentUtil.legacyToJson(...)`). Team colour is now an explicit VarInt enum (`:441-452`).
- `MAP_ITEM_DATA` icons gained a type field and optional display-name component (`:351-371`).
- `AWARD_STATS` statistics are now category-id + registry-id pairs instead of dotted strings (`:204-247`).
### Play — serverbound, new packets (1.13 = protocol 393)
IDs are the `ServerboundPackets1_13` enum ordinals (`packet/ServerboundPackets1_13.java`):
| ID | Enum (ViaVersion) | minecraft-data | Was (1.12.2) |
|---|---|---|---|
| `0x01` | `BLOCK_ENTITY_TAG_QUERY` | `query_block_nbt` | new |
| `0x0B` | `EDIT_BOOK` | `edit_book` | was `MC|BEdit`/`MC|BSign` plugin msg |
| `0x0C` | `ENTITY_TAG_QUERY` | `query_entity_nbt` | new |
| `0x15` | `PICK_ITEM` | `pick_item` | was `MC|PickItem` plugin msg |
| `0x1C` | `RENAME_ITEM` | `name_item` | was `MC|ItemName` plugin msg |
| `0x1F` | `SELECT_TRADE` | `select_trade` | was `MC|TrSel` plugin msg |
| `0x20` | `SET_BEACON` | `set_beacon_effect` | was `MC|Beacon` plugin msg |
| `0x22` | `SET_COMMAND_BLOCK` | `update_command_block` | was `MC|AutoCmd` plugin msg |
| `0x23` | `SET_COMMAND_MINECART` | `update_command_block_minecart` | was `MC|AdvCmd` plugin msg |
| `0x25` | `SET_STRUCTURE_BLOCK` | `update_structure_block` | was `MC|Struct` plugin msg |
This is the other half of the plugin-channel migration: ten interactions that were `MC|*` custom-payload messages in 1.12.2 became **dedicated serverbound packets** in 1.13. ViaVersion downgrades each by repackaging it back into the matching legacy `MC|*` channel — e.g. `SET_BEACON → "MC|Beacon"` (`Protocol1_12_2To1_13.java:657-665`), `SET_STRUCTURE_BLOCK → "MC|Struct"` (`:704-762`), `EDIT_BOOK → "MC|BEdit"/"MC|BSign"` (`:577-586`). The two NBT-query packets (`BLOCK_ENTITY_TAG_QUERY` 0x01, `ENTITY_TAG_QUERY` 0x0C) have no 1.12.2 equivalent and are simply cancelled when downgrading (`:539`, `:589`).
### Data-format changes (no packet add/remove, but wire-breaking)
- **Block states:** `id<<4 | metadata` → flat state integer. ViaVersion's `WorldPacketRewriter1_13.toNewId(int)` is the central mapping call (`WorldPacketRewriter1_13.java:566-586`).
- **Item IDs:** renumbered; `1.12 → 1.13` item bi-mapping (`MappingData1_13.java:144-156`). Spawn eggs collapsed from one item (numeric 383) + entity-id NBT to **per-entity flat items** (`ItemPacketRewriter1_13.java:395-401`, `:491-493`).
- **Chat:** strict JSON everywhere; legacy `§`-coded strings in objective/team/score fields must be converted to JSON components (`ComponentUtil.legacyToJson`, used throughout `Protocol1_12_2To1_13.java`).
- **Plugin channels:** legacy `MC|Brand`, `MC|StopSound`, `MC|TrList`, `MC|Register`/`UNREGISTER` etc. → namespaced `minecraft:*`; rename both directions with channel bi-map (`ItemPacketRewriter1_13.java:99-169`, `:199-229`; `MappingData1_13.java:84-95` loads `channelmappings-1.13.json`).
- **Particles:** numeric particle IDs renumbered, several merged/split; `ParticleIdMappings1_13.rewriteParticle` (`WorldPacketRewriter1_13.java:471-537`).
- **Biomes:** invalid biome ids now crash the 1.13 client, so ViaVersion clamps anything outside the valid set to plains (`WorldPacketRewriter1_13.java:56-76`, `:405-421`).
- **Sounds:** named-sound registry renamed/renumbered (`NamedSoundMappings1_13`, used at `WorldPacketRewriter1_13.java:317-327`).
---
## Declare Commands / Brigadier (the command tree)
Before 1.13 the client had no command model: it sent a string to a *Tab-Complete* packet and the server returned a flat list of completion strings. 1.13 replaces that with a **command graph** pushed once via the `Declare Commands` (`COMMANDS`, CB 0x11) packet, and reworks tab-complete into a transaction-id request/response.
**Packet structure** (per <https://minecraft.wiki/w/Minecraft_Wiki:Projects/wiki.vg_merge/Command_Data>, fetched 2026-06-19):
| Field | Type | Notes |
|---|---|---|
| Count | VarInt | number of nodes in the array |
| Nodes | Node[] | the graph, flat array; edges are integer indices |
| Root index | VarInt | index of the (nameless) root node |
Each **Node**:
| Field | Type | Present when |
|---|---|---|
| Flags | Byte | always |
| Children count | VarInt | always |
| Children | VarInt[] | always (indices into the node array) |
| Redirect node | VarInt | `flags & 0x08` |
| Name | String | literal & argument nodes |
| Parser | (see note) | argument nodes only |
| Properties | parser-specific | argument nodes only |
| Suggestions type | Identifier | `flags & 0x10` |
**Flags byte:** `0x03` = node type (`0` root, `1` literal, `2` argument), `0x04` executable, `0x08` has-redirect, `0x10` has-suggestions-type, `0x20` restricted (permission-gated) — wiki, fetched 2026-06-19.
> **Version-aware note on the Parser field.** The merged wiki page describes the *modern* format where the parser is a **VarInt parser-id**. In **1.13 specifically the parser is an Identifier (String)** such as `brigadier:string`, and the suggestions type is a String. This is confirmed by ViaVersion writing the parser as `Types.STRING, "brigadier:string"` and the suggestion provider as `Types.STRING, "minecraft:ask_server"` in its synthetic command tree (`Protocol1_12_2To1_13.java:140`, `:142`). The VarInt parser-id form arrived in **1.19 (protocol 759)**, confirmed by `Protocol1_18_2To1_19.java` lines ~193201: the handler reads the argument type as `Types.STRING` (from the 1.18.2 server) then writes it as `Types.VAR_INT` (to the 1.19 client) — proving the 1.19 client already expects VarInt. The `registerDeclareCommands` (String format) method is used for protocols up through 1.18.2; `handle1_19` (VarInt format, `CommandRewriter.java` method `registerDeclareCommands1_19`) is used from 1.19 onward. Source: `CommandRewriter.java:80110` (String format) vs `CommandRewriter.java:111175` (`handle1_19` VarInt format); `Protocol1_18_2To1_19.java:179210`; `Protocol1_19_1To1_19_3.java:116` uses `handle1_19` on both old and new side, confirming the format was already VarInt in 1.19.
ViaVersion can't synthesise a real 1.12.2 server's command set as a tree, so when bridging a 1.13 client to a 1.12.2 server it sends a **minimal fake command graph** — a root node plus one greedy `brigadier:string` argument named `args` with suggestion provider `minecraft:ask_server` — so that tab-completion is delegated back to the server (`Protocol1_12_2To1_13.java:126-145`, `SEND_DECLARE_COMMANDS_AND_TAGS`). Tab-complete itself becomes transaction-based: the serverbound `COMMAND_SUGGESTION` carries a transaction id which ViaVersion tracks per-connection (`TabCompleteTracker`, `:542-575`), echoing it back on the clientbound `COMMAND_SUGGESTIONS` (`:250-281`).
```mermaid
flowchart TD
R["Root node (flags 0x00, nameless)"] -->|child| L["Literal 'msg'"]
R -->|child| L2["Literal 'me'"]
L --> A1["Argument 'target' (parser brigadier:entity)"]
A1 --> A2["Argument 'message' (parser brigadier:string, executable 0x04)"]
L2 --> A3["Argument 'action' (parser brigadier:string, executable 0x04)"]
A2 -.->|redirect 0x08| R
```
Mermaid is illustrative of the node/edge shape; the literal/argument names are examples, not a captured packet.
---
## Tags
1.13's `Tags` packet (`UPDATE_TAGS`, CB 0x55) ships **named groups of registry IDs** so the client can resolve `#minecraft:logs`, `#minecraft:wool`, fluid tags, etc. for command parsing and rendering. Wire layout (from ViaVersion's emitter, `Protocol1_12_2To1_13.java:148-167`):
| Field | Type | Notes |
|---|---|---|
| Block tag count | VarInt | |
| Block tags | (String name, VarInt[] ids)× | each tag = identifier + array of block IDs |
| Item tag count | VarInt | |
| Item tags | (String, VarInt[])× | |
| Fluid tag count | VarInt | |
| Fluid tags | (String, VarInt[])× | |
(1.13 has three tag registries — block, item, fluid. Entity-type tags were added in 1.14, and the packet later became a generic per-registry map.) ViaVersion loads the canonical 1.13 tag set from its mapping data (`MappingData1_13.loadExtras → loadTags`, `:62-64`) and emits the packet alongside the fake command graph in `SEND_DECLARE_COMMANDS_AND_TAGS` (`:147-173`). For 1.20.5+ clients it sends tags in the configuration phase rather than play, because registry data may depend on them (`:168-172`).
---
## Per-patch sub-sections
### 1.13 — protocol 393 (2018-07-18)
The Flattening release; everything above. **ViaVersion package:** `v1_12_2to1_13` — by far the largest single translation package in the codebase (block-connections sub-package, world sub-package, item rewriter, component rewriter, block-entity providers, and an 8582-entry block-state map).
**Key commits** (`git log --oneline -- common/src/main/java/com/viaversion/viaversion/protocols/v1_12_2to1_13`):
- `e965e9713` — Package/class renames and moves (the package itself)
- `501f65e21` — Packet and entity type renames (Mojang-mapped names)
- `8f8f5e72c` — Default rewriter registrations across protocols
- `896c6accf` — Fix 1.13 recipe ingredient writing
- `7c80e37e3` — Rewrite item ids in 1.12.2->1.13 show_item hover events (#4671)
- `f612adbd0` — Rewrite player & display name in player info packet in 1.12.2->1.13 (#4550)
- `50084c112` — Send the tags packet in 1.12->1.13 before the play login packet (tracking fix)
- `33aecef7b` — Handle custom name in block entities in 1.12->1.13 (#4232)
- `80e90a440` — Fix flower pot block storage 1.12.2->1.13 memory leak (#4852)
- `cab919bfa` — Fix legacy skull rotation overflow in 1.12.2->1.13 (#4952)
### 1.13.1 — protocol 401 (2018-08-22)
**Net packet change: 0 added, 0 removed.** A bug-fix patch; the protocol number bumped but no packet was added or deleted. The wire-visible deltas ViaVersion handles in `Protocol1_13To1_13_1.java`:
1. **Command-suggestion slash handling.** 1.13.0 had MC-123806 (tab-completion only working on the final argument); the fix changed where the leading `/` sits. Serverbound `COMMAND_SUGGESTION`: strip a leading `/` for compatibility (`Protocol1_13To1_13_1.java:61-73`). Clientbound `COMMAND_SUGGESTIONS`: offset the start index by `+1` to account for the `/` (`:93-111`).
2. **Boss bar flags fix (MC-123880).** 1.13.0 reused the same byte bit for two different booleans in the Boss Bar packet; 1.13.1 split them. ViaVersion's `BOSS_EVENT` handler propagates bit `0x02` into bit `0x04` when downgrading (`:113-131`).
3. **Edit Book off-hand fix (MC-84005).** `EDIT_BOOK` now carries a hand VarInt; ViaVersion cancels the packet when `hand == 1` (off-hand) since 1.13.0 servers don't expect it (`:75-91`).
4. Item-registry tag rewrite registered (`tagRewriter.register(... UPDATE_TAGS, RegistryType.ITEM)`, `:133`) — reflects minor item-tag additions in 1.13.1.
(Wiki notes the non-protocol changes too: `%=` scoreboard operator switched to `Math.floorMod`, function error line numbers start at 1 — <https://minecraft.wiki/w/Java_Edition_1.13.1>, fetched 2026-06-19.)
**ViaVersion package:** `v1_13to1_13_1` (note its `MappingDataBase("1.13", "1.13.2")` — it shares mapping data with the 1.13.2 step, `Protocol1_13To1_13_1.java:44`).
**Key commits** (`git log -- …/v1_13to1_13_1`): `e965e9713` (package creation), `501f65e21` (packet/entity renames), `c13b40a37` (Add ParticleRewriter base), `bb48dc90f` (registerBlockStateHandler).
### 1.13.2 — protocol 404 (2018-10-22)
**Net packet change: 0 added, 0 removed. One data-format change: the Slot format.** This is the only wire-visible change, and it is a clean before/after:
| | 1.13 / 1.13.1 (`ItemType1_13`) | 1.13.2 (`ItemType1_13_2`) |
|---|---|---|
| Empty marker | `Short id = -1` | `Boolean present = false` |
| Item id | `Short` | `VarInt` |
| Then | Byte count, NBT | Byte count, NBT |
So 1.13.2 (a) replaced the "id = 1 means empty" sentinel with an explicit leading **present boolean**, and (b) widened the item id from a **Short to a VarInt**. Confirmed by the two type classes: `ItemType1_13.read` reads `short id; if (id < 0) return null` (`api/.../type/types/item/ItemType1_13.java:38-46`) vs `ItemType1_13_2.read` reads `boolean present; if (!present) return null; … VAR_INT id` (`api/.../type/types/item/ItemType1_13_2.java:38-46`).
ViaVersion's `v1_13_1to1_13_2` package therefore does almost nothing except retype every Slot field on every item-bearing packet from `ITEM1_13 ↔ ITEM1_13_2`:
- `CONTAINER_SET_SLOT`, `CONTAINER_SET_CONTENT`, `SET_EQUIPPED_ITEM`, `UPDATE_RECIPES`, the `minecraft:trader_list` plugin payload — all `map(Types.ITEM1_13, Types.ITEM1_13_2)` clientbound (`rewriter/ItemPacketRewriter1_13_2.java:30-114`).
- `CONTAINER_CLICK`, `SET_CREATIVE_MODE_SLOT`, `EDIT_BOOK``map(Types.ITEM1_13_2, Types.ITEM1_13)` serverbound (`:116-133`; `Protocol1_13_1To1_13_2.java:42-47`).
- `UPDATE_ADVANCEMENTS` icon retyped `ITEM1_13 → ITEM1_13_2` (`Protocol1_13_1To1_13_2.java:49-79`).
- One area-effect-cloud item-particle fix (commit `ee16d7af2`).
**ViaVersion package:** `v1_13_1to1_13_2`.
**Key commits** (`git log -- …/v1_13_1to1_13_2`): `e965e9713` (package creation), `501f65e21` (renames), `ee16d7af2` (Fix two area effect cloud item particle issues), `5286efde1` (move type instances out of enclosing class).
---
## Proxy and translation impact
### Why `v1_12_2to1_13` is ViaVersion's largest translation class
The 1.12.2→1.13 step is the heaviest in ViaVersion for three compounding reasons, all stemming from the Flattening:
1. **The ~8000-entry block-state remap.** Every block on every chunk, block-update, multi-block-change, block-event and explode packet must be rewritten from legacy `id<<4|data` to a flat 1.13 state. The mapping table is sized for **8582** entries (`blockconnections/ConnectionData.java:57`). The chunk path rewrites every palette entry in every section via `toNewId` (`WorldPacketRewriter1_13.java:338-347`, `:566-586`).
2. **Block *connections* must be computed proxy-side.** Pre-1.13, the *appearance* of fences, walls, glass panes, stairs, redstone, doors, chests, tripwire, vines, chorus plants, fire, stems, etc. was derived client-side from neighbours; 1.13 bakes the connected variant into the block state, so a 1.13 client expects the server to have already chosen `oak_fence[north=true,east=true,...]`. A 1.12.2 server doesn't send that, so ViaVersion runs a full **server-side block-connection engine**: it stores chunk block data (`storage/BlockStorage.java`, `BlockConnectionStorage`), and on every chunk load / block change recomputes neighbour connections with **19 dedicated connection-handler classes** (`blockconnections/*ConnectionHandler.java` — Wall, Stair, Door, Chest, Fence, NetherFence, Glass, Pane, Redstone, Tripwire, Vine, ChorusPlant, Fire, Pumpkin, Melon, Snowy-grass, Flower, Stem, …). This is unique to this version step — no other ViaVersion package carries a world-geometry simulator. Gated behind `serverside-block-connections` config.
3. **Everything else got renumbered or restructured at once.** Item bi-map, spawn-egg split, particle remap, named-sound remap, biome clamp, statistics restructure, chat→JSON on scoreboard/team fields, plugin-channel namespacing in both directions, plus block-entity→block synthesis (note blocks and flower pots stopped being block-entities and became states, so ViaVersion deletes their NBT block-entities and bakes the state in, `WorldPacketRewriter1_13.java:423-452`). The package therefore needs sub-packages `blockconnections/`, `data/`, `provider/blockentities/`, `rewriter/`, `storage/`, `task/` — the only version step that needs all of them.
### What a proxy must do for a 1.13 client → 1.12.2 server
- **Translate every block state down** (flat → id+data) on all world packets, and **strip connection bits** that the old server never set.
- **Synthesise a fake Declare Commands graph + Tags packet** at join (so command UI and tag-referencing recipes don't break) — `SEND_DECLARE_COMMANDS_AND_TAGS`.
- **Repackage the 10 new serverbound packets** back into their legacy `MC|*` plugin messages; **cancel** the two NBT-query packets.
- **Down-convert chat JSON** on objective/team/score fields to legacy `§` strings; **rename plugin channels** `minecraft:*``MC|*`.
- **Map items down** (incl. spawn eggs, show_item hover events), **remap particles/sounds**, **clamp biomes** to avoid client crashes.
### Going the other way / between patches
- A 1.13.1 server vs 1.13.0 client (or vice-versa): only the command-suggestion `/` offset, boss-bar flag split, and edit-book hand need handling — trivial next to the 1.13 step.
- A 1.13.2 server vs 1.13/1.13.1 client: only the **Slot format** (`present` boolean + VarInt id ↔ Short-sentinel) needs retyping on item-bearing packets. A proxy that gets this wrong corrupts every inventory and creative action.
---
## Why this version matters as a baseline
1.13.2 (protocol 404) is the stable terminal of the Flattening line and a common multi-version proxy target: it is the last point before 1.14's further entity/tag/registry churn, and the first protocol where blocks, items, commands, tags and recipes all use the modern flat/namespaced model. Everything from 1.14 onward builds on the 1.13 data model rather than re-inventing it; the next equally-invasive jump is 1.20.2's Configuration state, not a data re-flattening.