From 41a52c993e493f6ae5896d9cbd5f9730001185cd Mon Sep 17 00:00:00 2001 From: TheMode Date: Sat, 18 Dec 2021 16:30:24 +0100 Subject: [PATCH] Add basic tests for Palette Signed-off-by: TheMode --- .../server/instance/palette/Palette.java | 10 ++- .../server/instance/palette/PaletteImpl.java | 31 +++++++--- src/test/java/instance/PaletteTest.java | 61 +++++++++++++++++++ 3 files changed, 93 insertions(+), 9 deletions(-) create mode 100644 src/test/java/instance/PaletteTest.java diff --git a/src/main/java/net/minestom/server/instance/palette/Palette.java b/src/main/java/net/minestom/server/instance/palette/Palette.java index 8619cf694..3726fe00a 100644 --- a/src/main/java/net/minestom/server/instance/palette/Palette.java +++ b/src/main/java/net/minestom/server/instance/palette/Palette.java @@ -10,11 +10,15 @@ import org.jetbrains.annotations.NotNull; */ public sealed interface Palette extends Writeable permits PaletteImpl { static Palette blocks() { - return new PaletteImpl(16 * 16 * 16, 8, 6, 1); + return newPalette(16, 8, 6, 1); } static Palette biomes() { - return new PaletteImpl(4 * 4 * 4, 2, 2, 1); + return newPalette(4, 2, 2, 1); + } + + static Palette newPalette(int dimension, int maxBitsPerEntry, int bitsPerEntry, int bitIncrement) { + return new PaletteImpl(dimension, maxBitsPerEntry, bitsPerEntry, bitIncrement); } int get(int x, int y, int z); @@ -47,5 +51,7 @@ public sealed interface Palette extends Writeable permits PaletteImpl { */ int maxSize(); + int dimension(); + @NotNull Palette clone(); } diff --git a/src/main/java/net/minestom/server/instance/palette/PaletteImpl.java b/src/main/java/net/minestom/server/instance/palette/PaletteImpl.java index 3c968ef0e..997025117 100644 --- a/src/main/java/net/minestom/server/instance/palette/PaletteImpl.java +++ b/src/main/java/net/minestom/server/instance/palette/PaletteImpl.java @@ -7,8 +7,6 @@ import net.minestom.server.instance.Chunk; import net.minestom.server.utils.binary.BinaryWriter; import org.jetbrains.annotations.NotNull; -import static net.minestom.server.instance.Chunk.CHUNK_SECTION_SIZE; - final class PaletteImpl implements Palette, Cloneable { // Magic values generated with "Integer.MAX_VALUE >> (31 - bitsPerIndex)" for bitsPerIndex between 1 and 16 private static final int[] MAGIC_MASKS = @@ -18,6 +16,7 @@ final class PaletteImpl implements Palette, Cloneable { 8191, 16383, 32767}; // Specific to this palette type + private final int dimension; private final int size; private final int maxBitsPerEntry; @@ -36,8 +35,9 @@ final class PaletteImpl implements Palette, Cloneable { // value = palette index private Int2IntOpenHashMap valueToPaletteMap; - PaletteImpl(int size, int maxBitsPerEntry, int bitsPerEntry, int bitsIncrement) { - this.size = size; + PaletteImpl(int dimension, int maxBitsPerEntry, int bitsPerEntry, int bitsIncrement) { + this.dimension = dimension; + this.size = dimension * dimension * dimension; this.maxBitsPerEntry = maxBitsPerEntry; this.bitsPerEntry = bitsPerEntry; @@ -55,10 +55,16 @@ final class PaletteImpl implements Palette, Cloneable { @Override public int get(int x, int y, int z) { + if (x < 0 || y < 0 || z < 0) { + throw new IllegalArgumentException("Coordinates must be positive"); + } if (values.length == 0) { // Section is not loaded, can only be air return -1; } + x %= dimension; + y %= dimension; + z %= dimension; final int sectionIdentifier = getSectionIndex(x, y, z); final int index = sectionIdentifier / valuesPerLong; final int bitIndex = sectionIdentifier % valuesPerLong * bitsPerEntry; @@ -69,6 +75,9 @@ final class PaletteImpl implements Palette, Cloneable { @Override public void set(int x, int y, int z, int value) { + if (x < 0 || y < 0 || z < 0) { + throw new IllegalArgumentException("Coordinates must be positive"); + } final boolean placedAir = value == 0; if (values.length == 0) { if (placedAir) { @@ -78,6 +87,9 @@ final class PaletteImpl implements Palette, Cloneable { // Initialize the section this.values = new long[(size + valuesPerLong - 1) / valuesPerLong]; } + x %= dimension; + y %= dimension; + z %= dimension; // Change to palette value value = getPaletteIndex(value); final int sectionIndex = getSectionIndex(x, y, z); @@ -126,6 +138,11 @@ final class PaletteImpl implements Palette, Cloneable { return size; } + @Override + public int dimension() { + return dimension; + } + @Override public long[] data() { return values; @@ -201,9 +218,9 @@ final class PaletteImpl implements Palette, Cloneable { return paletteIndex; } - static int getSectionIndex(int x, int y, int z) { - y = Math.floorMod(y, CHUNK_SECTION_SIZE); - return y << 8 | z << 4 | x; + int getSectionIndex(int x, int y, int z) { + y = Math.floorMod(y, dimension); + return y << (dimension / 2) | z << (dimension / 4) | x; } static int maxPaletteSize(int bitsPerEntry) { diff --git a/src/test/java/instance/PaletteTest.java b/src/test/java/instance/PaletteTest.java new file mode 100644 index 000000000..6ef6e4e69 --- /dev/null +++ b/src/test/java/instance/PaletteTest.java @@ -0,0 +1,61 @@ +package instance; + +import net.minestom.server.instance.palette.Palette; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class PaletteTest { + private List palettes = new ArrayList<>(); + + @BeforeEach + public void reset() { + for (int i = 4; i < 16; i++) { + palettes.add(Palette.newPalette(i, 5, 3, 1)); + } + } + + @Test + public void testPlacement() { + for (Palette palette : palettes) { + final int dimension = palette.dimension(); + assertEquals(-1, palette.get(0, 0, 0), "Empty section should return -1"); + 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"); + + palette.set(1, 0, 0, 65); + assertEquals(64, palette.get(0, 0, 0)); + assertEquals(65, palette.get(1, 0, 0)); + + 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)); + + 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)); + } + } + + @Test + public void testPlacementNeg() { + for (Palette palette : palettes) { + assertThrows(IllegalArgumentException.class, () -> palette.set(-1, 0, 0, 64)); + assertThrows(IllegalArgumentException.class, () -> palette.set(0, -1, 0, 64)); + assertThrows(IllegalArgumentException.class, () -> palette.set(0, 0, -1, 64)); + + assertThrows(IllegalArgumentException.class, () -> palette.get(-1, 0, 0)); + assertThrows(IllegalArgumentException.class, () -> palette.get(0, -1, 0)); + assertThrows(IllegalArgumentException.class, () -> palette.get(0, 0, -1)); + } + } +}