Remove implementation details from Palette to allow better compression

Signed-off-by: TheMode <themode@outlook.fr>
This commit is contained in:
TheMode 2022-01-25 12:29:17 +01:00
parent 30cf6e8e4f
commit e9f9829c30
4 changed files with 34 additions and 53 deletions

View File

@ -63,7 +63,7 @@ public final class Section implements Writeable {
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeShort((short) blockPalette.size());
writer.writeShort((short) blockPalette.count());
writer.write(blockPalette);
writer.write(biomePalette);
}

View File

@ -42,30 +42,23 @@ public sealed interface Palette extends Writeable permits PaletteImpl {
/**
* Returns the number of entries in this palette.
*/
int size();
int count();
/**
* Returns the number of bits used per entry.
*/
int bitsPerEntry();
/**
* Returns the payload of this palette.
* <p>
* The size of each element is defined by {@link #bitsPerEntry()}.
*
* @return the palette payload
*/
long[] data();
int maxBitsPerEntry();
int dimension();
/**
* Returns the maximum number of entries in this palette.
*/
int maxSize();
int dimension();
default int maxSize() {
return dimension() * dimension() * dimension();
}
@NotNull Palette clone();

View File

@ -28,7 +28,6 @@ final class PaletteImpl implements Palette, Cloneable {
// Specific to this palette type
private final int dimension;
private final int dimensionBitCount;
private final int size;
private final int maxBitsPerEntry;
private final int bitsIncrement;
@ -39,7 +38,7 @@ final class PaletteImpl implements Palette, Cloneable {
private int count = 0;
private long[] values = new long[0];
private long[] values;
// palette index = value
private IntArrayList paletteToValueList;
// value = palette index
@ -49,7 +48,6 @@ final class PaletteImpl implements Palette, Cloneable {
this.dimensionBitCount = validateDimension(dimension);
this.dimension = dimension;
this.size = dimension * dimension * dimension;
this.maxBitsPerEntry = maxBitsPerEntry;
this.bitsIncrement = bitsIncrement;
@ -70,7 +68,7 @@ final class PaletteImpl implements Palette, Cloneable {
throw new IllegalArgumentException("Coordinates must be positive");
}
final long[] values = this.values;
if (values.length == 0) {
if (values == null) {
// Section is not loaded, return default value
return 0;
}
@ -105,7 +103,7 @@ final class PaletteImpl implements Palette, Cloneable {
final int bitsPerEntry = this.bitsPerEntry;
final int valuesPerLong = VALUES_PER_LONG[bitsPerEntry];
long[] values = this.values;
if (values.length == 0) {
if (values == null) {
if (placedAir) {
// Section is empty and method is trying to place an air block, stop unnecessary computation
return;
@ -142,7 +140,7 @@ final class PaletteImpl implements Palette, Cloneable {
@Override
public void fill(int value) {
if (value == 0) {
this.values = new long[0];
this.values = null;
this.count = 0;
return;
}
@ -150,7 +148,7 @@ final class PaletteImpl implements Palette, Cloneable {
final int bitsPerEntry = this.bitsPerEntry;
final int valuesPerLong = VALUES_PER_LONG[bitsPerEntry];
long[] values = this.values;
if (values.length == 0) {
if (values == null) {
this.values = values = new long[valuesLength(bitsPerEntry)];
}
long block = 0;
@ -223,7 +221,7 @@ final class PaletteImpl implements Palette, Cloneable {
}
@Override
public int size() {
public int count() {
return count;
}
@ -237,26 +235,16 @@ final class PaletteImpl implements Palette, Cloneable {
return maxBitsPerEntry;
}
@Override
public int maxSize() {
return size;
}
@Override
public int dimension() {
return dimension;
}
@Override
public long[] data() {
return values;
}
@Override
public @NotNull Palette clone() {
try {
PaletteImpl palette = (PaletteImpl) super.clone();
palette.values = values.clone();
palette.values = values != null ? values.clone() : null;
palette.paletteToValueList = paletteToValueList.clone();
palette.valueToPaletteMap = valueToPaletteMap.clone();
palette.count = count;
@ -283,7 +271,7 @@ final class PaletteImpl implements Palette, Cloneable {
private void retrieveAll(@NotNull EntryConsumer consumer, boolean consumeEmpty) {
final long[] values = this.values;
final int dimension = this.dimension;
if (values.length == 0) {
if (values == null) {
if (consumeEmpty) {
// No values, give all 0 to make the consumer happy
for (int y = 0; y < dimension; y++)
@ -296,7 +284,7 @@ final class PaletteImpl implements Palette, Cloneable {
final int bitsPerEntry = this.bitsPerEntry;
final int magicMask = MAGIC_MASKS[bitsPerEntry];
final int valuesPerLong = VALUES_PER_LONG[bitsPerEntry];
final int size = this.size;
final int size = maxSize();
final int dimensionMinus = dimension - 1;
final int[] ids = hasPalette ? paletteToValueList.elements() : null;
final int dimensionBitCount = this.dimensionBitCount;
@ -333,12 +321,12 @@ final class PaletteImpl implements Palette, Cloneable {
}
private void updateAll(int[] paletteValues) {
final int size = this.size;
final int size = maxSize();
assert paletteValues.length >= size;
final int bitsPerEntry = this.bitsPerEntry;
final int valuesPerLong = VALUES_PER_LONG[bitsPerEntry];
long[] values = this.values;
if (values.length == 0) {
if (values == null) {
this.values = values = new long[valuesLength(bitsPerEntry)];
}
final int magicMask = MAGIC_MASKS[bitsPerEntry];
@ -400,7 +388,7 @@ final class PaletteImpl implements Palette, Cloneable {
int valuesLength(int bitsPerEntry) {
int valuesPerLong = VALUES_PER_LONG[bitsPerEntry];
return (size + valuesPerLong - 1) / valuesPerLong;
return (maxSize() + valuesPerLong - 1) / valuesPerLong;
}
static int maxPaletteSize(int bitsPerEntry) {

View File

@ -27,32 +27,32 @@ public class PaletteTest {
for (Palette palette : palettes) {
final int dimension = palette.dimension();
assertEquals(0, palette.get(0, 0, 0), "Default value should be 0");
assertEquals(0, palette.size());
assertEquals(0, palette.count());
palette.set(0, 0, 0, 64);
assertEquals(64, palette.get(0, 0, 0));
assertEquals(64, palette.get(dimension, 0, 0), "Coordinate must be rounded to the palette dimension");
assertEquals(1, palette.size());
assertEquals(1, palette.count());
palette.set(1, 0, 0, 65);
assertEquals(64, palette.get(0, 0, 0));
assertEquals(65, palette.get(1, 0, 0));
assertEquals(2, palette.size());
assertEquals(2, palette.count());
palette.set(0, 1, 0, 66);
assertEquals(64, palette.get(0, 0, 0));
assertEquals(65, palette.get(1, 0, 0));
assertEquals(66, palette.get(0, 1, 0));
assertEquals(3, palette.size());
assertEquals(3, palette.count());
palette.set(0, 0, 1, 67);
assertEquals(64, palette.get(0, 0, 0));
assertEquals(65, palette.get(1, 0, 0));
assertEquals(66, palette.get(0, 1, 0));
assertEquals(67, palette.get(0, 0, 1));
assertEquals(4, palette.size());
assertEquals(4, palette.count());
palette.set(0, 0, 1, 68);
assertEquals(4, palette.size());
assertEquals(4, palette.count());
}
}
@ -93,13 +93,13 @@ public class PaletteTest {
public void fill() {
var palettes = testPalettes();
for (Palette palette : palettes) {
assertEquals(0, palette.size());
assertEquals(0, palette.count());
palette.set(0, 0, 0, 5);
assertEquals(1, palette.size());
assertEquals(1, palette.count());
assertEquals(5, palette.get(0, 0, 0));
palette.fill(6);
assertEquals(6, palette.get(0, 0, 0));
assertEquals(palette.maxSize(), palette.size());
assertEquals(palette.maxSize(), palette.count());
for (int x = 0; x < palette.dimension(); x++) {
for (int y = 0; y < palette.dimension(); y++) {
for (int z = 0; z < palette.dimension(); z++) {
@ -109,7 +109,7 @@ public class PaletteTest {
}
palette.fill(0);
assertEquals(0, palette.size());
assertEquals(0, palette.count());
for (int x = 0; x < palette.dimension(); x++) {
for (int y = 0; y < palette.dimension(); y++) {
for (int z = 0; z < palette.dimension(); z++) {
@ -133,7 +133,7 @@ public class PaletteTest {
}
}
}
assertEquals(palette.maxSize(), palette.size());
assertEquals(palette.maxSize(), palette.count());
// Verify
for (int x = 0; x < dimension; x++) {
for (int y = 0; y < dimension; y++) {
@ -181,12 +181,12 @@ public class PaletteTest {
assertTrue(points.add(new Vec(x, y, z)), "Duplicate point: " + x + ", " + y + ", " + z + ", dimension " + palette.dimension());
return count.incrementAndGet();
});
assertEquals(palette.maxSize(), palette.size());
assertEquals(palette.size(), count.get());
assertEquals(palette.maxSize(), palette.count());
assertEquals(palette.count(), count.get());
count.set(0);
palette.getAll((x, y, z, value) -> assertEquals(count.incrementAndGet(), value));
assertEquals(count.get(), palette.size());
assertEquals(count.get(), palette.count());
// Replacing
count.set(0);
@ -194,7 +194,7 @@ public class PaletteTest {
assertEquals(count.incrementAndGet(), value);
return count.get();
});
assertEquals(count.get(), palette.size());
assertEquals(count.get(), palette.count());
count.set(0);
palette.getAll((x, y, z, value) -> assertEquals(count.incrementAndGet(), value));