From b34778952a4db1e324c09c57349a6d1237aeec9c Mon Sep 17 00:00:00 2001 From: James Seibel Date: Fri, 30 Sep 2022 21:21:26 -0500 Subject: [PATCH] rename FullFormat -> FullDataPoint and IdBiomeBlockStateMap -> FullDataPointIdMap Also refactor FullDataPointIdMap --- .../core/datatype/full/ChunkSizedData.java | 2 +- .../{FullFormat.java => FullDataPoint.java} | 89 ++++++----- .../datatype/full/FullDataPointIdMap.java | 150 ++++++++++++++++++ .../core/datatype/full/FullDataSource.java | 6 +- .../datatype/full/IdBiomeBlockStateMap.java | 131 --------------- .../core/datatype/full/SparseDataSource.java | 10 +- .../datatype/full/accessor/FullArrayView.java | 18 ++- .../datatype/full/accessor/IFullDataView.java | 4 +- .../full/accessor/SingleFullArrayView.java | 18 +-- .../transform/FullToColumnTransformer.java | 15 +- .../datatype/transform/LodDataBuilder.java | 6 +- 11 files changed, 237 insertions(+), 212 deletions(-) rename core/src/main/java/com/seibel/lod/core/datatype/full/{FullFormat.java => FullDataPoint.java} (58%) create mode 100644 core/src/main/java/com/seibel/lod/core/datatype/full/FullDataPointIdMap.java delete mode 100644 core/src/main/java/com/seibel/lod/core/datatype/full/IdBiomeBlockStateMap.java diff --git a/core/src/main/java/com/seibel/lod/core/datatype/full/ChunkSizedData.java b/core/src/main/java/com/seibel/lod/core/datatype/full/ChunkSizedData.java index 85badb245..586d9f5de 100644 --- a/core/src/main/java/com/seibel/lod/core/datatype/full/ChunkSizedData.java +++ b/core/src/main/java/com/seibel/lod/core/datatype/full/ChunkSizedData.java @@ -11,7 +11,7 @@ public class ChunkSizedData extends FullArrayView public ChunkSizedData(byte dataDetail, int x, int z) { - super(new IdBiomeBlockStateMap(), new long[16 * 16][0], 16); + super(new FullDataPointIdMap(), new long[16 * 16][0], 16); this.dataDetail = dataDetail; this.x = x; this.z = z; diff --git a/core/src/main/java/com/seibel/lod/core/datatype/full/FullFormat.java b/core/src/main/java/com/seibel/lod/core/datatype/full/FullDataPoint.java similarity index 58% rename from core/src/main/java/com/seibel/lod/core/datatype/full/FullFormat.java rename to core/src/main/java/com/seibel/lod/core/datatype/full/FullDataPoint.java index 7a82c4f7d..120fb2936 100644 --- a/core/src/main/java/com/seibel/lod/core/datatype/full/FullFormat.java +++ b/core/src/main/java/com/seibel/lod/core/datatype/full/FullDataPoint.java @@ -1,25 +1,38 @@ package com.seibel.lod.core.datatype.full; -// Static class for the data format: -// ID: blockState id Y: Height(signed) DP: Depth(signed?) (Depth means the length of the block!) -// BL: Block light SL: Sky light -// =======Bit layout======= -// BL BL BL BL SL SL SL SL <-- Top bits -// YY YY YY YY YY YY YY YY -// YY YY YY YY DP DP DP DP -// DP DP DP DP DP DP DP DP -// ID ID ID ID ID ID IO ID -// ID ID ID ID ID ID IO ID -// ID ID ID ID ID ID IO ID -// ID ID ID ID ID ID IO ID <-- Bottom bits +// import com.seibel.lod.core.util.LodUtil; import org.jetbrains.annotations.Contract; import static com.seibel.lod.core.datatype.column.accessor.ColumnFormat.MAX_WORLD_Y_SIZE; -public class FullFormat { - +/** + * + * Static class used to format the full binary Distant Horizons data format.
+ * Contains all the data we save. + * + *

+ * ID: blockState id
+ * Y: Height(signed)
+ * DP: Depth(signed?) (Depth means the length of the block!)
+ * BL: Block light
+ * SL: Sky light

+ * + * =======Bit layout=======
+ * BL BL BL BL SL SL SL SL <-- Top bits
+ * YY YY YY YY YY YY YY YY
+ * YY YY YY YY DP DP DP DP
+ * DP DP DP DP DP DP DP DP
+ * ID ID ID ID ID ID IO ID
+ * ID ID ID ID ID ID IO ID
+ * ID ID ID ID ID ID IO ID
+ * ID ID ID ID ID ID IO ID <-- Bottom bits
+ *
+ * + */ +public class FullDataPoint +{ public static final int ID_WIDTH = 32; public static final int DP_WIDTH = 12; public static final int Y_WIDTH = 12; @@ -28,18 +41,22 @@ public class FullFormat { public static final int DP_OFFSET = ID_OFFSET + ID_WIDTH; public static final int Y_OFFSET = DP_OFFSET + DP_WIDTH; public static final int LIGHT_OFFSET = Y_OFFSET + Y_WIDTH; - - + + public static final long ID_MASK = Integer.MAX_VALUE; public static final long INVERSE_ID_MASK = ~ID_MASK; public static final int DP_MASK = (int)Math.pow(2, DP_WIDTH) - 1; public static final int Y_MASK = (int)Math.pow(2, Y_WIDTH) - 1; public static final int LIGHT_MASK = (int)Math.pow(2, LIGHT_WIDTH) - 1; - - public static long encode(int id, int depth, int y, byte lightPair) { + + + /** creates a new datapoint with the given values */ + public static long encode(int id, int depth, int y, byte lightPair) + { LodUtil.assertTrue(y >= 0 && y < MAX_WORLD_Y_SIZE, "Trying to create datapoint with y[{}] out of range!", y); LodUtil.assertTrue(depth > 0 && depth < MAX_WORLD_Y_SIZE, "Trying to create datapoint with depth[{}] out of range!", depth); LodUtil.assertTrue(y+depth <= MAX_WORLD_Y_SIZE, "Trying to create datapoint with y+depth[{}] out of range!", y+depth); + long data = 0; data |= id & ID_MASK; data |= (long) (depth & DP_MASK) << DP_OFFSET; @@ -48,31 +65,19 @@ public class FullFormat { LodUtil.assertTrue(getId(data) == id && getDepth(data) == depth && getY(data) == y && getLight(data) == Byte.toUnsignedInt(lightPair), "Trying to create datapoint with id[{}], depth[{}], y[{}], lightPair[{}] but got id[{}], depth[{}], y[{}], lightPair[{}]!", id, depth, y, Byte.toUnsignedInt(lightPair), getId(data), getDepth(data), getY(data), getLight(data)); + return data; } - - public static int getId(long data) { - return (int) (data & ID_MASK); - } - - public static int getDepth(long data) { - return (int) ((data >> DP_OFFSET) & DP_MASK); - } - - public static int getY(long data) { - return (int) ((data >> Y_OFFSET) & Y_MASK); - } - - public static int getLight(long data) { - return (int) ((data >> LIGHT_OFFSET) & LIGHT_MASK); - } - - public static String toString(long data) { - return "[ID:" + getId(data) + ",Y:" + getY(data) + ",Depth:" + getY(data) + ",Light:" + getLight(data) + "]"; - } - + + public static int getId(long data) { return (int) (data & ID_MASK); } + public static int getDepth(long data) { return (int) ((data >> DP_OFFSET) & DP_MASK); } + public static int getY(long data) { return (int) ((data >> Y_OFFSET) & Y_MASK); } + public static int getLight(long data) { return (int) ((data >> LIGHT_OFFSET) & LIGHT_MASK); } + + public static String toString(long data) { return "[ID:" + getId(data) + ",Y:" + getY(data) + ",Depth:" + getY(data) + ",Light:" + getLight(data) + "]"; } + + /** Remaps the biome/blockState ID of the given datapoint */ @Contract(pure = true) - public static long remap(int[] mapping, long data) { - return (data & INVERSE_ID_MASK) | mapping[(int)data]; - } + public static long remap(int[] newIdMapping, long data) { return (data & INVERSE_ID_MASK) | newIdMapping[(int)data]; } + } diff --git a/core/src/main/java/com/seibel/lod/core/datatype/full/FullDataPointIdMap.java b/core/src/main/java/com/seibel/lod/core/datatype/full/FullDataPointIdMap.java new file mode 100644 index 000000000..00aa84a6f --- /dev/null +++ b/core/src/main/java/com/seibel/lod/core/datatype/full/FullDataPointIdMap.java @@ -0,0 +1,150 @@ +package com.seibel.lod.core.datatype.full; + +import com.seibel.lod.core.dependencyInjection.SingletonInjector; +import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory; +import com.seibel.lod.core.wrapperInterfaces.block.IBlockStateWrapper; +import com.seibel.lod.core.wrapperInterfaces.world.IBiomeWrapper; + +import java.io.*; +import java.util.ArrayList; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; + +/** + * WARNING: This is not THREAD-SAFE! + *

+ * Used to map a numerical ID to a Biome/BlockState pair. + * + * @author Leetom + * @version 2022-9-30 + */ +public class FullDataPointIdMap +{ + final ArrayList entries = new ArrayList<>(); + final ConcurrentHashMap idMap = new ConcurrentHashMap<>(); // FIXME: Improve performance + + + + public IBiomeWrapper getBiomeWrapper(int id) { return entries.get(id).biome; } + public IBlockStateWrapper getBlockStateWrapper(int id) { return entries.get(id).blockState; } + + /** Adds a new entry to the map and returns its numerical ID */ + public int setAndGetId(IBiomeWrapper biome, IBlockStateWrapper blockState) { return setAndGetId(new Entry(biome, blockState)); } + private int setAndGetId(Entry biomeBlockStateEntry) + { + return idMap.computeIfAbsent(biomeBlockStateEntry, (entry) -> { + int id = entries.size(); + entries.add(entry); + return id; + }); + } + + + /** + * Adds each entry from the given map to this map. + * @return an array of each added entry's ID in this map in order + */ + public int[] mergeAndReturnRemappedEntityIds(FullDataPointIdMap target) + { + ArrayList entriesToMerge = target.entries; + + int[] remappedEntryIds = new int[entriesToMerge.size()]; + for (int i = 0; i < entriesToMerge.size(); i++) + { + remappedEntryIds[i] = setAndGetId(entriesToMerge.get(i)); + } + return remappedEntryIds; + } + + /** Serializes all contained entries into the given stream, formatted in UTF */ + void serialize(OutputStream outputStream) throws IOException + { + DataOutputStream dataStream = new DataOutputStream(outputStream); // DO NOT CLOSE! It would close all related streams + dataStream.writeInt(entries.size()); + for (Entry entry : entries) + { + dataStream.writeUTF(entry.serialize()); + } + } + + /** Creates a new IdBiomeBlockStateMap from the given UTF formatted stream */ + static FullDataPointIdMap deserialize(InputStream inputStream) throws IOException + { + DataInputStream dataStream = new DataInputStream(inputStream); // DO NOT CLOSE! It would close all related streams + int entityCount = dataStream.readInt(); + FullDataPointIdMap newMap = new FullDataPointIdMap(); + for (int i = 0; i < entityCount; i++) + { + newMap.entries.add(Entry.deserialize(dataStream.readUTF())); + } + return newMap; + } + + @Override + public boolean equals(Object other) + { + if (other == this) + return true; +// if (!(other instanceof IdBiomeBlockStateMap)) return false; +// IdBiomeBlockStateMap otherMap = (IdBiomeBlockStateMap) other; +// if (entries.size() != otherMap.entries.size()) return false; +// for (int i=0; i entries = new ArrayList<>(); - final ConcurrentHashMap idMap = new ConcurrentHashMap<>(); // FIXME: Improve performance - - public Entry get(int id) { return entries.get(id); } - - public int setAndGetId(IBiomeWrapper biome, IBlockStateWrapper blockState) - { - return idMap.computeIfAbsent(new Entry(biome, blockState), (e) -> { - int id = entries.size(); - entries.add(e); - return id; - }); - } - - public int setAndGetId(Entry biomeBlockStateEntry) - { - return idMap.computeIfAbsent(biomeBlockStateEntry, (e) -> { - int id = entries.size(); - entries.add(e); - return id; - }); - } - - public int[] computeAndMergeMapFrom(IdBiomeBlockStateMap target) - { - ArrayList mergeEntry = target.entries; - int[] mapper = new int[mergeEntry.size()]; - for (int i = 0; i < mergeEntry.size(); i++) - { - mapper[i] = setAndGetId(mergeEntry.get(i)); - } - return mapper; - } - - void serialize(OutputStream os) throws IOException - { - DataOutputStream dos = new DataOutputStream(os); // DO NOT CLOSE! - dos.writeInt(entries.size()); - for (Entry e : entries) - { - dos.writeUTF(e.serialize()); - } - } - - static IdBiomeBlockStateMap deserialize(InputStream is) throws IOException - { - DataInputStream dis = new DataInputStream(is); // DO NOT CLOSE! - int size = dis.readInt(); - IdBiomeBlockStateMap map = new IdBiomeBlockStateMap(); - for (int i = 0; i < size; i++) - { - map.entries.add(Entry.deserialize(dis.readUTF())); - } - return map; - } - - @Override - public boolean equals(Object other) - { - if (other == this) - return true; -// if (!(other instanceof IdBiomeBlockStateMap)) return false; -// IdBiomeBlockStateMap otherMap = (IdBiomeBlockStateMap) other; -// if (entries.size() != otherMap.entries.size()) return false; -// for (int i=0; i SPARSE_UNIT_DETAIL); LodUtil.assertTrue(sectionPos.sectionDetail <= MAX_SECTION_DETAIL); this.sectionPos = sectionPos; @@ -213,7 +213,7 @@ public class SparseDataSource implements ILodDataSource public static SparseDataSource loadData(DataMetaFile dataFile, InputStream dataStream, IDhLevel level) throws IOException { LodUtil.assertTrue(dataFile.pos.sectionDetail > SPARSE_UNIT_DETAIL); LodUtil.assertTrue(dataFile.pos.sectionDetail <= MAX_SECTION_DETAIL); - DataInputStream dos = new DataInputStream(dataStream); // DO NOT CLOSE! + DataInputStream dos = new DataInputStream(dataStream); // DO NOT CLOSE! It would close all related streams { int dataDetail = dos.readShort(); if(dataDetail != dataFile.metaData.dataLevel) @@ -271,7 +271,7 @@ public class SparseDataSource implements ILodDataSource // Id mapping end = dos.readInt(); if (end != 0xFFFFFFFF) throw new IOException("invalid data content end guard"); - IdBiomeBlockStateMap mapping = IdBiomeBlockStateMap.deserialize(dos); + FullDataPointIdMap mapping = FullDataPointIdMap.deserialize(dos); end = dos.readInt(); if (end != 0xFFFFFFFF) throw new IOException("invalid id mapping end guard"); diff --git a/core/src/main/java/com/seibel/lod/core/datatype/full/accessor/FullArrayView.java b/core/src/main/java/com/seibel/lod/core/datatype/full/accessor/FullArrayView.java index 75c078997..aff3ee883 100644 --- a/core/src/main/java/com/seibel/lod/core/datatype/full/accessor/FullArrayView.java +++ b/core/src/main/java/com/seibel/lod/core/datatype/full/accessor/FullArrayView.java @@ -1,7 +1,7 @@ package com.seibel.lod.core.datatype.full.accessor; -import com.seibel.lod.core.datatype.full.FullFormat; -import com.seibel.lod.core.datatype.full.IdBiomeBlockStateMap; +import com.seibel.lod.core.datatype.full.FullDataPoint; +import com.seibel.lod.core.datatype.full.FullDataPointIdMap; import com.seibel.lod.core.util.LodUtil; public class FullArrayView implements IFullDataView @@ -10,9 +10,9 @@ public class FullArrayView implements IFullDataView protected final int offset; protected final int size; protected final int dataSize; - protected final IdBiomeBlockStateMap mapping; + protected final FullDataPointIdMap mapping; - public FullArrayView(IdBiomeBlockStateMap mapping, long[][] dataArrays, int size) + public FullArrayView(FullDataPointIdMap mapping, long[][] dataArrays, int size) { if (dataArrays.length != size * size) throw new IllegalArgumentException( @@ -37,7 +37,7 @@ public class FullArrayView implements IFullDataView } @Override - public IdBiomeBlockStateMap getMapping() + public FullDataPointIdMap getMapping() { return mapping; } @@ -66,11 +66,13 @@ public class FullArrayView implements IFullDataView return new FullArrayView(this, size, ox, oz); } - /** WARNING: It will potentially share the underlying array object! */ + /** WARNING: This will potentially share the underlying array object! */ public void shadowCopyTo(FullArrayView target) { if (target.size != size) + { throw new IllegalArgumentException("Target view must have same size as this view"); + } if (target.mapping.equals(mapping)) { for (int x = 0; x < size; x++) @@ -81,7 +83,7 @@ public class FullArrayView implements IFullDataView } else { - int[] map = target.mapping.computeAndMergeMapFrom(mapping); + int[] remappedIds = target.mapping.mergeAndReturnRemappedEntityIds(mapping); for (int x = 0; x < size; x++) { for (int o = 0; o < size; o++) @@ -90,7 +92,7 @@ public class FullArrayView implements IFullDataView long[] newData = new long[sourceData.length]; for (int i = 0; i < newData.length; i++) { - newData[i] = FullFormat.remap(map, sourceData[i]); + newData[i] = FullDataPoint.remap(remappedIds, sourceData[i]); } target.dataArrays[target.offset + x * target.dataSize + o] = newData; } diff --git a/core/src/main/java/com/seibel/lod/core/datatype/full/accessor/IFullDataView.java b/core/src/main/java/com/seibel/lod/core/datatype/full/accessor/IFullDataView.java index 440c2241a..2b987db81 100644 --- a/core/src/main/java/com/seibel/lod/core/datatype/full/accessor/IFullDataView.java +++ b/core/src/main/java/com/seibel/lod/core/datatype/full/accessor/IFullDataView.java @@ -1,13 +1,13 @@ package com.seibel.lod.core.datatype.full.accessor; -import com.seibel.lod.core.datatype.full.IdBiomeBlockStateMap; +import com.seibel.lod.core.datatype.full.FullDataPointIdMap; import com.seibel.lod.core.util.LodUtil; import java.util.Iterator; public interface IFullDataView { - IdBiomeBlockStateMap getMapping(); + FullDataPointIdMap getMapping(); SingleFullArrayView get(int index); diff --git a/core/src/main/java/com/seibel/lod/core/datatype/full/accessor/SingleFullArrayView.java b/core/src/main/java/com/seibel/lod/core/datatype/full/accessor/SingleFullArrayView.java index e74d5ac2d..b019c3d2b 100644 --- a/core/src/main/java/com/seibel/lod/core/datatype/full/accessor/SingleFullArrayView.java +++ b/core/src/main/java/com/seibel/lod/core/datatype/full/accessor/SingleFullArrayView.java @@ -1,15 +1,15 @@ package com.seibel.lod.core.datatype.full.accessor; -import com.seibel.lod.core.datatype.full.FullFormat; -import com.seibel.lod.core.datatype.full.IdBiomeBlockStateMap; +import com.seibel.lod.core.datatype.full.FullDataPoint; +import com.seibel.lod.core.datatype.full.FullDataPointIdMap; public class SingleFullArrayView implements IFullDataView { private final long[][] dataArrays; private final int offset; - private final IdBiomeBlockStateMap mapping; + private final FullDataPointIdMap mapping; - public SingleFullArrayView(IdBiomeBlockStateMap mapping, long[][] dataArrays, int offset) + public SingleFullArrayView(FullDataPointIdMap mapping, long[][] dataArrays, int offset) { this.dataArrays = dataArrays; this.offset = offset; @@ -19,7 +19,7 @@ public class SingleFullArrayView implements IFullDataView public boolean doesItExist() { return dataArrays[offset].length != 0; } @Override - public IdBiomeBlockStateMap getMapping() { return mapping; } + public FullDataPointIdMap getMapping() { return mapping; } @Override public SingleFullArrayView get(int index) @@ -68,12 +68,12 @@ public class SingleFullArrayView implements IFullDataView } else { - int[] map = target.mapping.computeAndMergeMapFrom(mapping); + int[] remappedEntryIds = target.mapping.mergeAndReturnRemappedEntityIds(mapping); long[] sourceData = dataArrays[offset]; long[] newData = new long[sourceData.length]; for (int i = 0; i < newData.length; i++) { - newData[i] = FullFormat.remap(map, sourceData[i]); + newData[i] = FullDataPoint.remap(remappedEntryIds, sourceData[i]); } target.dataArrays[target.offset] = newData; } @@ -87,12 +87,12 @@ public class SingleFullArrayView implements IFullDataView } else { - int[] map = target.mapping.computeAndMergeMapFrom(mapping); + int[] remappedEntryIds = target.mapping.mergeAndReturnRemappedEntityIds(mapping); long[] sourceData = dataArrays[offset]; long[] newData = new long[sourceData.length]; for (int i = 0; i < newData.length; i++) { - newData[i] = FullFormat.remap(map, sourceData[i]); + newData[i] = FullDataPoint.remap(remappedEntryIds, sourceData[i]); } target.dataArrays[target.offset] = newData; } diff --git a/core/src/main/java/com/seibel/lod/core/datatype/transform/FullToColumnTransformer.java b/core/src/main/java/com/seibel/lod/core/datatype/transform/FullToColumnTransformer.java index df624cc1b..83e1c4905 100644 --- a/core/src/main/java/com/seibel/lod/core/datatype/transform/FullToColumnTransformer.java +++ b/core/src/main/java/com/seibel/lod/core/datatype/transform/FullToColumnTransformer.java @@ -163,18 +163,17 @@ public class FullToColumnTransformer { } private static void iterateAndConvert(IDhClientLevel level, int blockX, int blockZ, int genMode, ColumnArrayView column, SingleFullArrayView data) { - IdBiomeBlockStateMap mapping = data.getMapping(); + FullDataPointIdMap mapping = data.getMapping(); boolean isVoid = true; int offset = 0; for (int i = 0; i < data.getSingleLength(); i++) { long fullData = data.getSingle(i); - int y = FullFormat.getY(fullData); - int blockLength = FullFormat.getDepth(fullData); - int id = FullFormat.getId(fullData); - int light = FullFormat.getLight(fullData); - IdBiomeBlockStateMap.Entry entry = mapping.get(id); - IBiomeWrapper biome = entry.biome; - IBlockStateWrapper block = entry.blockState; + int y = FullDataPoint.getY(fullData); + int blockLength = FullDataPoint.getDepth(fullData); + int id = FullDataPoint.getId(fullData); + int light = FullDataPoint.getLight(fullData); + IBiomeWrapper biome = mapping.getBiomeWrapper(id); + IBlockStateWrapper block = mapping.getBlockStateWrapper(id); if (block.equals(AIR)) continue; isVoid = false; int color = level.computeBaseColor(new DhBlockPos(blockX, y + level.getMinY(), blockZ), biome, block); diff --git a/core/src/main/java/com/seibel/lod/core/datatype/transform/LodDataBuilder.java b/core/src/main/java/com/seibel/lod/core/datatype/transform/LodDataBuilder.java index e94d1908a..fd3b914d1 100644 --- a/core/src/main/java/com/seibel/lod/core/datatype/transform/LodDataBuilder.java +++ b/core/src/main/java/com/seibel/lod/core/datatype/transform/LodDataBuilder.java @@ -1,7 +1,7 @@ package com.seibel.lod.core.datatype.transform; import com.seibel.lod.core.datatype.full.ChunkSizedData; -import com.seibel.lod.core.datatype.full.FullFormat; +import com.seibel.lod.core.datatype.full.FullDataPoint; import com.seibel.lod.core.dependencyInjection.SingletonInjector; import com.seibel.lod.core.util.LodUtil; import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory; @@ -34,7 +34,7 @@ public class LodDataBuilder { byte newLight = (byte) ((chunk.getBlockLight(x,y+1,z) << 4) + chunk.getSkyLight(x,y+1,z)); if (!newBiome.equals(biome) || !newBlockState.equals(blockState)) { - longs.add(FullFormat.encode(mappedId, lastY-y, y+1 - chunk.getMinBuildHeight(), light)); + longs.add(FullDataPoint.encode(mappedId, lastY-y, y+1 - chunk.getMinBuildHeight(), light)); biome = newBiome; blockState = newBlockState; mappedId = chunkData.getMapping().setAndGetId(biome, blockState); @@ -47,7 +47,7 @@ public class LodDataBuilder { // lastY = y; // } } - longs.add(FullFormat.encode(mappedId, lastY-y, y+1 - chunk.getMinBuildHeight(), light)); + longs.add(FullDataPoint.encode(mappedId, lastY-y, y+1 - chunk.getMinBuildHeight(), light)); chunkData.setSingleColumn(longs.toArray(new long[0]), x, z); }