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>
24 KiB
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.javalines 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:
- Declare Commands / Brigadier — server-driven command tree (graph of nodes) replaces the flat string-list tab-complete model. New clientbound
Declare Commandspacket; tab-complete request/response reworked to be transaction-based. - Tags — a new clientbound
Tagspacket broadcasting block/item/fluid tag groups (#minecraft:logs,#minecraft:wool, …), which commands and recipes reference by tag. - 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).
- 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 namespacedminecraft:*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 ~8000 block-state figure here is grounded in ViaVersion's 8582-entry map rather than the wiki.
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
\nfromfaviconwhen 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:201comment) andcancelServerbound(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 |
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,EXPLODEnow carry flat block-state IDs, not id+data (rewriter/WorldPacketRewriter1_13.java).SET_OBJECTIVE(0x45) andSET_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_DATAicons gained a type field and optional display-name component (:351-371).AWARD_STATSstatistics 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 |
0x0C |
ENTITY_TAG_QUERY |
query_entity_nbt |
new |
0x15 |
PICK_ITEM |
pick_item |
was `MC |
0x1C |
RENAME_ITEM |
name_item |
was `MC |
0x1F |
SELECT_TRADE |
select_trade |
was `MC |
0x20 |
SET_BEACON |
set_beacon_effect |
was `MC |
0x22 |
SET_COMMAND_BLOCK |
update_command_block |
was `MC |
0x23 |
SET_COMMAND_MINECART |
update_command_block_minecart |
was `MC |
0x25 |
SET_STRUCTURE_BLOCK |
update_structure_block |
was `MC |
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'sWorldPacketRewriter1_13.toNewId(int)is the central mapping call (WorldPacketRewriter1_13.java:566-586). - Item IDs: renumbered;
1.12 → 1.13item 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 throughoutProtocol1_12_2To1_13.java). - Plugin channels: legacy
MC|Brand,MC|StopSound,MC|TrList,MC|Register/UNREGISTERetc. → namespacedminecraft:*; rename both directions with channel bi-map (ItemPacketRewriter1_13.java:99-169,:199-229;MappingData1_13.java:84-95loadschannelmappings-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 atWorldPacketRewriter1_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 asTypes.STRING, "brigadier:string"and the suggestion provider asTypes.STRING, "minecraft:ask_server"in its synthetic command tree (Protocol1_12_2To1_13.java:140,:142). The VarInt parser-id form arrived later (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).
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 protocols896c6accf— Fix 1.13 recipe ingredient writing7c80e37e3— 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:
- 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. ServerboundCOMMAND_SUGGESTION: strip a leading/for compatibility (Protocol1_13To1_13_1.java:61-73). ClientboundCOMMAND_SUGGESTIONS: offset the start index by+1to account for the/(:93-111). - 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_EVENThandler propagates bit0x02into bit0x04when downgrading (:113-131). - Edit Book off-hand fix (MC-84005).
EDIT_BOOKnow carries a hand VarInt; ViaVersion cancels the packet whenhand == 1(off-hand) since 1.13.0 servers don't expect it (:75-91). - 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, theminecraft:trader_listplugin payload — allmap(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_ADVANCEMENTSicon retypedITEM1_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:
-
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|datato 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 viatoNewId(WorldPacketRewriter1_13.java:338-347,:566-586). -
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 behindserverside-block-connectionsconfig. -
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-packagesblockconnections/,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 channelsminecraft:*→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 (
presentboolean + 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.