Write biome palettes in the form the client actually reads
Vanilla's SECTION_BIOMES palette strategy switches on the bit count with
`tableswitch {0..3}`: 0 single-valued, 1-3 linear, and everything else falls
through to the global palette. There is no hashmap tier for biomes — that exists
only for block states, whose 0..8 switch we already implement correctly.
We were writing a linear palette all the way up to 7 bits. A section holding 9 or
more distinct biomes therefore went out as a 4-bit indirect container while the
client read it as global: no palette prefix consumed, long array re-read at 7
bits, and every field after it in the chunk payload misaligned. Sections that
straddle the surface and the cave biomes really do carry that many, so this is
reachable in ordinary terrain rather than a corner case.
Checked against the jar rather than recalled: javap -c on Strategy$2 shows the
{0..3} switch with Configuration$Global in the default arm.
The test decodes each container the way the client would and requires it to
consume exactly the bytes we produced, so a misframed container shows up as a
byte count instead of needing a client to notice. Restoring the old threshold
fails the 9-, 20- and 65-biome cases.
This commit is contained in:
parent
4453bdeb55
commit
c399070f59
2 changed files with 105 additions and 1 deletions
|
|
@ -63,6 +63,16 @@ const (
|
|||
biomeCellsXZ = 16 / biomeCellSize // 4
|
||||
biomeCellsPerSection = biomeCellsXZ * biomeCellsXZ * biomeCellsXZ // 64
|
||||
totalBiomes = 65 // synced minecraft:worldgen/biome registry size
|
||||
|
||||
// maxBiomeLinearBits is the widest indirect (linear) biome palette the client
|
||||
// will read. Vanilla's SECTION_BIOMES strategy switches on the bit count with
|
||||
// `tableswitch {0..3}`: 0 is single-valued, 1-3 are linear, and everything
|
||||
// else falls through to the global palette — there is no hashmap tier for
|
||||
// biomes, unlike block states. Writing a linear palette at 4+ bits makes the
|
||||
// client read the container as global: it consumes no palette prefix and
|
||||
// re-reads the long array at bitsFor(totalBiomes), so the rest of the chunk
|
||||
// payload is misaligned.
|
||||
maxBiomeLinearBits = 3
|
||||
)
|
||||
|
||||
// Chunk is a 16xWorldHeightx16 column of block states. Each section may carry a
|
||||
|
|
@ -412,7 +422,7 @@ func writeBiomePalette(w *protocol.Writer, s *[biomeCellsPerSection]uint16) {
|
|||
if bpe < 1 {
|
||||
bpe = 1 // minimum for the indirect biome format
|
||||
}
|
||||
if bpe > bitsFor(totalBiomes) {
|
||||
if bpe > maxBiomeLinearBits {
|
||||
writeBiomeDirect(w, s)
|
||||
return
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue