minecraft_protocol: foundation + per-version protocol docs 1.7.10->26.2
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>
This commit is contained in:
@@ -0,0 +1,393 @@
|
||||
# Java Edition 1.18.x — Protocol Deep-Dive
|
||||
|
||||
| Release | Protocol # | Release date | minecraft-data dir | ViaVersion package (into this version) |
|
||||
|---|---|---|---|---|
|
||||
| 1.18 | **757** | 2021-11-30 | `data/pc/1.18` | `v1_17_1to1_18` |
|
||||
| 1.18.1 | **757** | 2021-12-10 | `data/pc/1.18.1` | *(same protocol; no VV package)* |
|
||||
| 1.18.2 | **758** | 2022-02-28 | `data/pc/1.18.2` | `v1_18to1_18_2` |
|
||||
|
||||
Protocol numbers confirmed from minecraft-data `version.json` for each dir (`1.18`→757, `1.18.1`→757, `1.18.2`→758) and ViaVersion source. **1.18 and 1.18.1 share protocol 757** — 1.18.1 was a critical security fix (Log4j RCE, fog) that did not touch the wire format. Release dates from minecraft.wiki release articles (fetched 2026-06-19): [1.18](https://minecraft.wiki/w/Java_Edition_1.18), [1.18.1](https://minecraft.wiki/w/Java_Edition_1.18.1), [1.18.2](https://minecraft.wiki/w/Java_Edition_1.18.2). ViaVersion source at `/tmp/mcproto-refs/ViaVersion/`.
|
||||
|
||||
---
|
||||
|
||||
## Headline — Caves & Cliffs Part II: world height expansion
|
||||
|
||||
1.18 ("**Caves & Cliffs Part II**", 2021-11-30) completed the biome and terrain overhaul begun in 1.17. The defining change is **world height expansion**: the overworld now spans **Y = −64 to Y = 319** (384 blocks total), up from 0–255 (256 blocks). This is not just a gameplay detail — it fundamentally restructures the chunk data packet:
|
||||
|
||||
- The chunk **now carries 24 sections** (384 ÷ 16) instead of 16.
|
||||
- **Biome data moved out of the flat array at chunk level** and into a **per-section paletted container** alongside block states, matching the per-section structure of block data. In 1.17 biomes were a flat `varint[]` at the top of the chunk packet; in 1.18 each section contains its own 4×4×4 biome palette.
|
||||
- The **Light Update and Chunk Data packets were merged** into a single `LEVEL_CHUNK_WITH_LIGHT` (0x22), collapsing what had been two separate packets into one.
|
||||
- The **section presence bitmask was removed**; all sections are always serialised, even if empty (filled with the single-value palette of air).
|
||||
|
||||
The actual *number* of packet types is nearly unchanged from 1.17.1 — one new packet (`SET_SIMULATION_DISTANCE`) and one merge (`LEVEL_CHUNK_WITH_LIGHT`) are the whole structural delta. The heavy cost is in the **chunk encoding / decoding work**, not in new protocol concepts.
|
||||
|
||||
Source: minecraft.wiki [Java Edition 1.18](https://minecraft.wiki/w/Java_Edition_1.18) (fetched 2026-06-19); ViaVersion `v1_17_1to1_18/`; minecraft-data `data/pc/1.17.1` vs `data/pc/1.18`.
|
||||
|
||||
---
|
||||
|
||||
## Protocol changes: 1.17.1 (756) → 1.18 (757)
|
||||
|
||||
### New packet: SET_SIMULATION_DISTANCE (0x57)
|
||||
|
||||
1.18 introduced a distinction between **view distance** (chunks loaded around the player) and **simulation distance** (chunks in which game logic runs). A new `SET_SIMULATION_DISTANCE` packet carries a single `varint distance` field.
|
||||
|
||||
minecraft-data confirms: `packet_simulation_distance` exists in `1.18` types but not in `1.17.1` — `data/pc/1.18/protocol.json` play toClient types. This insertion at 0x57 pushed all subsequent clientbound IDs up by one: the IDs from 0x57 onward in 1.18 are one higher than in 1.17.1.
|
||||
|
||||
```
|
||||
// SET_SIMULATION_DISTANCE (0x57, clientbound, Play)
|
||||
VarInt simulationDistance
|
||||
```
|
||||
|
||||
ViaVersion: `Protocol1_17_1To1_18.java` line 57–75 (serverbound `CLIENT_INFORMATION` handler) synthesises the simulation distance from view distance since the older client doesn't send it. `EntityPacketRewriter1_18.java` line 57–58 writes `simulationDistance` (duplicating the view-distance value) into the `LOGIN` packet.
|
||||
|
||||
Source: `v1_17_1to1_18/Protocol1_17_1To1_18.java:63-75`; `v1_17_1to1_18/rewriter/EntityPacketRewriter1_18.java:55-59`; minecraft-data `data/pc/1.18/protocol.json`.
|
||||
|
||||
### Serverbound CLIENT_INFORMATION: new field + rename
|
||||
|
||||
The `CLIENT_SETTINGS` serverbound packet gained one field and had one renamed:
|
||||
|
||||
| Field | 1.17.1 | 1.18 |
|
||||
|---|---|---|
|
||||
| locale (string) | ✓ | ✓ |
|
||||
| viewDistance (i8) | ✓ | ✓ |
|
||||
| chatFlags (varint) | ✓ | ✓ |
|
||||
| chatColors (bool) | ✓ | ✓ |
|
||||
| skinParts (u8) | ✓ | ✓ |
|
||||
| mainHand (varint) | ✓ | ✓ |
|
||||
| `disableTextFiltering` (bool) | ✓ (inverted name) | — |
|
||||
| `enableTextFiltering` (bool) | — | ✓ (renamed) |
|
||||
| `enableServerListing` (bool) | — | **added** |
|
||||
|
||||
Source: minecraft-data `data/pc/1.17.1/protocol.json` vs `data/pc/1.18/protocol.json` `packet_settings`; ViaVersion `Protocol1_17_1To1_18.java:63-75` strips `enableServerListing` when translating 1.18 clients toward a 1.17 server (the `read(Types.BOOLEAN)` at line 73 drops it).
|
||||
|
||||
### BLOCK_ENTITY_DATA: action field type change (u8 → varint)
|
||||
|
||||
The `BLOCK_ENTITY_DATA` clientbound packet changed its `action` field type from `unsigned byte` to `varint`:
|
||||
|
||||
```
|
||||
// BLOCK_ENTITY_DATA (0x0A, clientbound, Play) — 1.17.1
|
||||
BlockPos location
|
||||
u8 action // <-- byte
|
||||
OptNBT nbtData
|
||||
|
||||
// BLOCK_ENTITY_DATA (0x0A, clientbound, Play) — 1.18
|
||||
BlockPos location
|
||||
VarInt action // <-- varint
|
||||
OptNBT nbtData
|
||||
```
|
||||
|
||||
Source: minecraft-data `data/pc/1.17.1/protocol.json` vs `data/pc/1.18/protocol.json` `packet_tile_entity_data`; ViaVersion `WorldPacketRewriter1_18.java:56-64` reads the incoming 1.17.1 `UNSIGNED_BYTE` and writes `VAR_INT`.
|
||||
|
||||
### Chunk packet restructure: LEVEL_CHUNK_WITH_LIGHT (0x22)
|
||||
|
||||
This is the core change. In 1.17.1 there were two separate packets:
|
||||
|
||||
- `LEVEL_CHUNK` — chunk data (block states + biomes + block entities, no light)
|
||||
- `LIGHT_UPDATE` — light data for a chunk column (separate timing)
|
||||
|
||||
In 1.18 these are **merged** into `LEVEL_CHUNK_WITH_LIGHT` (0x22). The light data is appended directly after the chunk section data within the same packet. This is why ViaVersion must **buffer the LIGHT_UPDATE**, cache it keyed by (chunkX, chunkZ), then emit it when the corresponding `LEVEL_CHUNK` arrives (or vice versa — see `ChunkLightStorage`).
|
||||
|
||||
**Wire layout of `LEVEL_CHUNK_WITH_LIGHT` (1.18, 0x22):**
|
||||
|
||||
```
|
||||
Int chunkX
|
||||
Int chunkZ
|
||||
NBT heightMaps
|
||||
VarInt dataLength // byte count of the sections buffer
|
||||
[sections] <ySectionCount sections, each:>
|
||||
Short nonAirBlocksCount
|
||||
[blockPalette] paletted container (blocks)
|
||||
[biomePalette] paletted container (biomes) // NEW in 1.18
|
||||
VarInt blockEntityCount
|
||||
[blockEntities] <each: packed_xz (u8) + y (i16) + typeId (varint) + NBT>
|
||||
// Light data (was separate LIGHT_UPDATE in 1.17.1):
|
||||
Boolean trustEdges
|
||||
LongArray skyLightMask
|
||||
LongArray blockLightMask
|
||||
LongArray emptySkyLightMask
|
||||
LongArray emptyBlockLightMask
|
||||
VarInt skyLightArrayCount
|
||||
[byte[2048]] per section
|
||||
VarInt blockLightArrayCount
|
||||
[byte[2048]] per section
|
||||
```
|
||||
|
||||
Source: `ChunkType1_18.java:49-67` (read), `ChunkType1_18.java:71-86` (write); `ChunkSectionType1_18.java:51-54` (section read); `WorldPacketRewriter1_18.java:105-196`.
|
||||
|
||||
**Comparison with 1.17.1 LEVEL_CHUNK wire layout:**
|
||||
|
||||
```
|
||||
Int chunkX
|
||||
Int chunkZ
|
||||
LongArray sectionsMask // which of the 16 sections are present
|
||||
NBT heightMaps
|
||||
VarInt[] biomeData // flat array (1024 ints = 4×4×4 × 16 sections) -- GONE in 1.18
|
||||
VarInt dataLength
|
||||
[sections] only sections where bit set in mask:
|
||||
Short nonAirBlocksCount
|
||||
[blockPalette] paletted container (blocks only; no biome palette here)
|
||||
NBT[] blockEntities // full NBT per entity -- changed in 1.18
|
||||
```
|
||||
|
||||
Source: `ChunkType1_17.java:49-72` (read).
|
||||
|
||||
**Key structural differences:**
|
||||
|
||||
| Aspect | 1.17.1 (756) | 1.18 (757) |
|
||||
|---|---|---|
|
||||
| World height | Y 0–255, 16 sections | Y −64–319, 24 sections |
|
||||
| Section presence | bitmask (BitSet from LongArray) | **all sections always present** |
|
||||
| Biome data | flat `VarInt[]` of 1024 at chunk level | **per-section 4×4×4 paletted container** |
|
||||
| Block entities | full NBT array | packed `xz (u8) + y (i16) + typeId (varint) + NBT` |
|
||||
| Light | separate `LIGHT_UPDATE` packet | **merged into chunk packet** |
|
||||
| Section count | 16 (overworld) | **24 (overworld, +2 for border sections in light)** |
|
||||
|
||||
Source: `ChunkType1_17.java`, `ChunkType1_18.java`, `ChunkSectionType1_18.java`; ViaVersion `v1_17_1to1_18/`.
|
||||
|
||||
### Biome palette (per-section, 4×4×4)
|
||||
|
||||
In 1.18 each section in the chunk carries its own biome data as a **paletted container** using the same palette encoding as block states. The container covers a 4×4×4 sub-grid (64 biome cells per section), using the `PaletteType.BIOMES` type with `ChunkSection.BIOME_SIZE = 64`.
|
||||
|
||||
The palette format is identical to block palettes (`PaletteType1_18`):
|
||||
- **bits-per-value = 0** → single-value palette (one VarInt entry, zero-length data array) — used when an entire section is one biome
|
||||
- **1–3 bpv** → indirect palette (VarInt array of biome IDs + compact long array)
|
||||
- **direct/global** → compact long array, no palette array
|
||||
|
||||
The `highestBitsPerValue` for biomes is 3 in 1.18 (global palette otherwise). <!-- VERIFY: exact threshold for global biome palette bits in 1.18 -->
|
||||
|
||||
Source: `PaletteType1_18.java:38-171`; `ChunkSection.java:37` (`BIOME_SIZE = 4*4*4`); `PaletteType.java:27` (`BIOMES(ChunkSection.BIOME_SIZE, 3)`); `WorldPacketRewriter1_18.java:146-155` (ViaVersion filling biome palette from old flat array).
|
||||
|
||||
### World height in the dimension type NBT
|
||||
|
||||
The server communicates world height to clients via the **dimension type NBT** sent in the `LOGIN` and `RESPAWN` packets. The dimension type includes two fields:
|
||||
|
||||
- `height` (int) — total block height of the dimension
|
||||
- `min_y` (int) — minimum Y coordinate (negative for the expanded overworld: −64)
|
||||
|
||||
ViaVersion reads both to determine section count and minimum Y:
|
||||
|
||||
```java
|
||||
// EntityRewriter.java:512-526
|
||||
CompoundTag registryData = wrapper.get(Types.NAMED_COMPOUND_TAG, nbtIndex);
|
||||
NumberTag height = registryData.getNumberTag("height");
|
||||
// height >> 4 = section count (e.g. 384 >> 4 = 24)
|
||||
tracker.setCurrentWorldSectionHeight(blockHeight >> 4);
|
||||
NumberTag minY = registryData.getNumberTag("min_y");
|
||||
tracker.setCurrentMinY(minY.asInt()); // -64 for overworld
|
||||
```
|
||||
|
||||
The section count `tracker.currentWorldSectionHeight()` is then passed to `ChunkType1_17` / `ChunkType1_18` constructors at runtime so chunk reading is dimension-aware — not hardcoded to 24.
|
||||
|
||||
Source: `EntityRewriter.java:508-531`; `EntityPacketRewriter1_18.java:43-68` (LOGIN handler calling `worldDataTrackerHandler(1)`).
|
||||
|
||||
### Light update caching
|
||||
|
||||
Because 1.17.1 sends light and chunk data as separate packets, ViaVersion must buffer one while waiting for the other. The `ChunkLightStorage` per-connection object:
|
||||
|
||||
- On `LIGHT_UPDATE` for an **unloaded chunk**: cancels the packet (does not forward it) and caches the light data keyed by `(chunkX, chunkZ)`.
|
||||
- On `LIGHT_UPDATE` for an **already-loaded chunk**: passes through (and optionally caches, controlled by `cache-1_17-light` config).
|
||||
- On `LEVEL_CHUNK`: looks up the cached light, appends it to the merged `LEVEL_CHUNK_WITH_LIGHT`, then removes it from the cache.
|
||||
- On `FORGET_LEVEL_CHUNK`: clears both the cached light and the loaded-chunk marker.
|
||||
|
||||
Source: `ChunkLightStorage.java:28-68`; `WorldPacketRewriter1_18.java:66-103` (LIGHT_UPDATE handler), `105-196` (LEVEL_CHUNK → LEVEL_CHUNK_WITH_LIGHT).
|
||||
|
||||
### LOGIN packet: simulationDistance added
|
||||
|
||||
The `LOGIN` clientbound packet gained one field between 1.17.1 and 1.18:
|
||||
|
||||
```
|
||||
// 1.17.1 LOGIN (0x26) // 1.18 LOGIN (0x26)
|
||||
Int entityId Int entityId
|
||||
Bool isHardcore Bool isHardcore
|
||||
Byte gameMode Byte gameMode
|
||||
Byte previousGameMode Byte previousGameMode
|
||||
String[] worldNames String[] worldNames
|
||||
NBT dimensionCodec NBT dimensionCodec
|
||||
NBT dimension NBT dimension
|
||||
String worldName String worldName
|
||||
Long hashedSeed Long hashedSeed
|
||||
VarInt maxPlayers VarInt maxPlayers
|
||||
VarInt viewDistance VarInt viewDistance
|
||||
VarInt simulationDistance // NEW
|
||||
Bool reducedDebugInfo Bool reducedDebugInfo
|
||||
Bool enableRespawnScreen Bool enableRespawnScreen
|
||||
Bool isDebug Bool isDebug
|
||||
Bool isFlat Bool isFlat
|
||||
```
|
||||
|
||||
Source: minecraft-data `data/pc/1.17.1/protocol.json` vs `data/pc/1.18/protocol.json` `packet_login`; `EntityPacketRewriter1_18.java:43-68`.
|
||||
|
||||
### Particle: barrier (id 2) → block_marker (id 3)
|
||||
|
||||
A small entity-data / particle change: the `barrier` particle (ID 2 in 1.17) became the `block_marker` particle in 1.18 with an embedded block state, and what was `block_marker` (ID 3) got a different ID. ViaVersion maps these:
|
||||
|
||||
```java
|
||||
// EntityPacketRewriter1_18.java:86-92
|
||||
if (particle.id() == 2) { // Barrier
|
||||
particle.setId(3); // Block marker
|
||||
particle.add(Types.VAR_INT, 7754); // Barrier block state
|
||||
} else if (particle.id() == 3) { // Light block
|
||||
particle.add(Types.VAR_INT, 7786); // Light block state
|
||||
}
|
||||
```
|
||||
|
||||
Source: `v1_17_1to1_18/rewriter/EntityPacketRewriter1_18.java:85-93`.
|
||||
|
||||
### Tag renames
|
||||
|
||||
One block tag was renamed between 1.17 and 1.18:
|
||||
- `minecraft:lava_pool_stone_replaceables` → `minecraft:lava_pool_stone_cannot_replace`
|
||||
|
||||
Source: `Protocol1_17_1To1_18.java:82` (`tagRewriter.renameTag`).
|
||||
|
||||
---
|
||||
|
||||
## 757 — 1.18 (2021-11-30) and 1.18.1 (2021-12-10)
|
||||
|
||||
**1.18** shipped on 2021-11-30. It is the full Caves & Cliffs Part II release: expanded world height, noise caves, the new terrain generator, new mountain sub-biomes (Meadow, Grove, Snowy Slopes, Jagged Peaks, Frozen Peaks, Stony Peaks), and the 3D biome system decoupled from terrain generation. All protocol changes vs 1.17.1 are documented in the section above.
|
||||
|
||||
**1.18.1** shipped 2021-12-10, ten days later, as an emergency patch addressing:
|
||||
- Critical **Log4j2 RCE vulnerability** (CVE-2021-44228 / Log4Shell) exploitable via in-game chat messages logged by Log4j on the server side
|
||||
- Fog rendering change: fog now applies cylindrically (not spherically) and starts farther from the player
|
||||
- Eight bug fixes
|
||||
|
||||
**Protocol 757 is unchanged between 1.18 and 1.18.1.** The Log4j fix is entirely server-side (library update); no wire-format changes. There is no ViaVersion translation package between 1.18 and 1.18.1.
|
||||
|
||||
Source: minecraft.wiki [Java Edition 1.18.1](https://minecraft.wiki/w/Java_Edition_1.18.1) (fetched 2026-06-19); minecraft-data `data/pc/1.18.1/version.json` (`version: 757`).
|
||||
|
||||
---
|
||||
|
||||
## 758 — 1.18.2 (2022-02-28)
|
||||
|
||||
1.18.2 shipped 2022-02-28, bumping the protocol from 757 to **758**. The gameplay additions are modest (custom world-gen tag expansion, `/placefeature` command, new structure and biome tags), and the **protocol wire changes are minimal**:
|
||||
|
||||
### Effect ID type: byte → varint (UPDATE_MOB_EFFECT and REMOVE_MOB_EFFECT)
|
||||
|
||||
The only structural packet change from 1.18 to 1.18.2 is that the `effectId` field in two packets changed type from `byte` (i8) to `varint`:
|
||||
|
||||
**UPDATE_MOB_EFFECT (0x65 in 1.18):**
|
||||
```
|
||||
// 1.18 (757) // 1.18.2 (758)
|
||||
VarInt entityId VarInt entityId
|
||||
byte effectId // <-- i8 VarInt effectId // <-- varint
|
||||
byte amplifier byte amplifier
|
||||
VarInt duration VarInt duration
|
||||
byte hideParticles byte hideParticles
|
||||
```
|
||||
|
||||
**REMOVE_MOB_EFFECT (0x3B in 1.18):**
|
||||
```
|
||||
// 1.18 (757) // 1.18.2 (758)
|
||||
VarInt entityId VarInt entityId
|
||||
byte effectId // <-- i8 VarInt effectId // <-- varint
|
||||
```
|
||||
|
||||
ViaVersion maps both in `Protocol1_18To1_18_2.java`:
|
||||
```java
|
||||
// Protocol1_18To1_18_2.java:45-58
|
||||
registerClientbound(ClientboundPackets1_18.UPDATE_MOB_EFFECT, new PacketHandlers() {
|
||||
public void register() {
|
||||
map(Types.VAR_INT); // Entity id
|
||||
map(Types.BYTE, Types.VAR_INT); // Effect id byte→varint
|
||||
}
|
||||
});
|
||||
registerClientbound(ClientboundPackets1_18.REMOVE_MOB_EFFECT, new PacketHandlers() {
|
||||
public void register() {
|
||||
map(Types.VAR_INT); // Entity id
|
||||
map(Types.BYTE, Types.VAR_INT); // Effect id byte→varint
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Source: `v1_18to1_18_2/Protocol1_18To1_18_2.java:45-58`; minecraft-data `data/pc/1.18/protocol.json` vs `data/pc/1.18.2/protocol.json` `packet_entity_effect` + `packet_remove_entity_effect`.
|
||||
|
||||
### LOGIN / RESPAWN: `infiniburn` tag prefix added
|
||||
|
||||
Dimension type NBT now requires the `infiniburn` block tag to be prefixed with `#`:
|
||||
|
||||
```java
|
||||
// Protocol1_18To1_18_2.java:86-91
|
||||
private void addTagPrefix(CompoundTag tag) {
|
||||
final Tag infiniburnTag = tag.get("infiniburn");
|
||||
if (infiniburnTag instanceof final StringTag infiniburn) {
|
||||
infiniburn.setValue("#" + infiniburn.getValue());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This is applied to all dimension entries in the registry NBT (in `LOGIN`) and to the current dimension NBT in `RESPAWN`. The `#` prefix marks it as a tag reference rather than a direct block ID.
|
||||
|
||||
Source: `v1_18to1_18_2/Protocol1_18To1_18_2.java:61-91`.
|
||||
|
||||
### Tags: `fall_damage_resetting` block tag added
|
||||
|
||||
A new block tag `minecraft:fall_damage_resetting` is injected into `UPDATE_TAGS` with a fixed list of block IDs:
|
||||
|
||||
```java
|
||||
// Protocol1_18To1_18_2.java:42
|
||||
tagRewriter.addTagRaw(RegistryType.BLOCK, "minecraft:fall_damage_resetting",
|
||||
169, 257, 680, 713, 714, 715, 716, 859, 860, 696, 100);
|
||||
```
|
||||
|
||||
Source: `v1_18to1_18_2/Protocol1_18To1_18_2.java:41-43`.
|
||||
|
||||
### No packet additions or removals in 758
|
||||
|
||||
Minecraft-data confirms: the clientbound packet list in `data/pc/1.18/protocol.json` and `data/pc/1.18.2/protocol.json` are identical in packet names and IDs. The serverbound list is also unchanged. The protocol bump is driven by the effect-ID type change alone (plus the NBT / tag-data changes that don't alter packet structure).
|
||||
|
||||
---
|
||||
|
||||
## Proxy / translation impact
|
||||
|
||||
### What proxies must do for height-aware chunk translation
|
||||
|
||||
A proxy bridging 1.17.1 clients to a 1.18 server (or vice-versa) faces the most expensive chunk translation in the 1.17/1.18 era:
|
||||
|
||||
1. **Section count change**: must expand/shrink the section array from 16 to 24 (or back). For 1.17.1 clients receiving a 1.18 chunk, the 8 extra sections (Y = −64 to −1) are simply not representable — ViaVersion does not send those sections to old clients; they appear as void. <!-- VERIFY: exact ViaVersion handling of below-zero sections for 1.17.1 clients -->
|
||||
|
||||
2. **Biome re-encoding**: The 1.17.1 biome format is a flat `VarInt[]` of 1024 entries (4×4×4 per section × 16 sections). The 1.18 format is per-section paletted containers. ViaVersion's conversion:
|
||||
- Receiving a 1.17.1 chunk: reads the flat biome array, slices it into 16-entry groups (one per section × 64 biome cells), and creates a `DataPaletteImpl` per section — `WorldPacketRewriter1_18.java:146-155`.
|
||||
- The 8 extra sections for Y < 0 are padded with biome ID 0 (fallback for invalid/missing): `biome = biomeData[biomeArrayIndex]; biomePalette.setIdAt(biomeIndex, biome != -1 ? biome : 0)`.
|
||||
|
||||
3. **Light buffering**: Two packets become one. The proxy must buffer light packets until the corresponding chunk packet arrives (or vice-versa), then emit the merged `LEVEL_CHUNK_WITH_LIGHT`. ViaVersion's `ChunkLightStorage` implements this — `ChunkLightStorage.java:28-68`, `WorldPacketRewriter1_18.java:66-103`.
|
||||
|
||||
4. **Block entity format**: 1.17.1 sends block entities as raw NBT with `x`/`y`/`z`/`id` fields inside. 1.18 sends a packed struct: `packedXZ (u8) = (x & 15) << 4 | (z & 15)`, `y (i16)`, `typeId (varint)`. ViaVersion converts: `WorldPacketRewriter1_18.java:109-128`.
|
||||
|
||||
5. **Section presence bitmask**: In 1.17.1 null sections are skipped via bitmask; in 1.18 every section must be present in the serialised form (using single-value palette for air). ViaVersion fills null sections: `WorldPacketRewriter1_18.java:133-143`.
|
||||
|
||||
6. **`simulationDistance` injection**: When a 1.18 server sends `LOGIN`, ViaVersion injects a `simulationDistance` field (copied from `viewDistance`) for old 1.17.1 clients that don't know about it — `EntityPacketRewriter1_18.java:57-58`. In the reverse direction (serverbound), `CLIENT_INFORMATION` from a 1.17.1 client drops the `enableServerListing` bool that 1.18 expects — `Protocol1_17_1To1_18.java:63-74`.
|
||||
|
||||
Source: all paths above in `v1_17_1to1_18/`.
|
||||
|
||||
### 757 → 758 proxy impact (minimal)
|
||||
|
||||
For a proxy bridging protocol 757 to 758:
|
||||
- **Effect ID**: remap `effectId` in `UPDATE_MOB_EFFECT` and `REMOVE_MOB_EFFECT` between i8 and varint. Simple field-type swap, no data loss (effect IDs fit in a byte).
|
||||
- **NBT prefix**: add/strip `#` on the `infiniburn` string tag in `LOGIN` registry and `RESPAWN` dimension NBT.
|
||||
- **Tags**: inject or strip the `fall_damage_resetting` block tag.
|
||||
- No chunk re-encoding needed; chunk format is identical between 757 and 758.
|
||||
|
||||
Source: `v1_18to1_18_2/Protocol1_18To1_18_2.java:39-91`.
|
||||
|
||||
---
|
||||
|
||||
## ViaVersion git log summary
|
||||
|
||||
```
|
||||
# v1_17_1to1_18 package (selected):
|
||||
e15fc5953 Trim slightly more fastutil, use its interfaces for the long collections
|
||||
8ee5d7e68 Add missing biome name translations in 1.17.1->1.18 (#4597)
|
||||
12c773ede Add missing translatable mappings (#4542)
|
||||
b8a170873 Add more info to missing light data warning
|
||||
c13b40a37 Add ParticleRewriter base (#4203)
|
||||
bd4df2813 Refactor protocols to match template module (#3842)
|
||||
5286efde1 Move type instances out of its enclosing class
|
||||
|
||||
# v1_18to1_18_2 package (selected):
|
||||
cff9a8715 [ci skip] Update copyright header
|
||||
91f31b578 Clean up tags rewriting (#3856)
|
||||
501f65e21 Packet and entity type renames
|
||||
e965e9713 Package/class renames and moves
|
||||
```
|
||||
|
||||
Source: `git -C /tmp/mcproto-refs/ViaVersion log --oneline -- common/.../v1_17_1to1_18/` and `common/.../v1_18to1_18_2/`, each `| head -20`.
|
||||
Reference in New Issue
Block a user