From cf0bd6f021bd09396b5212b5d7c708f3602f19b2 Mon Sep 17 00:00:00 2001 From: Gerrygames Date: Mon, 12 Nov 2018 17:10:19 +0100 Subject: [PATCH] Use List and Map, fixes duplicate block ids in palette causing issues --- .../api/minecraft/chunks/ChunkSection.java | 52 +++++++++++++------ .../types/version/ChunkSectionType1_13.java | 16 +++--- .../types/version/ChunkSectionType1_8.java | 2 +- .../types/version/ChunkSectionType1_9.java | 15 +++--- 4 files changed, 50 insertions(+), 35 deletions(-) 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 88b69da0e..9305a5994 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,11 +1,14 @@ package us.myles.ViaVersion.api.minecraft.chunks; -import com.google.common.collect.BiMap; -import com.google.common.collect.HashBiMap; import io.netty.buffer.ByteBuf; import lombok.Getter; import lombok.Setter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + public class ChunkSection { /** * Size (dimensions) of blocks in a chunks section. @@ -15,8 +18,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) - @Getter - private BiMap palette = HashBiMap.create(); + private List palette = new ArrayList<>(); + private Map inversePalette = new HashMap<>(); private final int[] blocks; private NibbleArray blockLight; private NibbleArray skyLight; @@ -27,7 +30,8 @@ public class ChunkSection { public ChunkSection() { this.blocks = new int[SIZE]; this.blockLight = new NibbleArray(SIZE); - palette.put(0, 0); + palette.add(0); + inversePalette.put(0, 0); } /** @@ -58,12 +62,12 @@ public class ChunkSection { public int getFlatBlock(int x, int y, int z) { int index = blocks[index(x, y, z)]; - return palette.inverse().get(index); + return palette.get(index); } public int getFlatBlock(int idx) { int index = blocks[idx]; - return palette.inverse().get(index); + return palette.get(index); } public void setBlock(int idx, int type, int data) { @@ -84,16 +88,32 @@ public class ChunkSection { public int getPaletteEntry(int index) { if (index < 0 || index >= palette.size()) throw new IndexOutOfBoundsException(); - return palette.inverse().get(index); + return palette.get(index); } public void setPaletteEntry(int index, int id) { if (index < 0 || index >= palette.size()) throw new IndexOutOfBoundsException(); - palette.forcePut(id, index); + palette.set(index, id); + inversePalette.put(id, index); } public void replacePaletteEntry(int oldId, int newId) { - if (palette.containsKey(oldId)) palette.put(newId, palette.remove(oldId)); + Integer index = inversePalette.remove(oldId); + if (index == null) return; + inversePalette.put(newId, index); + for (int i = 0; i < palette.size(); i++) { + if (palette.get(i) == oldId) palette.set(i, newId); + } + } + + public void addPaletteEntry(int id) { + inversePalette.put(id, palette.size()); + palette.add(id); + } + + public void clearPalette() { + palette.clear(); + inversePalette.clear(); } /** @@ -104,12 +124,14 @@ public class ChunkSection { * @param id The raw or flat id of the block */ public void setFlatBlock(int idx, int id) { - Integer index = palette.get(id); - if (index == null) { - palette.put(id, index = palette.size()); - } + Integer index = inversePalette.get(id); + if (index == null) { + index = palette.size(); + palette.add(id); + inversePalette.put(id, index); + } - blocks[idx] = index; + blocks[idx] = 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 b2d7cf080..e6e265475 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 @@ -1,6 +1,5 @@ package us.myles.ViaVersion.api.type.types.version; -import com.google.common.collect.BiMap; import io.netty.buffer.ByteBuf; import us.myles.ViaVersion.api.minecraft.chunks.ChunkSection; import us.myles.ViaVersion.api.type.Type; @@ -14,8 +13,6 @@ public class ChunkSectionType1_13 extends Type { @Override public ChunkSection read(ByteBuf buffer) throws Exception { ChunkSection chunkSection = new ChunkSection(); - BiMap palette = chunkSection.getPalette(); - palette.clear(); // Reaad bits per block int bitsPerBlock = buffer.readUnsignedByte(); @@ -32,8 +29,9 @@ public class ChunkSectionType1_13 extends Type { } int paletteLength = bitsPerBlock == 14 ? 0 : Type.VAR_INT.read(buffer); // Read palette + chunkSection.clearPalette(); for (int i = 0; i < paletteLength; i++) { - palette.put(Type.VAR_INT.read(buffer), palette.size()); + chunkSection.addPaletteEntry(Type.VAR_INT.read(buffer)); } // Read blocks @@ -68,10 +66,8 @@ public class ChunkSectionType1_13 extends Type { @Override public void write(ByteBuf buffer, ChunkSection chunkSection) throws Exception { - BiMap palette = chunkSection.getPalette(); - int bitsPerBlock = 4; - while (palette.size() > 1 << bitsPerBlock) { + while (chunkSection.getPaletteSize() > 1 << bitsPerBlock) { bitsPerBlock += 1; } @@ -85,9 +81,9 @@ public class ChunkSectionType1_13 extends Type { // Write pallet (or not) if (bitsPerBlock != 14) { - Type.VAR_INT.write(buffer, palette.size()); - for (int i = 0; i < palette.size(); i++) { - Type.VAR_INT.write(buffer, palette.inverse().get(i)); + Type.VAR_INT.write(buffer, chunkSection.getPaletteSize()); + for (int i = 0; i < chunkSection.getPaletteSize(); i++) { + Type.VAR_INT.write(buffer, chunkSection.getPaletteEntry(i)); } } 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 e132d7f35..2cc3f478b 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 @@ -17,7 +17,7 @@ public class ChunkSectionType1_8 extends Type { @Override public ChunkSection read(ByteBuf buffer) throws Exception { ChunkSection chunkSection = new ChunkSection(); - chunkSection.getPalette().clear(); + chunkSection.clearPalette(); byte[] blockData = new byte[ChunkSection.SIZE * 2]; buffer.readBytes(blockData); 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 37758816c..8a596e24a 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(); - BiMap palette = chunkSection.getPalette(); - palette.clear(); // Reaad bits per block int bitsPerBlock = buffer.readUnsignedByte(); @@ -32,9 +30,10 @@ public class ChunkSectionType1_9 extends Type { } int paletteLength = Type.VAR_INT.read(buffer); // Read palette + chunkSection.clearPalette(); for (int i = 0; i < paletteLength; i++) { if (bitsPerBlock != 13) { - palette.put(Type.VAR_INT.read(buffer), palette.size()); + chunkSection.addPaletteEntry(Type.VAR_INT.read(buffer)); } else { Type.VAR_INT.read(buffer); } @@ -72,19 +71,17 @@ public class ChunkSectionType1_9 extends Type { @Override public void write(ByteBuf buffer, ChunkSection chunkSection) throws Exception { - BiMap palette = chunkSection.getPalette(); - int bitsPerBlock = 4; - while (palette.size() > 1 << bitsPerBlock) { + while (chunkSection.getPaletteSize() > 1 << bitsPerBlock) { bitsPerBlock += 1; } long maxEntryValue = (1L << bitsPerBlock) - 1; buffer.writeByte(bitsPerBlock); // Write pallet - Type.VAR_INT.write(buffer, palette.size()); - for (int i = 0; i < palette.size(); i++) { - Type.VAR_INT.write(buffer, palette.inverse().get(i)); + Type.VAR_INT.write(buffer, chunkSection.getPaletteSize()); + for (int i = 0; i < chunkSection.getPaletteSize(); i++) { + Type.VAR_INT.write(buffer, chunkSection.getPaletteEntry(i)); } int length = (int) Math.ceil(ChunkSection.SIZE * bitsPerBlock / 64.0);