Files
minecraft_protocol/versions/1.17.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

300 lines
18 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.
# Java Edition 1.17 — Caves & Cliffs Part I
| Release | Protocol | Release Date | Data Version |
|---------|----------|--------------|--------------|
| 1.17 | 755 | 2021-06-08 | 2724 |
| 1.17.1 | 756 | 2021-07-06 | 2730 |
Sources: minecraft.wiki/w/Java_Edition_1.17 (fetched 2026-06-19); minecraft.wiki/w/Java_Edition_1.17.1 (fetched 2026-06-19); `ViaVersion/common/.../protocols/v1_16_4to1_17/` + `v1_17to1_17_1/`; `minecraft-data/data/pc/1.17/protocol.json`, `entities.json`, `loginPacket.json`; `minecraft-data/data/pc/1.17.1/protocol.json`.
---
## Headline Changes (Caves & Cliffs Part I)
1.17 was the first half of the Caves & Cliffs split — the world-height expansion (Y -64 to 320) shipped in 1.18; what 1.17 delivered was the **groundwork** for it. The dimension codec in LOGIN gained two new mandatory NBT fields (`min_y`, `height`) and the chunk/light formats were updated to support variable-height sections. Three new mobs were added (axolotl, glow squid, goat), shifting all existing entity type IDs. The most sweeping protocol-visible change was **packet explosion-splitting**: the single `SET_TITLES` packet (6 actions via a VarInt discriminant) was split into 6 independent packets; similarly `SET_BORDER` (6 actions) became 6 packets; `PLAYER_COMBAT` (3 actions) became 3 packets. The `CONTAINER_ACK` / `TRANSACTION` packet and the abstract `MOVE_ENTITY` parent were removed. A `PING` / `PONG` round-trip pair was added. Tags now carry a generic resource-location prefix, and a new `GAME_EVENT` tag type was introduced.
---
## Protocol Changes vs 1.16.4 (754 → 755)
### Play state — Clientbound (new / removed / restructured)
**Packet-split: SET_TITLES → 6 packets**
1.16 had a single `SET_TITLES` (0x4F) with a leading `VarInt` action discriminant (0=title, 1=subtitle, 2=actionbar, 3=animation, 4=clear, 5=reset). In 1.17 this became six independent packets:
| 1.17 ID | Name | Notes |
|---------|------|-------|
| 0x10 | `CLEAR_TITLES` | carries a `Boolean` reset-times field |
| 0x41 | `SET_ACTION_BAR_TEXT` | action-bar chat component |
| 0x5A | `SET_TITLES_ANIMATION` | fade-in / stay / fade-out ticks |
| 0x59 | `SET_TITLE_TEXT` | title component |
| 0x57 | `SET_SUBTITLE_TEXT` | subtitle component |
Sources: `v1_16_4to1_17/Protocol1_16_4To1_17.java:110134`; `v1_16_4to1_17/packet/ClientboundPackets1_17.java:88114`; minecraft-data `1.17/protocol.json` 0x10/0x41/0x57/0x59/0x5A.
**Packet-split: SET_BORDER → 6 packets**
1.16 had `SET_BORDER` (0x3D) with 6 action types. In 1.17 these became:
| 1.17 ID | Name |
|---------|------|
| 0x20 | `INITIALIZE_BORDER` |
| 0x42 | `SET_BORDER_CENTER` |
| 0x43 | `SET_BORDER_LERP_SIZE` |
| 0x44 | `SET_BORDER_SIZE` |
| 0x45 | `SET_BORDER_WARNING_DELAY` |
| 0x46 | `SET_BORDER_WARNING_DISTANCE` |
Sources: `v1_16_4to1_17/rewriter/WorldPacketRewriter1_17.java:4256`; `v1_16_4to1_17/packet/ClientboundPackets1_17.java:56/9096`.
**Packet-split: PLAYER_COMBAT → 3 packets**
1.16 had `PLAYER_COMBAT` (0x31) with action types 0=enter, 1=end, 2=kill. In 1.17:
| 1.17 ID | Name |
|---------|------|
| 0x33 | `PLAYER_COMBAT_END` |
| 0x34 | `PLAYER_COMBAT_ENTER` |
| 0x35 | `PLAYER_COMBAT_KILL` |
Sources: `v1_16_4to1_17/rewriter/EntityPacketRewriter1_17.java:148164`; `v1_16_4to1_17/packet/ClientboundPackets1_17.java:7577`.
**New packet: ADD_VIBRATION_SIGNAL (0x05)**
Sculk sensors (command-only in 1.17) transmit vibration signals via this new packet. Inserted at 0x05, shifting all former 0x05+ clientbound IDs up by one.
Sources: `v1_16_4to1_17/packet/ClientboundPackets1_17.java:29`; minecraft-data `1.17/protocol.json` 0x05 `sculk_vibration_signal`.
**New packet: PING (0x30)**
Added alongside the serverbound `PONG` (0x1D) to support a ping/pong round-trip independent of the `KEEP_ALIVE` flow. Sent as a single `Int` ID; client echoes it in `PONG`.
Sources: `v1_16_4to1_17/packet/ClientboundPackets1_17.java:72`; `v1_16_4to1_17/packet/ServerboundPackets1_17.java:53`.
**Removed: CONTAINER_ACK / TRANSACTION (0x11 in 1.16)**
The `TRANSACTION` (also known as `CONTAINER_ACK`) packet was removed. Servers no longer send transaction-confirmation packets for inventory clicks; the mechanism was replaced by a state ID approach in 1.17.1 (see §1.17.1 below).
Sources: `v1_16_4to1_17/Protocol1_16_4To1_17.java:2729` (commit `27033e929`); minecraft-data 1.16 has `0x12 transaction`, 1.17 does not.
**Removed: MOVE_ENTITY (0x2A in 1.16 → absent in 1.17)**
The parent abstract packet `MOVE_ENTITY` (0x2A, used as a no-op stand-in for the position-only move that was never actually used) was removed from the ID list. `MOVE_ENTITY_POS` (0x29), `MOVE_ENTITY_POS_ROT` (0x2A), and `MOVE_ENTITY_ROT` (0x2B) remain.
Sources: `v1_16_4to1_17/rewriter/EntityPacketRewriter1_17.java:167` ("The parent class of the other entity move packets that is never actually used has finally been removed from the id list"); VV comment `cancelClientbound(ClientboundPackets1_16_2.MOVE_ENTITY)`.
**Removed/renamed: REMOVE_ENTITIES → REMOVE_ENTITY (0x3A)**
In 1.16 `REMOVE_ENTITIES` (0x36) sent a `VarInt`-prefixed array of entity IDs in a single packet. In 1.17 this was replaced by `REMOVE_ENTITY` (0x3A) which carries a **single `VarInt` entity ID** per packet — one remove packet per entity.
Sources: `v1_16_4to1_17/rewriter/EntityPacketRewriter1_17.java:7386` (sends one `REMOVE_ENTITY` per ID from old array); `v1_16_4to1_17/packet/ClientboundPackets1_17.java:84`.
**Field changes: RESOURCE_PACK (0x3C)**
Two new fields added at the end: `Required` (Boolean) and `Prompt` (Optional Chat, nullable). ViaVersion injects these from config when downgrading.
Sources: `v1_16_4to1_17/Protocol1_16_4To1_17.java:8792`.
**Field changes: MAP_ITEM_DATA (0x27)**
`Tracking position` boolean removed. Marker array now encoded as optional (Boolean prefix then count if true) instead of a simple VarInt count.
Sources: `v1_16_4to1_17/Protocol1_16_4To1_17.java:94108`.
**Field changes: EXPLODE (0x1C)**
`Collection length` (count of blocks affected) changed from `Int` to `VarInt`.
Sources: `v1_16_4to1_17/Protocol1_16_4To1_17.java:136145`.
**Field changes: SET_DEFAULT_SPAWN_POSITION (0x4B)**
New `Angle` field (Float) added after the block position. Mojang initially forgot to write this to the buffer, so ViaVersion hard-codes `0f` when downgrading.
Sources: `v1_16_4to1_17/Protocol1_16_4To1_17.java:147153` (comment: "which Mojang just forgot to write to the buffer, lol").
**Field changes: UPDATE_ATTRIBUTES (0x63)**
Collection length changed from `Int` to `VarInt`.
Sources: `v1_16_4to1_17/rewriter/EntityPacketRewriter1_17.java:126132`.
**Field changes: PLAYER_POSITION (0x38)**
New `Dismount vehicle` Boolean field appended.
Sources: `v1_16_4to1_17/rewriter/EntityPacketRewriter1_17.java:134146`.
---
### Play state — Serverbound (new / removed)
| Change | 1.16 (0x__) | 1.17 (0x__) | Notes |
|--------|-------------|-------------|-------|
| Removed | TRANSACTION 0x07 | — | Client-side ACK for inventory transactions; removed with CONTAINER_ACK |
| Removed | CRAFTING_BOOK_DATA 0x1E | — | Collapsed into two packets below |
| Added | — | PONG 0x1D | Echo for server-sent PING |
| Added | — | RECIPE_BOOK 0x1E | Recipe book settings (replaces part of crafting_book_data) |
| Added | — | DISPLAYED_RECIPE 0x1F | "Display recipe" action (replaces part of crafting_book_data) |
Sources: minecraft-data `1.16/protocol.json` SB vs `1.17/protocol.json` SB; `v1_16_4to1_17/packet/ServerboundPackets1_17.java:53/58/59`.
**Field changes: CLIENT_INFORMATION (0x05)**
`Text filtering` Boolean field removed (client to server).
Sources: `v1_16_4to1_17/Protocol1_16_4To1_17.java:155166` (`read(Types.BOOLEAN)` — drops the field when translating down).
---
### Login (JOIN_GAME / LOGIN packet, 0x26 C→client)
The `LOGIN` packet gained two new top-level fields compared to 1.16:
- **`isHardcore`** (Boolean) — added as the second field after `Entity ID`. Absent in the 1.16 LOGIN packet (confirmed: `minecraft-data/data/pc/1.16/loginPacket.json` has no `isHardcore` key; `1.17/loginPacket.json` has it). ViaVersion maps it at `EntityPacketRewriter1_17.java:92`.
- **`Simulation Distance`** — added in 1.18, not 1.17. Confirmed: `minecraft-data/data/pc/1.17/loginPacket.json` lists `viewDistance` but has no `simulationDistance` field; `data/pc/1.18/loginPacket.json` adds it immediately after `viewDistance`. ViaVersion `EntityPacketRewriter1_18.java:57-58` injects it as a copy of `viewDistance` when a 1.17.1-era server does not supply it.
More significantly, the **dimension codec NBT** structure changed:
| Field | 1.16 | 1.17 |
|-------|------|------|
| Codec registry key | `"dimension"` (flat list) | `"minecraft:dimension_type"` (named registry) + `"minecraft:worldgen/biome"` |
| Dimension element `"name"` | present | removed |
| Dimension element `"shrunk"` | present | removed |
| Dimension element `"coordinate_scale"` | absent | added |
| Dimension element `"effects"` | absent | added (sky/fog rendering type) |
| Dimension element `"min_y"` | absent | added (always 0 in 1.17; expanded to -64 in 1.18) |
| Dimension element `"height"` | absent | added (always 256 in 1.17; expanded to 384 in 1.18) |
The **biome registry** (`minecraft:worldgen/biome`) is now part of the codec compound, transmitted inline in LOGIN. In 1.16 it was not present in the codec.
Sources: minecraft-data `1.17/loginPacket.json` vs `1.16/loginPacket.json` (deep diff, path `.dimensionCodec.value.*`); `v1_16_4to1_17/rewriter/EntityPacketRewriter1_17.java:196199` (`addNewDimensionData` adds `min_y=0`, `height=256`).
---
### Chunk format (LEVEL_CHUNK, 0x22)
1.17 eliminated partial-chunk ("non-full chunk") packets. All chunks are now sent as full chunks. The chunk section bitmask changed from a plain `Int` to a `BitSet` (serialized as `Long[]`). This is groundwork for the expanded world height in 1.18 — a BitSet can represent more than 16 sections.
ViaVersion: non-full chunks arriving from a 1.16 server are converted into `SECTION_BLOCKS_UPDATE` packets because the chunk payload cannot be retransmitted without full section data.
Sources: `v1_16_4to1_17/rewriter/WorldPacketRewriter1_17.java:102122` (chunk type switch `ChunkType1_16_2``ChunkType1_17`, BitSet mask).
---
### Light update format (LIGHT_UPDATE, 0x25)
Light section masks changed from `VarInt` bitmasks to `Long[]` BitSets (same direction as chunk masks). Each sky/block light mask is now serialized as a long array. Each light array is now preceded by its count (as a VarInt) before the byte arrays.
Sources: `v1_16_4to1_17/rewriter/WorldPacketRewriter1_17.java:5899` (converts VarInt bitmasks to `long[]` BitSets, writes count prefix for light array lists).
---
### Tags (UPDATE_TAGS, 0x66)
Tags are now **generically written with resource location keys**. In 1.16 the server sent 4 fixed tag types (block, item, fluid, entity) with no type identifier. In 1.17 each tag group is prefixed with its registry resource location (e.g. `"minecraft:block"`, `"minecraft:item"`, `"minecraft:fluid"`, `"minecraft:entity_type"`, `"minecraft:game_event"`), and the count of registry types is sent first as a VarInt. A fifth **Game Event** tag type (`minecraft:game_event`) was added.
Sources: `v1_16_4to1_17/Protocol1_16_4To1_17.java:6685`; `v1_16_4to1_17/Protocol1_16_4To1_17.java:181` (`addEmptyTags(RegistryType.GAME_EVENT, ...)`).
---
### Entity data (metadata)
**New index 7 — Ticks Frozen** added to the `ENTITY` base class (all entities). Index 7 is a new VarInt field representing how many ticks the entity has been in powder snow.
**Pose enum** gained a new value `LONG_JUMP` at index 6 (shifting `FALL_FLYING` from 6 to 7).
**Shulker** lost entity data index 17 (`Attachment position`, an optional BlockPos).
Sources: `v1_16_4to1_17/rewriter/EntityPacketRewriter1_17.java:171188`.
---
### Entity type IDs (ADD_ENTITY / ADD_MOB)
Five entities were added, inserted alphabetically, shifting most existing entity type IDs upward:
| Entity | New ID (1.17) | Notes |
|--------|---------------|-------|
| `axolotl` | 3 | New mob; inserted before `bat` (formerly 3) |
| `glow_item_frame` | 32 | New entity; subtype of item_frame |
| `glow_squid` | 33 | New mob; subtype of squid |
| `goat` | 34 | New mob |
| `marker` | 49 | New marker entity for command/datapack use |
All entities formerly with ID ≥ 3 shift; e.g. `bat` 3→4, `player` 106→111, `fishing_bobber` 107→112. Total entity types: 108 (1.16.2) → 113 (1.17).
Sources: minecraft-data `1.17/entities.json` vs `1.16.2/entities.json` (ID diff); `ViaVersion/api/.../entities/EntityTypes1_17.java:144/127/128/154/43`.
**Item frame rotation encoding change**
The `ADD_ENTITY` packet for item frames changed: 1.16 clients read rotation from the `data` field; 1.17 clients read it from `yaw`/`pitch`. ViaVersion sends a follow-up `MOVE_ENTITY_ROT` packet after `ADD_ENTITY` to supply the rotation when downgrading.
Sources: `v1_16_4to1_17/rewriter/EntityPacketRewriter1_17.java:4971`.
---
## 1.17.1 — Protocol 755 → 756 (2021-07-06)
1.17.1 was a small bug-fix release. Only a handful of protocol changes:
### REMOVE_ENTITY → REMOVE_ENTITIES (0x3A)
**Reverted.** 1.17 (755) changed the entity-remove packet from an array (1.16) to single-entity (1.17). 1.17.1 reverted this: the packet at 0x3A now carries a **`VarInt[]` array** of entity IDs again (same logical shape as 1.16's array, but with `VarInt` prefix length rather than `Int`).
This is reflected in the minecraft-data names: 1.17 has `destroy_entity` (0x3A), 1.17.1 has `entity_destroy` (0x3A). The ViaVersion translator converts the single-ID 1.17 server packet into the array wrapper for 1.17.1 clients.
Sources: `v1_17to1_17_1/Protocol1_17To1_17_1.java:4751` ("Aaaaand back to an array again!"); `v1_17to1_17_1/packet/ClientboundPackets1_17_1.java:82` (`REMOVE_ENTITIES`); minecraft-data `1.17/protocol.json` vs `1.17.1/protocol.json` (0x3A name diff).
### CONTAINER_SET_SLOT and CONTAINER_SET_CONTENT — State ID added
Both `CONTAINER_SET_SLOT` (0x16) and `CONTAINER_SET_CONTENT` (0x14) gained a new `State ID` field (`VarInt`). The client echoes this value in `CONTAINER_CLICK` to let the server detect desync.
- `CONTAINER_SET_SLOT`: state ID inserted between container ID and slot ID.
- `CONTAINER_SET_CONTENT`: state ID inserted after container ID; item array length encoding changed from `Short` to `VarInt`; a new `Carried item` field (the cursor item, `Slot`) was appended.
Sources: `v1_17to1_17_1/rewriter/ItemPacketRewriter1_17_1.java:4765` (writes `Types.VAR_INT, 0` as placeholder state ID); commit `ddbe8ef0f`.
### CONTAINER_CLICK — State ID consumed
Serverbound `CONTAINER_CLICK` (0x08) gained a `State ID` VarInt field (read and discarded by ViaVersion when forwarding to older servers).
Sources: `v1_17to1_17_1/rewriter/ItemPacketRewriter1_17_1.java:6783`.
### EDIT_BOOK — Format restructured
Serverbound `EDIT_BOOK` (0x0B) changed format: previously an item (writable book with NBT pages), now sends pages as a raw `VarInt` count + `String[]` list plus an optional `Boolean`-gated title. ViaVersion reconstructs the old NBT item format from the new wire format.
Sources: `v1_17to1_17_1/Protocol1_17To1_17_1.java:5395`; commit `ddbe8ef0f`.
### Enchantment level cap exposed
Items with enchantment levels outside [0, 255] were crashing 1.17 clients. 1.17.1 caps display. ViaVersion's downgrade handler hides out-of-range enchantments in lore when translating to older clients.
Sources: `v1_17to1_17_1/rewriter/ItemPacketRewriter1_17_1.java:88103`; commit `2c30a2748`.
---
## Proxy / Translation Impact
**For ViaVersion (older client → 1.17+ server):**
1. **Entity type ID remapping** — every `ADD_ENTITY`/`ADD_MOB` entity type ID must be remapped. Proxies must maintain a full 1.16↔1.17 entity type translation table. All IDs ≥ 3 shifted.
2. **Packet fan-out**`SET_TITLES`, `SET_BORDER`, `PLAYER_COMBAT` must be split from the old multiplexed format on downgrade (1.17 server → 1.16 client) or collapsed on upgrade.
3. **REMOVE_ENTITIES ↔ REMOVE_ENTITY** — single-ID vs array format must be translated in both directions. Additionally 1.17.1 reverted back to array, so the proxy must handle three forms across the 755→756 boundary.
4. **Dimension codec injection**`min_y` and `height` fields must be injected for 1.17-aware clients even when the server runs 1.16. ViaVersion injects `{min_y: 0, height: 256}` unconditionally.
5. **Chunk format** — 1.17 chunk type uses BitSet masks; a proxy bridging a 1.16 server must rewrite the chunk bitmask from `Int` to `Long[]` and vice versa. Non-full chunks from 1.16 servers must be converted to multi-block-change sequences.
6. **Light update** — mask encoding (VarInt → Long[] BitSet) must be translated.
7. **Tags** — the generic resource-location prefix and game-event registry type must be stripped/injected when bridging 1.16↔1.17.
8. **RESOURCE_PACK**`Required` + `Prompt` fields must be added (or stripped) at the boundary.
9. **Entity data index 7 (Ticks Frozen)** — must be injected (as 0) for all entities when serving 1.17 clients from a 1.16 source, and stripped in the other direction.
10. **State IDs (1.17.1)**`CONTAINER_SET_SLOT` / `CONTAINER_SET_CONTENT` / `CONTAINER_CLICK` all carry an extra VarInt state ID in 1.17.1 that must be stripped (downstream) or injected as 0 (upstream) when crossing the 755/756 boundary.
ViaVersion commit highlights for this boundary:
- `aa22ca1d5` — item-frame pitch/yaw→data rotation change
- `27033e929` — drop CONTAINER_ACK (transaction) tracking
- `501f65e21` — Mojang-mapped packet/entity type renames
- `ddbe8ef0f` — CONTAINER_SET_CONTENT/SLOT state IDs (1.17.1)
- `2c30a2748` — out-of-bounds enchantment lore display (1.17.1)