# 1.8.x — The Bountiful Update **Protocol:** 47 **Versions:** 1.8 (2014-09-02) through 1.8.9 (2015-12-09) — all share the same protocol number **Minecraft wiki release article:** (fetched 2026-06-19) **minecraft-data sources:** `/tmp/mcproto-refs/minecraft-data/data/pc/1.8/protocol.json`, `version.json`; diff against `/tmp/mcproto-refs/minecraft-data/data/pc/1.7/protocol.json` **ViaVersion source:** `/tmp/mcproto-refs/ViaVersion/common/src/main/java/com/viaversion/viaversion/protocols/v1_8to1_9/packet/` — `ClientboundPackets1_8.java`, `ServerboundPackets1_8.java` **Protocol version confirmed:** `version.json` (`/tmp/mcproto-refs/minecraft-data/data/pc/1.8/version.json`) = `{"version":47,"minecraftVersion":"1.8.8","majorVersion":"1.8"}`; 1.7.10 = `{"version":5}`. --- ## Headline changes 1.8 ("The Bountiful Update") shipped 2014-09-02. On the wire it made three structural additions that defined the protocol for years: **Packet compression.** A new `Set Compression` packet was inserted into the login flow (login-state, clientbound 0x03). From that point forward, each packet carries a second VarInt (`Data Length`) between the existing `Packet Length` VarInt and the payload, enabling optional zlib deflate per-packet. This is the biggest framing change since the Netty rewrite in 1.7. See [§ Compression detail](#compression-in-detail) below. **Palette-based block and chunk encoding.** The `Map Chunk` (`0x21`) and `Multi Block Change` (`0x22`) packets switched from the 1.7 format (separate 8-bit block-ID + 4-bit metadata nibble-plane) to a single unified block-state integer. The `Multi Block Change` record went from a packed `{12-bit blockId, 4-bit metadata}` bitfield (separate words) to a single VarInt block-state ID per record. The `block_change` packet's payload similarly changed from `{type:varint, metadata:u8}` (two fields) to a single `{type:varint}` block-state ID. **New packed-integer Position type.** Block coordinates moved from three separate `i32`/`i16`/`i32` fields in a `position_iii`/`position_isi`/`position_ibi` struct to a single `i64` packed as `{x:26-bit signed, y:12-bit signed, z:26-bit signed}`. This is the `position` bitfield type that appears throughout the 1.8 protocol. **Why protocol 47 stayed so long.** 1.8 was the last major version for ~17 months (1.9 shipped 2016-02-29). Server operators preferred it for PvP because 1.9 introduced a weapon cooldown mechanic that most competitive networks rejected. Combined with Mojang's slow adoption of forced upgrades, protocol 47 remained the dominant live-traffic version until at least 2017 — the era that spawned the entire ViaVersion ecosystem. --- ## Compression in detail > Cross-reference: [../05-login-encryption.md](../05-login-encryption.md) covers the full login flow; this section focuses on the 1.8 addition. ### The Set Compression packet Sent by the server **during the login state**, after `Login Success` is in the pipeline but **before** it is actually sent: | State | Direction | ID | Name | Field | Type | |---|---|---|---|---|---| | login | clientbound | `0x03` | Set Compression | threshold | VarInt | Source: `minecraft-data/data/pc/1.8/protocol.json` login.toClient mappings `"0x03": "compress"` and `packet_compress` definition `[{"name":"threshold","type":"varint"}]`. The 1.7 login state had only three clientbound packets (`0x00` disconnect, `0x01` encryption_begin, `0x02` success). 1.8 added `0x03` compress. A negative `threshold` value disables compression. A value ≥ 0 means: packets whose uncompressed payload is ≥ `threshold` bytes **must** be zlib-compressed; smaller packets **may** be sent uncompressed (Data Length = 0). ### Framing change: the Data Length VarInt Before compression is enabled the packet format is identical to 1.7: ``` [Packet Length : VarInt] [Packet ID : VarInt] [Payload...] ``` After `Set Compression` is received, **all** subsequent packets (in both directions) add a second VarInt: ``` [Packet Length : VarInt] [Data Length : VarInt] [Packet ID + Payload : zlib or raw] ``` - `Packet Length` = byte-count of everything that follows, i.e. `len(Data Length varint) + len(compressed-or-raw-data)`. - `Data Length = 0` → the following bytes are **not** compressed (uncompressed payload was below threshold). - `Data Length > 0` → the following bytes are zlib-deflated; `Data Length` is the **uncompressed** byte count (used to size the decompression buffer). This second VarInt is invisible in the 1.7 framing; adding it is the entire framing change. The rest of the packet (ID + payload) is structurally unchanged — compression is a wrapper layer only. ### Login flow with compression (1.8) ```mermaid sequenceDiagram participant C as Client participant S as Server C->>S: Login Start (0x00) [username] S->>C: Encryption Request (0x01) [serverId, pubKey, verifyToken] C->>S: Encryption Response (0x02) [encSharedSecret, encVerifyToken] Note over C,S: AES/CFB8 encryption begins (both directions) S->>C: Set Compression (0x03) [threshold] — NEW in 1.8 Note over C,S: Framing switches to compressed format (both directions) S->>C: Login Success (0x02) [uuid, username] Note over C,S: Transition to PLAY state ``` Note: `Set Compression` is sent **encrypted** (after the AES stream is established) but **before** the state transitions to PLAY. The compression threshold is server-controlled; vanilla default is 256 bytes. --- ## Protocol changes vs 1.7 (from minecraft-data diff) The 1.7 and 1.8 protocol.json files share the same top-level packet names and IDs for nearly all play-state packets (0x00–0x40 clientbound, 0x00–0x17 serverbound). The protocol-breaking changes are in field types and the new packets. Key diffs: ### Handshake state Identical. Both: `0x00` set_protocol (`protocolVersion:varint, serverHost:string, serverPort:u16, nextState:varint`). ### Login state (clientbound) | ID | 1.7 packet | 1.8 change | |---|---|---| | 0x00 | disconnect | unchanged | | 0x01 | encryption_begin | **field type change**: `publicKey` and `verifyToken` lengths changed from `i16`-prefixed buffers (1.7) to `varint`-prefixed buffers (1.8) | | 0x02 | success | unchanged (`uuid:string, username:string`) | | 0x03 | — | **NEW**: `compress` (`threshold:varint`) | Source: compare `login.toClient` in both `protocol.json` files. In 1.7, `packet_encryption_begin` uses `{"countType":"i16"}` for both fields; in 1.8 they use `{"countType":"varint"}`. ### Login state (serverbound) Same change: 1.8 `encryption_begin` uses `varint`-prefixed `sharedSecret` and `verifyToken` buffers instead of `i16`-prefixed. ### Play state — new/changed clientbound packets | ID | Name | 1.7 → 1.8 change | |---|---|---| | 0x01 (login) | Login | **Added** `reducedDebugInfo:bool` field in 1.8 | | 0x02 (chat) | Chat | **Added** `position:i8` field in 1.8 (chat box=0, system=1, game info/action bar=2) | | 0x04 (entity_equipment) | Entity Equipment | Entity ID: `i32` → `varint` | | 0x05 (spawn_position) | Spawn Position | `location`: `position_iii` (3×i32) → packed `position` (single i64 bitfield) | | 0x06 (update_health) | Update Health | `food`: `i16` → `varint` | | 0x0a (bed) | Use Bed | Entity ID `i32` → `varint`; `location`: `position_ibi` → packed `position` | | 0x0c (named_entity_spawn) | Named Entity Spawn | **Major**: removed inline `playerName:string` and `data[]` properties array (1.7 sent these inline); added `playerUUID:UUID` binary type; removed `currentItem` field; 1.7 had string UUID + full profile inline | | 0x0d (collect) | Collect | Both entity IDs `i32` → `varint` | | 0x0e (spawn_entity) | Spawn Entity | `objectData` refactored: was inline `{intField:i32, velocityX/Y/Z:i16-conditional}`; same semantics, slightly different schema | | 0x12 (entity_velocity) | Entity Velocity | Entity ID `i32` → `varint` | | 0x13 (entity_destroy) | Entity Destroy | Count prefix `i8`+entity `i32` array → `varint` count + `varint` array | | 0x14–0x19 (entity move/look/teleport) | Entity movement | Entity ID `i32` → `varint`; `onGround:bool` added to rel_entity_move, entity_look, entity_move_look, entity_teleport | | 0x1a (entity_status) | Entity Status | Entity ID unchanged (`i32`) | | 0x1c (entity_metadata) | Entity Metadata | Entity ID `i32` → `varint` | | 0x1d (entity_effect) | Entity Effect | `duration`: `i16` → `varint`; added `hideParticles:bool` | | 0x1e (remove_entity_effect) | Remove Entity Effect | Entity ID `i32` → `varint` | | 0x1f (experience) | Set Experience | `level` and `totalExperience`: `i16` → `varint` | | 0x20 (update_attributes) | Update Attributes | Modifier count prefix: `i16` → `varint` | | 0x21 (map_chunk) | Map Chunk | **Major**: removed `addBitMap:u16` and `compressedChunkData` (zlib-in-packet); replaced with raw `chunkData:ByteArray(varint-prefixed)`; blocks now use palette block-state IDs | | 0x22 (multi_block_change) | Multi Block Change | **Major**: record format changed from separate `{metadata+blockId bitfield, y:u8, x+z bitfield}` to `{horizontalPos:u8, y:u8, blockId:varint}`; count now `varint`, removed `dataLength:i32` | | 0x23 (block_change) | Block Change | `location`: `position_ibi` → packed `position`; removed `metadata:u8` field — block-state ID in `type:varint` encodes both | | 0x24 (block_action) | Block Action | `location`: `position_isi` → packed `position` | | 0x25 (block_break_animation) | Block Break Animation | `location`: `position_iii` → packed `position` | | 0x26 (map_chunk_bulk) | Map Chunk Bulk | **Major**: removed per-chunk `addBitMap:u16`; removed `compressedChunkData` bulk buffer; switched to `skyLightSent:bool` + varint-prefixed meta array + raw data buffer | | 0x28 (world_event) | World Event | `location`: `position_ibi` → packed `position` | | 0x2a (world_particles) | World Particles | Switched from `particleName:string` to `particleId:i32`; added `longDistance:bool`; added extra `data[]` varint array for item/block particles | | 0x2c (spawn_entity_weather) | Spawn Weather Entity | Entity ID unchanged (`varint`) | | 0x2d (open_window) | Open Window | `inventoryType`: `u8` numeric → `string` identifier; removed `useProvidedTitle:bool` | | 0x33 (update_sign) | Update Sign | `location`: `position_isi` → packed `position` | | 0x34 (map) | Map Item Data | **Major reformat**: 1.7 had just `{itemDamage:varint, data:buffer(i16)}`; 1.8 expanded to `{itemDamage:varint, scale:i8, icons:[...], columns:i8, rows:i8, x:i8, y:i8, data:ByteArray}` | | 0x35 (tile_entity_data) | Tile Entity Data | `location`: `position_isi` → packed `position`; `nbtData`: `compressedNbt` → uncompressed `optionalNbt` | | 0x36 (open_sign_entity) | Open Sign Editor | `location`: `position_iii` → packed `position` | | 0x38 (player_info) | Player Info | **Major**: 1.7 was a flat `{playerName:string, online:bool, ping:i16}`; 1.8 became an action-based structure with `{action:varint, data:[{uuid:UUID, ...}]}` supporting add/remove/update-gamemode/update-latency/update-displayname actions | | 0x41 (difficulty) | Change Difficulty | **NEW** in 1.8 (absent from 1.7) | | 0x42 (combat_event) | Player Combat | **NEW** in 1.8 | | 0x43 (camera) | Set Camera | **NEW** in 1.8 | | 0x44 (world_border) | World Border | **NEW** in 1.8 | | 0x45 (title) | Title | **NEW** in 1.8 | | 0x46 (set_compression) | Set Compression | **NEW** in 1.8 (play-state duplicate; also exists in login state as 0x03) | | 0x47 (playerlist_header) | Tab List Header/Footer | **NEW** in 1.8 | | 0x48 (resource_pack_send) | Resource Pack | **NEW** in 1.8 | | 0x49 (update_entity_nbt) | Update Entity NBT | **NEW** in 1.8 | Source: packet maps in `minecraft-data/data/pc/1.8/protocol.json` play.toClient vs `data/pc/1.7/protocol.json` play.toClient. 1.7 clientbound play topped at `0x40` (kick_disconnect); 1.8 extends to `0x49`. ### Play state — changed serverbound packets | ID | Name | 1.7 → 1.8 change | |---|---|---| | 0x02 (use_entity) | Interact | `target:i32` → `varint`; `mouse:i8` → `varint`; added optional `{x,y,z}:f32` fields when `mouse=2` (interact-at) | | 0x04 (position) | Player Position | **Removed** `stance:f64` field (1.7 had x,stance,y,z; 1.8 has x,y,z) | | 0x06 (position_look) | Player Pos+Look | Same: removed `stance:f64` | | 0x07 (block_dig) | Player Action | `status:i8` → `varint`; `location`: `position_ibi` → packed `position` | | 0x08 (block_place) | Use Item On | `location`: `position_ibi` → packed `position` | | 0x0a (arm_animation) | Swing Arm | 1.7 had `{entityId:i32, animation:i8}`; 1.8 is empty (no fields) | | 0x0b (entity_action) | Player Command | `entityId:i32` → `varint`; `actionId:i8` → `varint`; `jumpBoost:i32` → `varint` | | 0x0c (steer_vehicle) | Player Input | `jump:bool+unmount:bool` → single `jump:u8` flags byte | | 0x12 (update_sign) | Sign Update | `location`: `position_isi` → packed `position` | | 0x14 (tab_complete) | Command Suggestion | Added optional `block:option` field | | 0x15 (settings) | Client Information | Removed `difficulty:u8` and `showCape:bool`; added `skinParts:u8` bitmask | | 0x18 (spectate) | Teleport To Entity | **NEW** in 1.8 | | 0x19 (resource_pack_receive) | Resource Pack Status | **NEW** in 1.8 | Source: `minecraft-data/data/pc/1.8/protocol.json` play.toServer vs `data/pc/1.7/protocol.json` play.toServer. 1.7 serverbound play topped at `0x17` (custom_payload); 1.8 extends to `0x19`. --- ## Entity metadata format Both 1.7 and 1.8 use the same sentinel-terminated metadata loop structure: - Each entry is a header byte with `{type:3 bits, key:5 bits}`. - End of stream signalled by byte `0x7F` (127). - Entry values by type: 0=i8, 1=i16, 2=i32, 3=f32, 4=string, 5=slot, 6={x:i32,y:i32,z:i32}, 7={pitch:f32,yaw:f32,roll:f32}. The type table is identical in both versions (verified from `entityMetadataItem` in both `protocol.json` files). However, the set of actual metadata indices and their meanings changed for several entity types in 1.8 to accommodate new entity properties (guardians, rabbits, armor stands). The container types `entityMetadata` and `entityMetadataItem` in 1.8's `protocol.json` are structurally identical to 1.7 — confirming that the metadata **encoding format** did not change between protocol 5 and 47; the changes were in which indices are used, not the framing. --- ## Chunk and block encoding ### 1.7 chunk format (for comparison) In 1.7, `Map Chunk` (`0x21`) contained: - `bitMap:u16` — which of the 16 vertical sections are present - `addBitMap:u16` — additional-data sections for blocks requiring >8 bits of block ID (extended blocks) - `compressedChunkData:buffer(i32-count)` — zlib-deflated payload containing raw nibble arrays: 8-bit block IDs + 4-bit metadata nibbles + 4-bit block light + optional 4-bit sky light + optional 4-bit add-data The 1.7 format encoded block type as `(blockID << 4) | metadata` using two separate nibble planes. ### 1.8 chunk format In 1.8, `Map Chunk` (`0x21`) contains: - `bitMap:u16` — which sections are present - `chunkData:ByteArray` (varint-prefixed) — raw uncompressed per-section data The per-section data layout in 1.8 encodes blocks as **block-state IDs** — a single integer combining what was previously `blockId` and `metadata`. Each section now stores: - 4096 block-state values as 16-bit entries (2 bytes per block, stored little-endian in a flat array of `4096 × 2` bytes) - 2048 bytes block light nibble array - 2048 bytes sky light nibble array (overworld only) The `addBitMap` field and the separate metadata nibble plane are gone entirely. Block state IDs are the canonical 1.8+ block representation: e.g., oak log facing north is a single integer distinct from oak log facing east, rather than `id=17, meta=4` vs `id=17, meta=0`. The `Multi Block Change` record format reflects this too: in 1.7, each record packed `{metadata:4bits, blockId:12bits}` in one i16 plus a separate `y:u8` and `{x:4bits,z:4bits}` nibble. In 1.8, each record is `{horizontalPos:u8, y:u8, blockId:varint}` where `blockId` is the full block-state ID. --- ## Packet inventory by state — 1.8 (protocol 47) Source: `minecraft-data/data/pc/1.8/protocol.json` packet mapper sections. ViaVersion `ClientboundPackets1_8.java` and `ServerboundPackets1_8.java` confirm the same IDs. ### Handshake (C→S) | ID | Name | |---|---| | 0x00 | Set Protocol (Handshake) | | 0xFE | Legacy Server List Ping | ### Status | ID | Direction | Name | |---|---|---| | 0x00 | S→C | Server Info (JSON response) | | 0x01 | S→C | Ping (i64 payload echo) | | 0x00 | C→S | Request (empty) | | 0x01 | C→S | Ping (i64 timestamp) | ### Login | ID | Direction | Name | |---|---|---| | 0x00 | S→C | Disconnect | | 0x01 | S→C | Encryption Request | | 0x02 | S→C | Login Success | | 0x03 | S→C | **Set Compression** ← new in 1.8 | | 0x00 | C→S | Login Start | | 0x01 | C→S | Encryption Response | ### Play — Clientbound (S→C) | ID | Name | |---|---| | 0x00 | Keep Alive | | 0x01 | Login (Join Game) | | 0x02 | Chat Message | | 0x03 | Time Update | | 0x04 | Entity Equipment | | 0x05 | Spawn Position | | 0x06 | Update Health | | 0x07 | Respawn | | 0x08 | Player Position and Look | | 0x09 | Held Item Change | | 0x0A | Use Bed | | 0x0B | Animation | | 0x0C | Spawn Named Entity | | 0x0D | Collect Item | | 0x0E | Spawn Object | | 0x0F | Spawn Mob | | 0x10 | Spawn Painting | | 0x11 | Spawn Experience Orb | | 0x12 | Entity Velocity | | 0x13 | Destroy Entities | | 0x14 | Entity (no-op move) | | 0x15 | Entity Relative Move | | 0x16 | Entity Look | | 0x17 | Entity Look and Relative Move | | 0x18 | Entity Teleport | | 0x19 | Entity Head Look | | 0x1A | Entity Status | | 0x1B | Attach Entity | | 0x1C | Entity Metadata | | 0x1D | Entity Effect | | 0x1E | Remove Entity Effect | | 0x1F | Set Experience | | 0x20 | Entity Properties | | 0x21 | Chunk Data | | 0x22 | Multi Block Change | | 0x23 | Block Change | | 0x24 | Block Action | | 0x25 | Block Break Animation | | 0x26 | Map Chunk Bulk | | 0x27 | Explosion | | 0x28 | Effect | | 0x29 | Sound Effect | | 0x2A | Particle | | 0x2B | Change Game State | | 0x2C | Spawn Global Entity | | 0x2D | Open Window | | 0x2E | Close Window | | 0x2F | Set Slot | | 0x30 | Window Items | | 0x31 | Window Property | | 0x32 | Confirm Transaction | | 0x33 | Update Sign | | 0x34 | Maps | | 0x35 | Update Block Entity | | 0x36 | Open Sign Editor | | 0x37 | Statistics | | 0x38 | Player List Item | | 0x39 | Player Abilities | | 0x3A | Tab-Complete | | 0x3B | Scoreboard Objective | | 0x3C | Update Score | | 0x3D | Display Scoreboard | | 0x3E | Teams | | 0x3F | Plugin Message | | 0x40 | Disconnect | | 0x41 | Server Difficulty ← new in 1.8 | | 0x42 | Combat Event ← new in 1.8 | | 0x43 | Camera ← new in 1.8 | | 0x44 | World Border ← new in 1.8 | | 0x45 | Title ← new in 1.8 | | 0x46 | Set Compression (play-state) ← new in 1.8 | | 0x47 | Player List Header and Footer ← new in 1.8 | | 0x48 | Resource Pack Send ← new in 1.8 | | 0x49 | Update Entity NBT ← new in 1.8 | ### Play — Serverbound (C→S) | ID | Name | |---|---| | 0x00 | Keep Alive | | 0x01 | Chat Message | | 0x02 | Use Entity | | 0x03 | Player (ground status only) | | 0x04 | Player Position | | 0x05 | Player Look | | 0x06 | Player Position and Look | | 0x07 | Player Digging | | 0x08 | Player Block Placement | | 0x09 | Held Item Change | | 0x0A | Animation (arm swing — empty payload in 1.8) | | 0x0B | Entity Action | | 0x0C | Steer Vehicle | | 0x0D | Close Window | | 0x0E | Click Window | | 0x0F | Confirm Transaction | | 0x10 | Creative Inventory Action | | 0x11 | Enchant Item | | 0x12 | Update Sign | | 0x13 | Player Abilities | | 0x14 | Tab-Complete | | 0x15 | Client Settings | | 0x16 | Client Status | | 0x17 | Plugin Message | | 0x18 | Spectate ← new in 1.8 | | 0x19 | Resource Pack Status ← new in 1.8 | --- ## Proxy and translation impact **ViaVersion floor.** Protocol 47 is ViaVersion's oldest natively supported client. There is no `v1_7to1_8` package in ViaVersion — 1.7 support requires ViaLegacy/ViaRewind. The `v1_8to1_9` package (`/tmp/mcproto-refs/ViaVersion/common/src/main/java/com/viaversion/viaversion/protocols/v1_8to1_9/`) is the FROM-1.8 direction and serves as the canonical definition of the 1.8 packet set. **Compression negotiation at the proxy.** A proxy operating in front of a 1.8+ server must intercept `Set Compression` (login 0x03) from the backend and decide whether to relay, modify, or suppress it. The compression threshold may differ between the proxy's own connection to the client and the proxy-to-server leg. BungeeCord and Velocity both intercept this packet and re-issue their own `Set Compression` to the client with their own threshold, then maintain separate compression state for each half of the connection. **Position type translation.** Any proxy accepting 1.7 clients and forwarding to a 1.8+ server must translate between the old triple-i32/i16 position types and the new packed `i64` `position` type for every block-coordinate field (spawn_position, bed, block_change, block_action, block_break_animation, update_sign, tile_entity_data, open_sign_entity, world_event, and on the serverbound side: block_dig, block_place, update_sign). **block_change metadata removal.** A 1.7-to-1.8 translator must combine the 1.7 `{type:varint, metadata:u8}` pair into a single 1.8 block-state VarInt on `block_change`, and split in the reverse direction. **Stance removal.** The 1.7 serverbound `position` packet had a `stance:f64` field (eye-height offset for collision) that was removed in 1.8. A proxy bridging 1.7→1.8 must strip this field; a 1.8→1.7 bridge must synthesise it (typically `y + 1.62`). **Player Info restructure.** The flat single-player `player_info` from 1.7 (`playerName, online, ping`) was replaced in 1.8 with the action-based multi-player structure. Proxies doing tab-list passthrough must understand the 1.8 structure. **New packets requiring proxy awareness.** `World Border` (0x44), `Title` (0x45), `Combat Event` (0x42), and `Set Compression` (0x46 in play-state) are all 1.8-new and unknown to 1.7 clients. A proxy connecting a 1.7 client to a 1.8 server must either translate or drop these; ViaLegacy/ViaRewind handle this for the compatibility layer. --- ## Sub-version notes (1.8.1 – 1.8.9) All 1.8.x patches share **protocol 47**. Patch releases addressed server-side exploits (combat, enchantment mechanics, item duplication), server crash vectors, and connectivity bugs but made **no wire-format changes**. A 1.8 client connects to a 1.8.9 server without negotiation issues, and vice versa. --- ## Sources summary | Claim | Source | |---|---| | Protocol 47; version 1.8.8 as representative | `/tmp/mcproto-refs/minecraft-data/data/pc/1.8/version.json` | | Release date 2014-09-02 | (fetched 2026-06-19) | | Login 0x03 `compress` packet field def | `/tmp/mcproto-refs/minecraft-data/data/pc/1.8/protocol.json` login.toClient | | 1.7 login had no 0x03 | `/tmp/mcproto-refs/minecraft-data/data/pc/1.7/protocol.json` login.toClient (0x00–0x02 only) | | Encryption buffer countType i16→varint | Both `protocol.json` files, `packet_encryption_begin` | | Play packet IDs 0x00–0x49 (1.8) | `/tmp/mcproto-refs/minecraft-data/data/pc/1.8/protocol.json` play.toClient mapper | | Play packet IDs 0x00–0x40 (1.7) | `/tmp/mcproto-refs/minecraft-data/data/pc/1.7/protocol.json` play.toClient mapper | | 1.8 clientbound packet enum with IDs | `/tmp/mcproto-refs/ViaVersion/…/v1_8to1_9/packet/ClientboundPackets1_8.java` | | 1.8 serverbound packet enum with IDs | `/tmp/mcproto-refs/ViaVersion/…/v1_8to1_9/packet/ServerboundPackets1_8.java` | | Compression framing (Data Length VarInt) | (fetched 2026-06-19) | | chunk_data addBitMap present in 1.7, absent in 1.8 | diff of `packet_map_chunk` in both `protocol.json` | | multi_block_change record format change | diff of `packet_multi_block_change` in both `protocol.json` | | `stance` field in 1.7 position, absent in 1.8 | `packet_position` in both `protocol.json` | | metadata loop structure identical 1.7 and 1.8 | `entityMetadata`/`entityMetadataItem` in both `protocol.json` |