From e744214ad612f71ff6a3c943bd73716906dd74d0 Mon Sep 17 00:00:00 2001 From: Nassim Jahnke Date: Fri, 8 Oct 2021 12:52:53 +0200 Subject: [PATCH] Fix biome palette writing Co-authored-by: Gerrygames --- .../api/minecraft/chunks/ChunkSection.java | 5 ++++ .../minecraft/chunks/ChunkSectionImpl.java | 4 +-- .../api/minecraft/chunks/DataPalette.java | 30 ++++++++++++------- .../api/minecraft/chunks/DataPaletteImpl.java | 18 ++++++----- .../api/minecraft/chunks/PaletteType.java | 12 ++++---- .../type/types/version/PaletteType1_18.java | 12 ++++---- .../packets/WorldPackets.java | 21 ++++--------- 7 files changed, 56 insertions(+), 46 deletions(-) diff --git a/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/ChunkSection.java b/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/ChunkSection.java index 04509c22d..cc9a787f7 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/ChunkSection.java +++ b/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/ChunkSection.java @@ -31,6 +31,11 @@ public interface ChunkSection { */ int SIZE = 16 * 16 * 16; // width * depth * height + /** + * Size (dimensions) of biomes in a chunks section. + */ + int BIOME_SIZE = 4 * 4 * 4; + static int index(int x, int y, int z) { return y << 8 | z << 4 | x; } diff --git a/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/ChunkSectionImpl.java b/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/ChunkSectionImpl.java index d091fe71d..b1f41c3c0 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/ChunkSectionImpl.java +++ b/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/ChunkSectionImpl.java @@ -36,14 +36,14 @@ public class ChunkSectionImpl implements ChunkSection { } public ChunkSectionImpl(final boolean holdsLight) { - addPalette(PaletteType.BLOCKS, new DataPaletteImpl()); + addPalette(PaletteType.BLOCKS, new DataPaletteImpl(ChunkSection.SIZE)); if (holdsLight) { this.light = new ChunkSectionLightImpl(); } } public ChunkSectionImpl(final boolean holdsLight, final int expectedPaletteLength) { - addPalette(PaletteType.BLOCKS, new DataPaletteImpl(expectedPaletteLength)); + addPalette(PaletteType.BLOCKS, new DataPaletteImpl(ChunkSection.SIZE, expectedPaletteLength)); if (holdsLight) { this.light = new ChunkSectionLightImpl(); } diff --git a/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/DataPalette.java b/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/DataPalette.java index 730981cb3..657afa8bd 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/DataPalette.java +++ b/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/DataPalette.java @@ -24,11 +24,21 @@ package com.viaversion.viaversion.api.minecraft.chunks; public interface DataPalette { + /** + * Returns the packet section index of the given coordinates. + * + * @param x x + * @param y y + * @param z z + * @return packed section index of the given coordinates + */ + int index(final int x, final int y, final int z); + /** * Returns the value of the given chunk coordinate. * - * @param sectionCoordinate block index within the section - * @return block state of the given index + * @param sectionCoordinate section index within the section + * @return section state of the given index */ int idAt(int sectionCoordinate); @@ -38,17 +48,17 @@ public interface DataPalette { * @param sectionX section x * @param sectionY section y * @param sectionZ section z - * @return block state of the given section coordinate + * @return id of the given section coordinate */ default int idAt(final int sectionX, final int sectionY, final int sectionZ) { - return idAt(ChunkSection.index(sectionX, sectionY, sectionZ)); + return idAt(index(sectionX, sectionY, sectionZ)); } /** * Set a value in the chunk section. * This method does not update non-air blocks count. * - * @param sectionCoordinate block index within the section + * @param sectionCoordinate section index within the section * @param id id value */ void setIdAt(int sectionCoordinate, int id); @@ -63,7 +73,7 @@ public interface DataPalette { * @param id id value */ default void setIdAt(final int sectionX, final int sectionY, final int sectionZ, final int id) { - setIdAt(ChunkSection.index(sectionX, sectionY, sectionZ), id); + setIdAt(index(sectionX, sectionY, sectionZ), id); } /** @@ -83,17 +93,17 @@ public interface DataPalette { void setIdByIndex(int index, int id); /** - * Returns the palette index of the given block index. + * Returns the palette index of the given section index. * - * @param packedCoordinate block index - * @return palette index of the given block index + * @param packedCoordinate section index + * @return palette index of the given section index */ int paletteIndexAt(int packedCoordinate); /** * Sets the index of the given section coordinate. * - * @param sectionCoordinate block index + * @param sectionCoordinate section index * @param index palette index */ void setPaletteIndexAt(int sectionCoordinate, int index); diff --git a/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/DataPaletteImpl.java b/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/DataPaletteImpl.java index 3c0c83484..7620ab2b0 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/DataPaletteImpl.java +++ b/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/DataPaletteImpl.java @@ -32,22 +32,26 @@ public final class DataPaletteImpl implements DataPalette { private final IntList palette; private final Int2IntMap inversePalette; private final int[] values; + private final int sizeBits; - public DataPaletteImpl() { - this.values = new int[ChunkSection.SIZE]; - palette = new IntArrayList(); - inversePalette = new Int2IntOpenHashMap(); - inversePalette.defaultReturnValue(-1); + public DataPaletteImpl(final int valuesLength) { + this(valuesLength, 8); } - public DataPaletteImpl(final int expectedPaletteLength) { - this.values = new int[ChunkSection.SIZE]; + public DataPaletteImpl(final int valuesLength, final int expectedPaletteLength) { + this.values = new int[valuesLength]; + sizeBits = Integer.numberOfTrailingZeros(valuesLength) / 3; // Pre-size the palette array/map palette = new IntArrayList(expectedPaletteLength); inversePalette = new Int2IntOpenHashMap(expectedPaletteLength); inversePalette.defaultReturnValue(-1); } + @Override + public int index(final int x, final int y, final int z) { + return (y << this.sizeBits | z) << this.sizeBits | x; + } + @Override public int idAt(final int sectionCoordinate) { final int index = values[sectionCoordinate]; diff --git a/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/PaletteType.java b/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/PaletteType.java index 8881b92aa..5c6e5b536 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/PaletteType.java +++ b/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/PaletteType.java @@ -24,18 +24,18 @@ package com.viaversion.viaversion.api.minecraft.chunks; public enum PaletteType { BLOCKS(ChunkSection.SIZE, 8), - BIOMES(4 * 4 * 4, 2); + BIOMES(ChunkSection.BIOME_SIZE, 2); - private final int maxSize; + private final int size; private final int highestBitsPerValue; - PaletteType(final int maxSize, final int highestBitsPerValue) { - this.maxSize = maxSize; + PaletteType(final int size, final int highestBitsPerValue) { + this.size = size; this.highestBitsPerValue = highestBitsPerValue; } - public int maxSize() { - return maxSize; + public int size() { + return size; } public int highestBitsPerValue() { diff --git a/api/src/main/java/com/viaversion/viaversion/api/type/types/version/PaletteType1_18.java b/api/src/main/java/com/viaversion/viaversion/api/type/types/version/PaletteType1_18.java index dbecfe7b3..66c35e939 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/type/types/version/PaletteType1_18.java +++ b/api/src/main/java/com/viaversion/viaversion/api/type/types/version/PaletteType1_18.java @@ -52,7 +52,7 @@ public final class PaletteType1_18 extends Type { final DataPaletteImpl palette; if (bitsPerValue == 0) { //TODO Create proper singleton palette Object - palette = new DataPaletteImpl(1); + palette = new DataPaletteImpl(type.size(), 1); palette.addId(Type.VAR_INT.readPrimitive(buffer)); Type.VAR_INT.readPrimitive(buffer); // 0 values length return palette; @@ -60,19 +60,19 @@ public final class PaletteType1_18 extends Type { if (bitsPerValue != globalPaletteBits) { final int paletteLength = Type.VAR_INT.readPrimitive(buffer); - palette = new DataPaletteImpl(paletteLength); + palette = new DataPaletteImpl(type.size(), paletteLength); for (int i = 0; i < paletteLength; i++) { palette.addId(Type.VAR_INT.readPrimitive(buffer)); } } else { - palette = new DataPaletteImpl(); + palette = new DataPaletteImpl(type.size()); } // Read values final long[] values = new long[Type.VAR_INT.readPrimitive(buffer)]; if (values.length > 0) { final char valuesPerLong = (char) (64 / bitsPerValue); - final int expectedLength = (type.maxSize() + valuesPerLong - 1) / valuesPerLong; + final int expectedLength = (type.size() + valuesPerLong - 1) / valuesPerLong; if (values.length != expectedLength) { throw new IllegalStateException("Palette data length (" + values.length + ") does not match expected length (" + expectedLength + ")! bitsPerValue=" + bitsPerValue + ", originalBitsPerValue=" + originalBitsPerValue); } @@ -80,7 +80,7 @@ public final class PaletteType1_18 extends Type { for (int i = 0; i < values.length; i++) { values[i] = buffer.readLong(); } - CompactArrayUtil.iterateCompactArrayWithPadding(bitsPerValue, type.maxSize(), values, + CompactArrayUtil.iterateCompactArrayWithPadding(bitsPerValue, type.size(), values, bitsPerValue == globalPaletteBits ? palette::setIdAt : palette::setPaletteIndexAt); } return palette; @@ -120,7 +120,7 @@ public final class PaletteType1_18 extends Type { } } - final long[] data = CompactArrayUtil.createCompactArrayWithPadding(bitsPerValue, type.maxSize(), bitsPerValue == globalPaletteBits ? palette::idAt : palette::paletteIndexAt); + final long[] data = CompactArrayUtil.createCompactArrayWithPadding(bitsPerValue, type.size(), bitsPerValue == globalPaletteBits ? palette::idAt : palette::paletteIndexAt); Type.VAR_INT.writePrimitive(buffer, data.length); for (final long l : data) { buffer.writeLong(l); diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_18to1_17_1/packets/WorldPackets.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_18to1_17_1/packets/WorldPackets.java index 39c4d43bf..11a1b2f54 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_18to1_17_1/packets/WorldPackets.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_18to1_17_1/packets/WorldPackets.java @@ -47,7 +47,6 @@ public final class WorldPackets { private static final int WIDTH_BITS = 2; private static final int HORIZONTAL_MASK = 3; - private static final int BIOMES_PER_CHUNK = 4 * 4 * 4; public static void register(final Protocol1_18To1_17_1 protocol) { protocol.registerClientbound(ClientboundPackets1_17_1.BLOCK_ENTITY_DATA, new PacketRemapper() { @@ -137,7 +136,7 @@ public final class WorldPackets { sections[i] = section; section.setNonAirBlocksCount(0); - final DataPaletteImpl blockPalette = new DataPaletteImpl(); + final DataPaletteImpl blockPalette = new DataPaletteImpl(ChunkSection.SIZE); blockPalette.addId(0); section.addPalette(PaletteType.BLOCKS, blockPalette); } else { @@ -149,20 +148,12 @@ public final class WorldPackets { } // Fill biome palette - final DataPaletteImpl biomePalette = new DataPaletteImpl(); + final DataPaletteImpl biomePalette = new DataPaletteImpl(ChunkSection.BIOME_SIZE); section.addPalette(PaletteType.BIOMES, biomePalette); - for (int biomeIndex = i * BIOMES_PER_CHUNK; biomeIndex < (i * BIOMES_PER_CHUNK) + BIOMES_PER_CHUNK; biomeIndex++) { - final int biome = biomeData[biomeIndex]; - final int minX = (biomeIndex & HORIZONTAL_MASK) << 2; - final int minY = ((biomeIndex >> WIDTH_BITS + WIDTH_BITS) << 2) & 15; - final int minZ = (biomeIndex >> WIDTH_BITS & HORIZONTAL_MASK) << 2; - for (int x = minX; x < minX + 4; x++) { - for (int y = minY; y < minY + 4; y++) { - for (int z = minZ; z < minZ + 4; z++) { - biomePalette.setIdAt(x, y, z, biome); - } - } - } + + final int offset = i * ChunkSection.BIOME_SIZE; + for (int biomeIndex = 0; biomeIndex < ChunkSection.BIOME_SIZE; biomeIndex++) { + biomePalette.setIdAt(biomeIndex, biomeData[offset + biomeIndex]); } }