From cf2adab7281b25bbeadfe5c99205077f429f0878 Mon Sep 17 00:00:00 2001 From: KennyTV Date: Thu, 20 May 2021 18:32:28 +0200 Subject: [PATCH] Make ChunkSection an interface, don't allocate light arrays if not needed --- .../api/minecraft/chunks/ChunkSection.java | 283 ++++-------------- .../minecraft/chunks/ChunkSectionImpl.java | 166 ++++++++++ .../minecraft/chunks/ChunkSectionLight.java | 83 +++++ .../chunks/ChunkSectionLightImpl.java | 113 +++++++ .../types/version/ChunkSectionType1_13.java | 5 +- .../types/version/ChunkSectionType1_16.java | 5 +- .../types/version/ChunkSectionType1_8.java | 5 +- .../types/version/ChunkSectionType1_9.java | 3 +- .../Protocol1_12To1_11_1.java | 2 +- .../types/Chunk1_13Type.java | 10 +- .../packets/WorldPackets.java | 34 ++- .../types/Chunk1_9_3_4Type.java | 10 +- .../Protocol1_9_3To1_9_1_2.java | 2 +- .../types/Chunk1_9_1_2Type.java | 10 +- .../types/Chunk1_9to1_8Type.java | 15 +- 15 files changed, 479 insertions(+), 267 deletions(-) create mode 100644 api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/ChunkSectionImpl.java create mode 100644 api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/ChunkSectionLight.java create mode 100644 api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/ChunkSectionLightImpl.java diff --git a/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/ChunkSection.java b/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/ChunkSection.java index 06b5cdd0c..1b45d5127 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/ChunkSection.java +++ b/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/ChunkSection.java @@ -22,46 +22,50 @@ */ package com.viaversion.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.checkerframework.checker.nullness.qual.Nullable; -public class ChunkSection { +public interface ChunkSection { /** * Size (dimensions) of blocks in a chunks section. */ - public static final int SIZE = 16 * 16 * 16; // width * depth * height - /** - * 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 IntList palette; - private final Int2IntMap inversePalette; - private final int[] blocks; - private NibbleArray blockLight; - private NibbleArray skyLight; - private int nonAirBlocksCount; + int SIZE = 16 * 16 * 16; // width * depth * height - public ChunkSection() { - this.blocks = new int[SIZE]; - this.blockLight = new NibbleArray(SIZE); - palette = new IntArrayList(); - inversePalette = new Int2IntOpenHashMap(); - inversePalette.defaultReturnValue(-1); + /** + * Returns the block index of the given coordinates within a section. + * + * @param x section x + * @param y section y + * @param z section z + * @return section block index + */ + static int index(int x, int y, int z) { + return y << 8 | z << 4 | x; } - public ChunkSection(int expectedPaletteLength) { - this.blocks = new int[SIZE]; - this.blockLight = new NibbleArray(SIZE); + int getFlatBlock(int idx); - // Pre-size the palette array/map - palette = new IntArrayList(expectedPaletteLength); - inversePalette = new Int2IntOpenHashMap(expectedPaletteLength); - inversePalette.defaultReturnValue(-1); + int getFlatBlock(int x, int y, int z); + + /** + * Set a block state in the chunk + * This method will not update non-air blocks count + * + * @param idx Index + * @param id The raw or flat id of the block + */ + void setFlatBlock(int idx, int id); + + default void setFlatBlock(int x, int y, int z, int type) { + setFlatBlock(index(x, y, z), type); + } + + default int getBlockWithoutData(int x, int y, int z) { + return getFlatBlock(x, y, z) >> 4; + } + + default int getBlockData(int x, int y, int z) { + return getFlatBlock(x, y, z) & 0xF; } /** @@ -74,206 +78,39 @@ public class ChunkSection { * @param type The type of the block * @param data The data value of the block */ - public void setBlock(int x, int y, int z, int type, int data) { + default void setBlockWithData(int x, int y, int z, int type, int data) { setFlatBlock(index(x, y, z), type << 4 | (data & 0xF)); } - public void setFlatBlock(int x, int y, int z, int type) { - setFlatBlock(index(x, y, z), type); - } - - public int getBlockId(int x, int y, int z) { - return getFlatBlock(x, y, z) >> 4; - } - - public int getBlockData(int x, int y, int z) { - return getFlatBlock(x, y, z) & 0xF; - } - - public int getFlatBlock(int x, int y, int z) { - int index = blocks[index(x, y, z)]; - return palette.getInt(index); - } - - public int getFlatBlock(int idx) { - int index = blocks[idx]; - return palette.getInt(index); - } - - public void setBlock(int idx, int type, int data) { + default void setBlockWithData(int idx, int type, int data) { setFlatBlock(idx, type << 4 | (data & 0xF)); } - public void setPaletteIndex(int idx, int index) { - blocks[idx] = index; + void setPaletteIndex(int idx, int index); + + int getPaletteIndex(int idx); + + int getPaletteSize(); + + int getPaletteEntry(int index); + + void setPaletteEntry(int index, int id); + + void replacePaletteEntry(int oldId, int newId); + + void addPaletteEntry(int id); + + void clearPalette(); + + int getNonAirBlocksCount(); + + void setNonAirBlocksCount(int nonAirBlocksCount); + + default boolean hasLight() { + return getLight() != null; } - public int getPaletteIndex(int idx) { - return blocks[idx]; - } + @Nullable ChunkSectionLight getLight(); - public int getPaletteSize() { - return palette.size(); - } - - public int getPaletteEntry(int index) { - return palette.getInt(index); - } - - public void setPaletteEntry(int index, int id) { - 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.getInt(i) == oldId) { - inversePalette.put(oldId, i); - break; - } - } - } - } - - public void replacePaletteEntry(int oldId, int newId) { - int index = inversePalette.remove(oldId); - if (index == -1) return; - - inversePalette.put(newId, index); - for (int i = 0; i < palette.size(); i++) { - if (palette.getInt(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(); - } - - /** - * Set a block state in the chunk - * This method will not update non-air blocks count - * - * @param idx Index - * @param id The raw or flat id of the block - */ - public void setFlatBlock(int idx, int id) { - int index = inversePalette.get(id); - if (index == -1) { - index = palette.size(); - palette.add(id); - inversePalette.put(id, index); - } - - blocks[idx] = index; - } - - /** - * Set the block light array - * - * @param data The value to set the block light to - */ - public void setBlockLight(byte @Nullable [] data) { - if (data.length != LIGHT_LENGTH) throw new IllegalArgumentException("Data length != " + LIGHT_LENGTH); - if (this.blockLight == null) { - this.blockLight = new NibbleArray(data); - } else { - this.blockLight.setHandle(data); - } - } - - /** - * Set the sky light array - * - * @param data The value to set the sky light to - */ - public void setSkyLight(byte @Nullable [] data) { - if (data.length != LIGHT_LENGTH) throw new IllegalArgumentException("Data length != " + LIGHT_LENGTH); - if (this.skyLight == null) { - this.skyLight = new NibbleArray(data); - } else { - this.skyLight.setHandle(data); - } - } - - public byte @Nullable [] getBlockLight() { - return blockLight == null ? null : blockLight.getHandle(); - } - - public @Nullable NibbleArray getBlockLightNibbleArray() { - return blockLight; - } - - public byte @Nullable [] getSkyLight() { - return skyLight == null ? null : skyLight.getHandle(); - } - - public @Nullable NibbleArray getSkyLightNibbleArray() { - return skyLight; - } - - public void readBlockLight(ByteBuf input) { - if (this.blockLight == null) { - this.blockLight = new NibbleArray(LIGHT_LENGTH * 2); - } - input.readBytes(this.blockLight.getHandle()); - } - - public void readSkyLight(ByteBuf input) { - if (this.skyLight == null) { - this.skyLight = new NibbleArray(LIGHT_LENGTH * 2); - } - input.readBytes(this.skyLight.getHandle()); - } - - public static int index(int x, int y, int z) { - return y << 8 | z << 4 | x; - } - - /** - * Write the block light to a buffer - * - * @param output The buffer to write to - */ - public void writeBlockLight(ByteBuf output) { - output.writeBytes(blockLight.getHandle()); - } - - /** - * Write the sky light to a buffer - * - * @param output The buffer to write to - */ - public void writeSkyLight(ByteBuf output) { - output.writeBytes(skyLight.getHandle()); - } - - /** - * Check if sky light is present - * - * @return True if skylight is present - */ - public boolean hasSkyLight() { - return skyLight != null; - } - - public boolean hasBlockLight() { - return blockLight != null; - } - - public int getNonAirBlocksCount() { - return nonAirBlocksCount; - } - - public void setNonAirBlocksCount(int nonAirBlocksCount) { - this.nonAirBlocksCount = nonAirBlocksCount; - } + void setLight(@Nullable ChunkSectionLight light); } diff --git a/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/ChunkSectionImpl.java b/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/ChunkSectionImpl.java new file mode 100644 index 000000000..8ad086cf4 --- /dev/null +++ b/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/ChunkSectionImpl.java @@ -0,0 +1,166 @@ +/* + * This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion + * Copyright (C) 2016-2021 ViaVersion and contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.viaversion.viaversion.api.minecraft.chunks; + +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.checkerframework.checker.nullness.qual.Nullable; + +public class ChunkSectionImpl implements ChunkSection { + + private final IntList palette; + private final Int2IntMap inversePalette; + private final int[] blocks; + private ChunkSectionLight light; + private int nonAirBlocksCount; + + public ChunkSectionImpl(boolean holdsLight) { + this.blocks = new int[SIZE]; + palette = new IntArrayList(); + inversePalette = new Int2IntOpenHashMap(); + inversePalette.defaultReturnValue(-1); + if (holdsLight) { + this.light = new ChunkSectionLightImpl(); + } + } + + public ChunkSectionImpl(boolean holdsLight, int expectedPaletteLength) { + this.blocks = new int[SIZE]; + if (holdsLight) { + this.light = new ChunkSectionLightImpl(); + } + + // Pre-size the palette array/map + palette = new IntArrayList(expectedPaletteLength); + inversePalette = new Int2IntOpenHashMap(expectedPaletteLength); + inversePalette.defaultReturnValue(-1); + } + + @Override + public int getFlatBlock(int idx) { + int index = blocks[idx]; + return palette.getInt(index); + } + + @Override + public int getFlatBlock(int x, int y, int z) { + int index = blocks[ChunkSection.index(x, y, z)]; + return palette.getInt(index); + } + + @Override + public void setFlatBlock(int idx, int id) { + int index = inversePalette.get(id); + if (index == -1) { + index = palette.size(); + palette.add(id); + inversePalette.put(id, index); + } + + blocks[idx] = index; + } + + @Override + public int getPaletteIndex(int idx) { + return blocks[idx]; + } + + @Override + public void setPaletteIndex(int idx, int index) { + blocks[idx] = index; + } + + @Override + public int getPaletteSize() { + return palette.size(); + } + + @Override + public int getPaletteEntry(int index) { + return palette.getInt(index); + } + + @Override + public void setPaletteEntry(int index, int id) { + 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.getInt(i) == oldId) { + inversePalette.put(oldId, i); + break; + } + } + } + } + + @Override + public void replacePaletteEntry(int oldId, int newId) { + int index = inversePalette.remove(oldId); + if (index == -1) return; + + inversePalette.put(newId, index); + for (int i = 0; i < palette.size(); i++) { + if (palette.getInt(i) == oldId) { + palette.set(i, newId); + } + } + } + + @Override + public void addPaletteEntry(int id) { + inversePalette.put(id, palette.size()); + palette.add(id); + } + + @Override + public void clearPalette() { + palette.clear(); + inversePalette.clear(); + } + + @Override + public int getNonAirBlocksCount() { + return nonAirBlocksCount; + } + + @Override + public void setNonAirBlocksCount(int nonAirBlocksCount) { + this.nonAirBlocksCount = nonAirBlocksCount; + } + + @Override + public @Nullable ChunkSectionLight getLight() { + return light; + } + + @Override + public void setLight(@Nullable ChunkSectionLight light) { + this.light = light; + } +} diff --git a/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/ChunkSectionLight.java b/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/ChunkSectionLight.java new file mode 100644 index 000000000..87891d79c --- /dev/null +++ b/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/ChunkSectionLight.java @@ -0,0 +1,83 @@ +/* + * This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion + * Copyright (C) 2016-2021 ViaVersion and contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.viaversion.viaversion.api.minecraft.chunks; + +import io.netty.buffer.ByteBuf; +import org.checkerframework.checker.nullness.qual.Nullable; + +public interface ChunkSectionLight { + + /** + * Length of the sky and block light nibble arrays. + */ + int LIGHT_LENGTH = 16 * 16 * 16 / 2; // Dimensions / 2 (nibble bit count) + + /** + * Check if sky light is present + * + * @return True if skylight is present + */ + boolean hasSkyLight(); + + boolean hasBlockLight(); + + byte @Nullable [] getSkyLight(); + + byte @Nullable [] getBlockLight(); + + /** + * Set the sky light array + * + * @param data The value to set the sky light to + */ + void setSkyLight(byte[] data); + + /** + * Set the block light array + * + * @param data The value to set the block light to + */ + void setBlockLight(byte[] data); + + @Nullable NibbleArray getBlockLightNibbleArray(); + + @Nullable NibbleArray getSkyLightNibbleArray(); + + void readSkyLight(ByteBuf input); + + void readBlockLight(ByteBuf input); + + /** + * Write the sky light to a buffer. + * + * @param output The buffer to write to + */ + void writeSkyLight(ByteBuf output); + + /** + * Write the block light to a buffer. + * + * @param output The buffer to write to + */ + void writeBlockLight(ByteBuf output); +} diff --git a/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/ChunkSectionLightImpl.java b/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/ChunkSectionLightImpl.java new file mode 100644 index 000000000..8fa5b6527 --- /dev/null +++ b/api/src/main/java/com/viaversion/viaversion/api/minecraft/chunks/ChunkSectionLightImpl.java @@ -0,0 +1,113 @@ +/* + * This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion + * Copyright (C) 2016-2021 ViaVersion and contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.viaversion.viaversion.api.minecraft.chunks; + +import io.netty.buffer.ByteBuf; +import org.checkerframework.checker.nullness.qual.Nullable; + +public class ChunkSectionLightImpl implements ChunkSectionLight { + + private NibbleArray blockLight; + private NibbleArray skyLight; + + public ChunkSectionLightImpl() { + // Block light is always written + this.blockLight = new NibbleArray(ChunkSection.SIZE); + } + + @Override + public void setBlockLight(byte[] data) { + if (data.length != LIGHT_LENGTH) throw new IllegalArgumentException("Data length != " + LIGHT_LENGTH); + if (this.blockLight == null) { + this.blockLight = new NibbleArray(data); + } else { + this.blockLight.setHandle(data); + } + } + + @Override + public void setSkyLight(byte[] data) { + if (data.length != LIGHT_LENGTH) throw new IllegalArgumentException("Data length != " + LIGHT_LENGTH); + if (this.skyLight == null) { + this.skyLight = new NibbleArray(data); + } else { + this.skyLight.setHandle(data); + } + } + + @Override + public byte @Nullable [] getBlockLight() { + return blockLight == null ? null : blockLight.getHandle(); + } + + @Override + public @Nullable NibbleArray getBlockLightNibbleArray() { + return blockLight; + } + + @Override + public byte @Nullable [] getSkyLight() { + return skyLight == null ? null : skyLight.getHandle(); + } + + @Override + public @Nullable NibbleArray getSkyLightNibbleArray() { + return skyLight; + } + + @Override + public void readBlockLight(ByteBuf input) { + if (this.blockLight == null) { + this.blockLight = new NibbleArray(LIGHT_LENGTH * 2); + } + input.readBytes(this.blockLight.getHandle()); + } + + @Override + public void readSkyLight(ByteBuf input) { + if (this.skyLight == null) { + this.skyLight = new NibbleArray(LIGHT_LENGTH * 2); + } + input.readBytes(this.skyLight.getHandle()); + } + + @Override + public void writeBlockLight(ByteBuf output) { + output.writeBytes(blockLight.getHandle()); + } + + @Override + public void writeSkyLight(ByteBuf output) { + output.writeBytes(skyLight.getHandle()); + } + + @Override + public boolean hasSkyLight() { + return skyLight != null; + } + + @Override + public boolean hasBlockLight() { + return blockLight != null; + } +} diff --git a/api/src/main/java/com/viaversion/viaversion/api/type/types/version/ChunkSectionType1_13.java b/api/src/main/java/com/viaversion/viaversion/api/type/types/version/ChunkSectionType1_13.java index b105daf4a..2d33fca8b 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/type/types/version/ChunkSectionType1_13.java +++ b/api/src/main/java/com/viaversion/viaversion/api/type/types/version/ChunkSectionType1_13.java @@ -23,6 +23,7 @@ package com.viaversion.viaversion.api.type.types.version; import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection; +import com.viaversion.viaversion.api.minecraft.chunks.ChunkSectionImpl; import com.viaversion.viaversion.api.type.Type; import com.viaversion.viaversion.util.CompactArrayUtil; import io.netty.buffer.ByteBuf; @@ -48,12 +49,12 @@ public class ChunkSectionType1_13 extends Type { ChunkSection chunkSection; if (bitsPerBlock != GLOBAL_PALETTE) { int paletteLength = Type.VAR_INT.readPrimitive(buffer); - chunkSection = new ChunkSection(paletteLength); + chunkSection = new ChunkSectionImpl(true, paletteLength); for (int i = 0; i < paletteLength; i++) { chunkSection.addPaletteEntry(Type.VAR_INT.readPrimitive(buffer)); } } else { - chunkSection = new ChunkSection(); + chunkSection = new ChunkSectionImpl(true); } // Read blocks diff --git a/api/src/main/java/com/viaversion/viaversion/api/type/types/version/ChunkSectionType1_16.java b/api/src/main/java/com/viaversion/viaversion/api/type/types/version/ChunkSectionType1_16.java index 1454eef7a..084ff51fa 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/type/types/version/ChunkSectionType1_16.java +++ b/api/src/main/java/com/viaversion/viaversion/api/type/types/version/ChunkSectionType1_16.java @@ -23,6 +23,7 @@ package com.viaversion.viaversion.api.type.types.version; import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection; +import com.viaversion.viaversion.api.minecraft.chunks.ChunkSectionImpl; import com.viaversion.viaversion.api.type.Type; import com.viaversion.viaversion.util.CompactArrayUtil; import io.netty.buffer.ByteBuf; @@ -48,12 +49,12 @@ public class ChunkSectionType1_16 extends Type { ChunkSection chunkSection; if (bitsPerBlock != GLOBAL_PALETTE) { int paletteLength = Type.VAR_INT.readPrimitive(buffer); - chunkSection = new ChunkSection(paletteLength); + chunkSection = new ChunkSectionImpl(false, paletteLength); for (int i = 0; i < paletteLength; i++) { chunkSection.addPaletteEntry(Type.VAR_INT.readPrimitive(buffer)); } } else { - chunkSection = new ChunkSection(); + chunkSection = new ChunkSectionImpl(false); } // Read blocks diff --git a/api/src/main/java/com/viaversion/viaversion/api/type/types/version/ChunkSectionType1_8.java b/api/src/main/java/com/viaversion/viaversion/api/type/types/version/ChunkSectionType1_8.java index d869ad903..b5c7fde67 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/type/types/version/ChunkSectionType1_8.java +++ b/api/src/main/java/com/viaversion/viaversion/api/type/types/version/ChunkSectionType1_8.java @@ -23,6 +23,7 @@ package com.viaversion.viaversion.api.type.types.version; import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection; +import com.viaversion.viaversion.api.minecraft.chunks.ChunkSectionImpl; import com.viaversion.viaversion.api.type.Type; import io.netty.buffer.ByteBuf; @@ -36,7 +37,7 @@ public class ChunkSectionType1_8 extends Type { @Override public ChunkSection read(ByteBuf buffer) throws Exception { - ChunkSection chunkSection = new ChunkSection(); + ChunkSection chunkSection = new ChunkSectionImpl(true); // 0 index needs to be air in 1.9 chunkSection.addPaletteEntry(0); @@ -46,7 +47,7 @@ public class ChunkSectionType1_8 extends Type { int mask = littleEndianView.readShort(); int type = mask >> 4; int data = mask & 0xF; - chunkSection.setBlock(i, type, data); + chunkSection.setBlockWithData(i, type, data); } return chunkSection; diff --git a/api/src/main/java/com/viaversion/viaversion/api/type/types/version/ChunkSectionType1_9.java b/api/src/main/java/com/viaversion/viaversion/api/type/types/version/ChunkSectionType1_9.java index cacfd3257..3c98ad340 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/type/types/version/ChunkSectionType1_9.java +++ b/api/src/main/java/com/viaversion/viaversion/api/type/types/version/ChunkSectionType1_9.java @@ -23,6 +23,7 @@ package com.viaversion.viaversion.api.type.types.version; import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection; +import com.viaversion.viaversion.api.minecraft.chunks.ChunkSectionImpl; import com.viaversion.viaversion.api.type.Type; import com.viaversion.viaversion.util.CompactArrayUtil; import io.netty.buffer.ByteBuf; @@ -52,7 +53,7 @@ public class ChunkSectionType1_9 extends Type { // Read palette int paletteLength = Type.VAR_INT.readPrimitive(buffer); - ChunkSection chunkSection = bitsPerBlock != GLOBAL_PALETTE ? new ChunkSection(paletteLength) : new ChunkSection(); + ChunkSection chunkSection = bitsPerBlock != GLOBAL_PALETTE ? new ChunkSectionImpl(true, paletteLength) : new ChunkSectionImpl(true); for (int i = 0; i < paletteLength; i++) { if (bitsPerBlock != GLOBAL_PALETTE) { chunkSection.addPaletteEntry(Type.VAR_INT.readPrimitive(buffer)); diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_12to1_11_1/Protocol1_12To1_11_1.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_12to1_11_1/Protocol1_12To1_11_1.java index 47f833b70..e268e0851 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_12to1_11_1/Protocol1_12To1_11_1.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_12to1_11_1/Protocol1_12To1_11_1.java @@ -129,7 +129,7 @@ public class Protocol1_12To1_11_1 extends AbstractProtocol { color:14, x:132, y:64, z:222, id:"minecraft:bed" } (Debug output) diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_13to1_12_2/types/Chunk1_13Type.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_13to1_12_2/types/Chunk1_13Type.java index 86294d74e..ad97cb66c 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_13to1_12_2/types/Chunk1_13Type.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_13to1_12_2/types/Chunk1_13Type.java @@ -57,9 +57,9 @@ public class Chunk1_13Type extends PartialType { ChunkSection section = Types1_13.CHUNK_SECTION.read(data); sections[i] = section; - section.readBlockLight(data); + section.getLight().readBlockLight(data); if (world.getEnvironment() == Environment.NORMAL) { - section.readSkyLight(data); + section.getLight().readSkyLight(data); } } @@ -101,10 +101,10 @@ public class Chunk1_13Type extends PartialType { ChunkSection section = chunk.getSections()[i]; if (section == null) continue; // Section not set Types1_13.CHUNK_SECTION.write(buf, section); - section.writeBlockLight(buf); + section.getLight().writeBlockLight(buf); - if (!section.hasSkyLight()) continue; // No sky light, we're done here. - section.writeSkyLight(buf); + if (!section.getLight().hasSkyLight()) continue; // No sky light, we're done here. + section.getLight().writeSkyLight(buf); } buf.readerIndex(0); diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_14to1_13_2/packets/WorldPackets.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_14to1_13_2/packets/WorldPackets.java index c8632cadd..b614d137f 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_14to1_13_2/packets/WorldPackets.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_14to1_13_2/packets/WorldPackets.java @@ -32,6 +32,7 @@ import com.viaversion.viaversion.api.protocol.remapper.ValueCreator; import com.viaversion.viaversion.api.type.Type; import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ClientboundPackets1_13; import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.types.Chunk1_13Type; +import com.viaversion.viaversion.protocols.protocol1_14to1_13_2.ClientboundPackets1_14; import com.viaversion.viaversion.protocols.protocol1_14to1_13_2.Protocol1_14To1_13_2; import com.viaversion.viaversion.protocols.protocol1_14to1_13_2.storage.EntityTracker1_14; import com.viaversion.viaversion.protocols.protocol1_14to1_13_2.types.Chunk1_14Type; @@ -198,7 +199,7 @@ public class WorldPackets { heightMap.put("WORLD_SURFACE", new LongArrayTag(encodeHeightMap(worldSurface))); chunk.setHeightMap(heightMap); - PacketWrapper lightPacket = wrapper.create(0x24); + PacketWrapper lightPacket = wrapper.create(ClientboundPackets1_14.UPDATE_LIGHT); lightPacket.write(Type.VAR_INT, chunk.getX()); lightPacket.write(Type.VAR_INT, chunk.getZ()); @@ -207,7 +208,7 @@ public class WorldPackets { for (int i = 0; i < chunk.getSections().length; i++) { ChunkSection sec = chunk.getSections()[i]; if (sec == null) continue; - if (!chunk.isFullChunk() && sec.hasSkyLight()) { + if (!chunk.isFullChunk() && sec.getLight().hasSkyLight()) { skyLightMask |= (1 << (i + 1)); } blockLightMask |= (1 << (i + 1)); @@ -223,20 +224,20 @@ public class WorldPackets { if (chunk.isFullChunk()) lightPacket.write(Type.BYTE_ARRAY_PRIMITIVE, FULL_LIGHT); // chunk below 0 for (ChunkSection section : chunk.getSections()) { - if (section == null || !section.hasSkyLight()) { + if (section == null || !section.getLight().hasSkyLight()) { if (chunk.isFullChunk()) { lightPacket.write(Type.BYTE_ARRAY_PRIMITIVE, FULL_LIGHT); } continue; } - lightPacket.write(Type.BYTE_ARRAY_PRIMITIVE, section.getSkyLight()); + lightPacket.write(Type.BYTE_ARRAY_PRIMITIVE, section.getLight().getSkyLight()); } if (chunk.isFullChunk()) lightPacket.write(Type.BYTE_ARRAY_PRIMITIVE, FULL_LIGHT); // chunk above 255 for (ChunkSection section : chunk.getSections()) { if (section == null) continue; - lightPacket.write(Type.BYTE_ARRAY_PRIMITIVE, section.getBlockLight()); + lightPacket.write(Type.BYTE_ARRAY_PRIMITIVE, section.getLight().getBlockLight()); } EntityTracker1_14 entityTracker = wrapper.user().get(EntityTracker1_14.class); @@ -254,6 +255,13 @@ public class WorldPackets { } lightPacket.send(Protocol1_14To1_13_2.class, true, true); + + // Remove light references from chunk sections + for (ChunkSection section : chunk.getSections()) { + if (section != null) { + section.setLight(null); + } + } } private Byte[] fromPrimitiveArray(byte[] bytes) { @@ -390,8 +398,8 @@ public class WorldPackets { int skyLight = 0; int blockLight = 0; for (BlockFace blockFace : BlockFace.values()) { - NibbleArray skyLightArray = section.getSkyLightNibbleArray(); - NibbleArray blockLightArray = section.getBlockLightNibbleArray(); + NibbleArray skyLightArray = section.getLight().getSkyLightNibbleArray(); + NibbleArray blockLightArray = section.getLight().getBlockLightNibbleArray(); int neighbourX = x + blockFace.getModX(); int neighbourY = y + blockFace.getModY(); int neighbourZ = z + blockFace.getModZ(); @@ -414,8 +422,8 @@ public class WorldPackets { ChunkSection newSection = chunk.getSections()[ySection]; if (newSection == null) continue; - skyLightArray = newSection.getSkyLightNibbleArray(); - blockLightArray = newSection.getBlockLightNibbleArray(); + skyLightArray = newSection.getLight().getSkyLightNibbleArray(); + blockLightArray = newSection.getLight().getBlockLightNibbleArray(); } } else if (blockFace.getModZ() != 0) { // Another chunk, nothing we can do without an unnecessary amount of caching @@ -447,15 +455,15 @@ public class WorldPackets { } if (skyLight != 0) { - if (!section.hasSkyLight()) { + if (!section.getLight().hasSkyLight()) { byte[] newSkyLight = new byte[2028]; - section.setSkyLight(newSkyLight); + section.getLight().setSkyLight(newSkyLight); } - section.getSkyLightNibbleArray().set(x, y, z, skyLight); + section.getLight().getSkyLightNibbleArray().set(x, y, z, skyLight); } if (blockLight != 0) { - section.getBlockLightNibbleArray().set(x, y, z, blockLight); + section.getLight().getBlockLightNibbleArray().set(x, y, z, blockLight); } } diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_9_1_2to1_9_3_4/types/Chunk1_9_3_4Type.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_9_1_2to1_9_3_4/types/Chunk1_9_3_4Type.java index 0932401f2..8ad45ed53 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_9_1_2to1_9_3_4/types/Chunk1_9_3_4Type.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_9_1_2to1_9_3_4/types/Chunk1_9_3_4Type.java @@ -56,9 +56,9 @@ public class Chunk1_9_3_4Type extends PartialType { ChunkSection section = Types1_9.CHUNK_SECTION.read(input); sections[i] = section; - section.readBlockLight(input); + section.getLight().readBlockLight(input); if (world.getEnvironment() == Environment.NORMAL) { - section.readSkyLight(input); + section.getLight().readSkyLight(input); } } @@ -96,10 +96,10 @@ public class Chunk1_9_3_4Type extends PartialType { ChunkSection section = chunk.getSections()[i]; if (section == null) continue; // Section not set Types1_9.CHUNK_SECTION.write(buf, section); - section.writeBlockLight(buf); + section.getLight().writeBlockLight(buf); - if (!section.hasSkyLight()) continue; // No sky light, we're done here. - section.writeSkyLight(buf); + if (!section.getLight().hasSkyLight()) continue; // No sky light, we're done here. + section.getLight().writeSkyLight(buf); } buf.readerIndex(0); Type.VAR_INT.writePrimitive(output, buf.readableBytes() + (chunk.isBiomeData() ? 256 : 0)); diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_9_3to1_9_1_2/Protocol1_9_3To1_9_1_2.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_9_3to1_9_1_2/Protocol1_9_3To1_9_1_2.java index 1acfd2187..6e9560a8a 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_9_3to1_9_1_2/Protocol1_9_3To1_9_1_2.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_9_3to1_9_1_2/Protocol1_9_3To1_9_1_2.java @@ -111,7 +111,7 @@ public class Protocol1_9_3To1_9_1_2 extends AbstractProtocol { if (!usedSections.get(i)) continue; // Section not set ChunkSection section = Types1_9.CHUNK_SECTION.read(input); sections[i] = section; - section.readBlockLight(input); + section.getLight().readBlockLight(input); if (world.getEnvironment() == Environment.NORMAL) { - section.readSkyLight(input); + section.getLight().readSkyLight(input); } if (replacePistons) { section.replacePaletteEntry(36, replacementId); @@ -100,10 +100,10 @@ public class Chunk1_9_1_2Type extends PartialType { ChunkSection section = chunk.getSections()[i]; if (section == null) continue; // Section not set Types1_9.CHUNK_SECTION.write(buf, section); - section.writeBlockLight(buf); + section.getLight().writeBlockLight(buf); - if (!section.hasSkyLight()) continue; // No sky light, we're done here. - section.writeSkyLight(buf); + if (!section.getLight().hasSkyLight()) continue; // No sky light, we're done here. + section.getLight().writeSkyLight(buf); } buf.readerIndex(0); diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_9to1_8/types/Chunk1_9to1_8Type.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_9to1_8/types/Chunk1_9to1_8Type.java index 519120727..3245d84ab 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_9to1_8/types/Chunk1_9to1_8Type.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_9to1_8/types/Chunk1_9to1_8Type.java @@ -22,6 +22,7 @@ import com.viaversion.viaversion.api.Via; import com.viaversion.viaversion.api.minecraft.chunks.Chunk; import com.viaversion.viaversion.api.minecraft.chunks.Chunk1_8; import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection; +import com.viaversion.viaversion.api.minecraft.chunks.ChunkSectionLight; import com.viaversion.viaversion.api.type.PartialType; import com.viaversion.viaversion.api.type.Type; import com.viaversion.viaversion.api.type.types.minecraft.BaseChunkType; @@ -113,16 +114,16 @@ public class Chunk1_9to1_8Type extends PartialType { // Read block light for (int i = 0; i < SECTION_COUNT; i++) { if (!usedSections.get(i)) continue; // Section not set, has no light - sections[i].readBlockLight(input); + sections[i].getLight().readBlockLight(input); } // Read sky light int bytesLeft = dataLength - (input.readerIndex() - startIndex); - if (bytesLeft >= ChunkSection.LIGHT_LENGTH) { + if (bytesLeft >= ChunkSectionLight.LIGHT_LENGTH) { for (int i = 0; i < SECTION_COUNT; i++) { if (!usedSections.get(i)) continue; // Section not set, has no light - sections[i].readSkyLight(input); - bytesLeft -= ChunkSection.LIGHT_LENGTH; + sections[i].getLight().readSkyLight(input); + bytesLeft -= ChunkSectionLight.LIGHT_LENGTH; } } @@ -162,10 +163,10 @@ public class Chunk1_9to1_8Type extends PartialType { ChunkSection section = chunk.getSections()[i]; if (section == null) continue; // Section not set Types1_9.CHUNK_SECTION.write(buf, section); - section.writeBlockLight(buf); + section.getLight().writeBlockLight(buf); - if (!section.hasSkyLight()) continue; // No sky light, we're done here. - section.writeSkyLight(buf); + if (!section.getLight().hasSkyLight()) continue; // No sky light, we're done here. + section.getLight().writeSkyLight(buf); } buf.readerIndex(0); Type.VAR_INT.writePrimitive(output, buf.readableBytes() + (chunk.hasBiomeData() ? 256 : 0));