Fix biome palette writing

Co-authored-by: Gerrygames <gecam59@gmail.com>
This commit is contained in:
Nassim Jahnke 2021-10-08 12:52:53 +02:00
parent 3feff8e751
commit e744214ad6
No known key found for this signature in database
GPG Key ID: 6BE3B555EBC5982B
7 changed files with 56 additions and 46 deletions

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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);

View File

@ -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];

View File

@ -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() {

View File

@ -52,7 +52,7 @@ public final class PaletteType1_18 extends Type<DataPalette> {
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<DataPalette> {
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<DataPalette> {
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<DataPalette> {
}
}
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);

View File

@ -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]);
}
}