From e2edb8473adcae012ba099aa6c8d8b816e118c96 Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Sun, 8 Dec 2024 00:47:23 +0800 Subject: [PATCH] feat: some improvements on palette & bitarray --- .../datastruct/bitarray/BitArrayVersion.java | 18 ++++++------ .../server/datastruct/palette/Palette.java | 19 +++++++----- .../server/world/chunk/ChunkSection.java | 2 +- .../datastruct/palette/PaletteTest.java | 29 +++++++++++++++++++ 4 files changed, 51 insertions(+), 17 deletions(-) create mode 100644 server/src/test/java/org/allaymc/server/datastruct/palette/PaletteTest.java diff --git a/server/src/main/java/org/allaymc/server/datastruct/bitarray/BitArrayVersion.java b/server/src/main/java/org/allaymc/server/datastruct/bitarray/BitArrayVersion.java index aa1df2b83..01eb1f5c0 100644 --- a/server/src/main/java/org/allaymc/server/datastruct/bitarray/BitArrayVersion.java +++ b/server/src/main/java/org/allaymc/server/datastruct/bitarray/BitArrayVersion.java @@ -33,7 +33,7 @@ public enum BitArrayVersion { } public static BitArrayVersion get(int version, boolean read) { - for (BitArrayVersion ver : values()) { + for (BitArrayVersion ver : VALUES) { if ((!read && ver.entriesPerWord <= version) || (read && ver.bits == version)) { return ver; } @@ -52,11 +52,6 @@ public static BitArrayVersion forBitsCeil(int bits) { return null; } - public int getWordsForSize(int size) { - Preconditions.checkArgument(this != V0); - return GenericMath.ceil((float) size / this.entriesPerWord); - } - public BitArray createArray(int size) { if (this == V0) { return SingletonBitArray.INSTANCE; @@ -64,12 +59,17 @@ public BitArray createArray(int size) { return this.createArray(size, new int[getWordsForSize(size)]); } + public int getWordsForSize(int size) { + Preconditions.checkArgument(this != V0); + return GenericMath.ceil((float) size / this.entriesPerWord); + } + public BitArray createArray(int size, int[] words) { - if (this == V3 || this == V5 || this == V6) { + if (this == V0) { + return SingletonBitArray.INSTANCE; + } else if (this == V3 || this == V5 || this == V6) { // Padded palettes aren't able to use bitwise operations due to their padding. return new PaddedBitArray(this, size, words); - } else if (this == V0) { - return SingletonBitArray.INSTANCE; } else { return new Pow2BitArray(this, size, words); } diff --git a/server/src/main/java/org/allaymc/server/datastruct/palette/Palette.java b/server/src/main/java/org/allaymc/server/datastruct/palette/Palette.java index c804b400f..8e7350e09 100644 --- a/server/src/main/java/org/allaymc/server/datastruct/palette/Palette.java +++ b/server/src/main/java/org/allaymc/server/datastruct/palette/Palette.java @@ -16,8 +16,6 @@ import java.util.List; /** - * TODO: add tests - * * @author JukeboxMC | daoge_cmd | CoolLoong */ @Slf4j @@ -69,7 +67,7 @@ public void writeToNetwork(ByteBuf byteBuf, RuntimeDataSerializer serializer) } public void writeToStoragePersistent(ByteBuf byteBuf, PersistentDataSerializer serializer) { - var version = isEmpty() ? BitArrayVersion.V0 : this.bitArray.version(); + var version = oneEntryOnly() ? BitArrayVersion.V0 : this.bitArray.version(); byteBuf.writeByte(Palette.getPaletteHeader(version, false)); if (version != BitArrayVersion.V0) { @@ -118,12 +116,12 @@ public void readFromStoragePersistent(ByteBuf byteBuf, PersistentDataDeserialize public void writeToStorageRuntime(ByteBuf byteBuf, RuntimeDataSerializer serializer, Palette last) { // FIXME: copy last flag -// if (last != null && last.palette.equals(this.palette)) { +// if (last != null && last.equals(this)) { // byteBuf.writeByte(COPY_LAST_FLAG_HEADER); // return; // } - var version = this.isEmpty() ? BitArrayVersion.V0 : this.bitArray.version(); + var version = this.oneEntryOnly() ? BitArrayVersion.V0 : this.bitArray.version(); byteBuf.writeByte(Palette.getPaletteHeader(version, true)); if (version != BitArrayVersion.V0) { for (int word : this.bitArray.words()) { @@ -167,13 +165,18 @@ public void readFromStorageRuntime(ByteBuf byteBuf, RuntimeDataDeserializer d } } - public boolean isEmpty() { + public boolean oneEntryOnly() { if (this.palette.size() == 1) { return true; } - // Do not use stream, this will be quicker + // The palette list may contain more than one entry, + // but the words are all point to the first entry. + // In this case, the palette is still one entry only. for (int word : this.bitArray.words()) { + // Do not use stream, this will be quicker if (Integer.toUnsignedLong(word) != 0L) { + // The word is not point to the first entry, + // so this palette shouldn't be empty return false; } } @@ -217,6 +220,8 @@ private int paletteIndexFor(V value) { var next = version.next; if (next != null) { this.onResize(next); + } else { + throw new PaletteException("Palette have reached the max bit array version"); } } diff --git a/server/src/main/java/org/allaymc/server/world/chunk/ChunkSection.java b/server/src/main/java/org/allaymc/server/world/chunk/ChunkSection.java index 03cb3d2e3..10de8417c 100644 --- a/server/src/main/java/org/allaymc/server/world/chunk/ChunkSection.java +++ b/server/src/main/java/org/allaymc/server/world/chunk/ChunkSection.java @@ -49,7 +49,7 @@ public BiomeType getBiomeType(int x, int y, int z) { } public boolean isAirSection() { - return blockLayers[0].isEmpty() && blockLayers[0].get(0) == AIR.getDefaultState(); + return blockLayers[0].oneEntryOnly() && blockLayers[0].get(0) == AIR.getDefaultState(); } public void writeToNetwork(ByteBuf byteBuf) { diff --git a/server/src/test/java/org/allaymc/server/datastruct/palette/PaletteTest.java b/server/src/test/java/org/allaymc/server/datastruct/palette/PaletteTest.java new file mode 100644 index 000000000..19fe11d4f --- /dev/null +++ b/server/src/test/java/org/allaymc/server/datastruct/palette/PaletteTest.java @@ -0,0 +1,29 @@ +package org.allaymc.server.datastruct.palette; + +import org.allaymc.server.datastruct.bitarray.BitArrayVersion; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * @author daoge_cmd + */ +class PaletteTest { + + @Test + void test() { + var obj0 = new Object(); + var palette = new Palette<>(obj0, BitArrayVersion.V0); + assertEquals(obj0, palette.get(0)); + + var obj1 = new Object(); + palette.set(1, obj1); + assertEquals(obj1, palette.get(1)); + + var obj2 = new Object(); + palette.set(2, obj2); + assertEquals(obj2, palette.get(2)); + + // TODO: more tests + } +} \ No newline at end of file