diff --git a/common/src/main/java/us/myles/ViaVersion/api/minecraft/chunks/ChunkSection.java b/common/src/main/java/us/myles/ViaVersion/api/minecraft/chunks/ChunkSection.java index 595496c26..75c63a346 100644 --- a/common/src/main/java/us/myles/ViaVersion/api/minecraft/chunks/ChunkSection.java +++ b/common/src/main/java/us/myles/ViaVersion/api/minecraft/chunks/ChunkSection.java @@ -1,13 +1,12 @@ package us.myles.ViaVersion.api.minecraft.chunks; import io.netty.buffer.ByteBuf; +import it.unimi.dsi.fastutil.ints.Int2IntMap; +import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - public class ChunkSection { /** @@ -18,8 +17,8 @@ public class ChunkSection { * Length of the sky and block light nibble arrays. */ public static final int LIGHT_LENGTH = 16 * 16 * 16 / 2; // size * size * size / 2 (nibble bit count) - private final List palette = new ArrayList<>(); - private final Map inversePalette = new HashMap<>(); + private final IntList palette; + private final Int2IntMap inversePalette; private final int[] blocks; private NibbleArray blockLight; private NibbleArray skyLight; @@ -28,7 +27,19 @@ public class ChunkSection { public ChunkSection() { this.blocks = new int[SIZE]; this.blockLight = new NibbleArray(SIZE); - addPaletteEntry(0); + palette = new IntArrayList(); + inversePalette = new Int2IntOpenHashMap(); + inversePalette.defaultReturnValue(-1); + } + + public ChunkSection(int expectedPaletteLength) { + this.blocks = new int[SIZE]; + this.blockLight = new NibbleArray(SIZE); + + // Pre-size the palette array/map + palette = new IntArrayList(expectedPaletteLength); + inversePalette = new Int2IntOpenHashMap(expectedPaletteLength); + inversePalette.defaultReturnValue(-1); } /** @@ -59,12 +70,12 @@ public class ChunkSection { public int getFlatBlock(int x, int y, int z) { int index = blocks[index(x, y, z)]; - return palette.get(index); + return palette.getInt(index); } public int getFlatBlock(int idx) { int index = blocks[idx]; - return palette.get(index); + return palette.getInt(index); } public void setBlock(int idx, int type, int data) { @@ -85,18 +96,20 @@ public class ChunkSection { public int getPaletteEntry(int index) { if (index < 0 || index >= palette.size()) throw new IndexOutOfBoundsException(); - return palette.get(index); + return palette.getInt(index); } public void setPaletteEntry(int index, int id) { if (index < 0 || index >= palette.size()) throw new IndexOutOfBoundsException(); + int oldId = palette.set(index, id); if (oldId == id) return; + inversePalette.put(id, index); if (inversePalette.get(oldId) == index) { inversePalette.remove(oldId); for (int i = 0; i < palette.size(); i++) { - if (palette.get(i) == oldId) { + if (palette.getInt(i) == oldId) { inversePalette.put(oldId, i); break; } @@ -105,11 +118,14 @@ public class ChunkSection { } public void replacePaletteEntry(int oldId, int newId) { - Integer index = inversePalette.remove(oldId); - if (index == null) return; + int index = inversePalette.remove(oldId); + if (index == -1) return; + inversePalette.put(newId, index); for (int i = 0; i < palette.size(); i++) { - if (palette.get(i) == oldId) palette.set(i, newId); + if (palette.getInt(i) == oldId) { + palette.set(i, newId); + } } } @@ -131,8 +147,8 @@ public class ChunkSection { * @param id The raw or flat id of the block */ public void setFlatBlock(int idx, int id) { - Integer index = inversePalette.get(id); - if (index == null) { + int index = inversePalette.get(id); + if (index == -1) { index = palette.size(); palette.add(id); inversePalette.put(id, index); diff --git a/common/src/main/java/us/myles/ViaVersion/api/type/types/version/ChunkSectionType1_13.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/version/ChunkSectionType1_13.java index f2b74b309..762b1c6b4 100644 --- a/common/src/main/java/us/myles/ViaVersion/api/type/types/version/ChunkSectionType1_13.java +++ b/common/src/main/java/us/myles/ViaVersion/api/type/types/version/ChunkSectionType1_13.java @@ -14,8 +14,6 @@ public class ChunkSectionType1_13 extends Type { @Override public ChunkSection read(ByteBuf buffer) throws Exception { - ChunkSection chunkSection = new ChunkSection(); - // Reaad bits per block int bitsPerBlock = buffer.readUnsignedByte(); int originalBitsPerBlock = bitsPerBlock; @@ -24,11 +22,16 @@ public class ChunkSectionType1_13 extends Type { bitsPerBlock = GLOBAL_PALETTE; } - int paletteLength = bitsPerBlock == GLOBAL_PALETTE ? 0 : Type.VAR_INT.readPrimitive(buffer); // Read palette - chunkSection.clearPalette(); - for (int i = 0; i < paletteLength; i++) { - chunkSection.addPaletteEntry(Type.VAR_INT.readPrimitive(buffer)); + ChunkSection chunkSection; + if (bitsPerBlock != GLOBAL_PALETTE) { + int paletteLength = Type.VAR_INT.readPrimitive(buffer); + chunkSection = new ChunkSection(paletteLength); + for (int i = 0; i < paletteLength; i++) { + chunkSection.addPaletteEntry(Type.VAR_INT.readPrimitive(buffer)); + } + } else { + chunkSection = new ChunkSection(); } // Read blocks diff --git a/common/src/main/java/us/myles/ViaVersion/api/type/types/version/ChunkSectionType1_16.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/version/ChunkSectionType1_16.java index 375f20565..3f911db09 100644 --- a/common/src/main/java/us/myles/ViaVersion/api/type/types/version/ChunkSectionType1_16.java +++ b/common/src/main/java/us/myles/ViaVersion/api/type/types/version/ChunkSectionType1_16.java @@ -14,8 +14,6 @@ public class ChunkSectionType1_16 extends Type { @Override public ChunkSection read(ByteBuf buffer) throws Exception { - ChunkSection chunkSection = new ChunkSection(); - // Reaad bits per block int bitsPerBlock = buffer.readUnsignedByte(); int originalBitsPerBlock = bitsPerBlock; @@ -24,11 +22,16 @@ public class ChunkSectionType1_16 extends Type { bitsPerBlock = GLOBAL_PALETTE; } - int paletteLength = bitsPerBlock == GLOBAL_PALETTE ? 0 : Type.VAR_INT.readPrimitive(buffer); // Read palette - chunkSection.clearPalette(); - for (int i = 0; i < paletteLength; i++) { - chunkSection.addPaletteEntry(Type.VAR_INT.readPrimitive(buffer)); + ChunkSection chunkSection; + if (bitsPerBlock != GLOBAL_PALETTE) { + int paletteLength = Type.VAR_INT.readPrimitive(buffer); + chunkSection = new ChunkSection(paletteLength); + for (int i = 0; i < paletteLength; i++) { + chunkSection.addPaletteEntry(Type.VAR_INT.readPrimitive(buffer)); + } + } else { + chunkSection = new ChunkSection(); } // Read blocks diff --git a/common/src/main/java/us/myles/ViaVersion/api/type/types/version/ChunkSectionType1_8.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/version/ChunkSectionType1_8.java index b9fb18036..112f70083 100644 --- a/common/src/main/java/us/myles/ViaVersion/api/type/types/version/ChunkSectionType1_8.java +++ b/common/src/main/java/us/myles/ViaVersion/api/type/types/version/ChunkSectionType1_8.java @@ -15,7 +15,8 @@ public class ChunkSectionType1_8 extends Type { @Override public ChunkSection read(ByteBuf buffer) throws Exception { ChunkSection chunkSection = new ChunkSection(); - // Don't clear palette because 0 index needs to be air in 1.9 version + // 0 index needs to be air in 1.9 + chunkSection.addPaletteEntry(0); ByteBuf littleEndianView = buffer.order(ByteOrder.LITTLE_ENDIAN); diff --git a/common/src/main/java/us/myles/ViaVersion/api/type/types/version/ChunkSectionType1_9.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/version/ChunkSectionType1_9.java index c4630635a..a75ce3101 100644 --- a/common/src/main/java/us/myles/ViaVersion/api/type/types/version/ChunkSectionType1_9.java +++ b/common/src/main/java/us/myles/ViaVersion/api/type/types/version/ChunkSectionType1_9.java @@ -14,8 +14,6 @@ public class ChunkSectionType1_9 extends Type { @Override public ChunkSection read(ByteBuf buffer) throws Exception { - ChunkSection chunkSection = new ChunkSection(); - // Reaad bits per block int bitsPerBlock = buffer.readUnsignedByte(); int originalBitsPerBlock = bitsPerBlock; @@ -29,9 +27,10 @@ public class ChunkSectionType1_9 extends Type { if (bitsPerBlock > 8) { bitsPerBlock = GLOBAL_PALETTE; } - int paletteLength = Type.VAR_INT.readPrimitive(buffer); + // Read palette - chunkSection.clearPalette(); + int paletteLength = Type.VAR_INT.readPrimitive(buffer); + ChunkSection chunkSection = bitsPerBlock != GLOBAL_PALETTE ? new ChunkSection(paletteLength) : new ChunkSection(); for (int i = 0; i < paletteLength; i++) { if (bitsPerBlock != GLOBAL_PALETTE) { chunkSection.addPaletteEntry(Type.VAR_INT.readPrimitive(buffer));