# 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:** - (fetched 2026-06-19) — release date 2018-07-18, protocol 393, data version 1519, data/resource pack format 4 - (fetched 2026-06-19) — release date 2018-08-22, protocol 401 - (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 (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: (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 0–8581, 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 , 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 ~193–201: 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:80–110` (String format) vs `CommandRewriter.java:111–175` (`handle1_19` VarInt format); `Protocol1_18_2To1_19.java:179–210`; `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 — , 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.