diff --git a/core/src/main/java/com/seibel/lod/core/datatype/column/ColumnRenderSource.java b/core/src/main/java/com/seibel/lod/core/datatype/column/ColumnRenderSource.java index b1daf3409..3e653b3a5 100644 --- a/core/src/main/java/com/seibel/lod/core/datatype/column/ColumnRenderSource.java +++ b/core/src/main/java/com/seibel/lod/core/datatype/column/ColumnRenderSource.java @@ -28,394 +28,434 @@ import java.nio.ByteOrder; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicReference; -public class ColumnRenderSource implements ILodRenderSource, IColumnDatatype { - private static final Logger LOGGER = DhLoggerBuilder.getLogger(); - public static final boolean DO_SAFETY_CHECKS = true; - public static final byte SECTION_SIZE_OFFSET = 6; - public static final int SECTION_SIZE = 1 << SECTION_SIZE_OFFSET; - public static final byte LATEST_VERSION = 1; - public static final long TYPE_ID = "ColumnRenderSource".hashCode(); - public static final int AIR_LODS_SIZE = 16; - public static final int AIR_SECTION_SIZE = SECTION_SIZE/AIR_LODS_SIZE; - - public final int verticalSize; - public final DhSectionPos sectionPos; - public final int yOffset; - - public final long[] dataContainer; - public final int[] airDataContainer; - - public enum DebugSourceFlag { - FULL(ColorUtil.BLUE), - DIRECT(ColorUtil.WHITE), - SPARSE(ColorUtil.YELLOW), - FILE(ColorUtil.BROWN); - public final int color; - DebugSourceFlag(int color) { - this.color = color; - } - } - - public final DebugSourceFlag[] debugSourceFlags; - - public void debugFillFlag(int ox, int oz, int w, int h, DebugSourceFlag flag) { - for (int x = ox; x < ox + w; x++) { - for (int z = oz; z < oz + h; z++) { - debugSourceFlags[x * SECTION_SIZE + z] = flag; - } - } - } - - public DebugSourceFlag debugGetFlag(int ox, int oz) { - return debugSourceFlags[ox * SECTION_SIZE + oz]; - } - - private boolean isEmpty = true; - - /** - * Constructor of the ColumnDataType - * @param maxVerticalSize the maximum vertical size of the container - */ - public ColumnRenderSource(DhSectionPos sectionPos, int maxVerticalSize, int yOffset) { - verticalSize = maxVerticalSize; - dataContainer = new long[SECTION_SIZE * SECTION_SIZE * verticalSize]; - airDataContainer = new int[AIR_SECTION_SIZE * AIR_SECTION_SIZE * verticalSize]; - debugSourceFlags = new DebugSourceFlag[SECTION_SIZE * SECTION_SIZE]; - this.sectionPos = sectionPos; - this.yOffset = yOffset; - } - - private long[] loadData(DataInputStream inputData, int version, int verticalSize) throws IOException { - switch (version) { - case 1: - return readDataV1(inputData, verticalSize); - default: - throw new IOException("Invalid Data: The version of the data is not supported"); - } - } - private long[] readDataV1(DataInputStream inputData, int tempMaxVerticalData) throws IOException { - int x = SECTION_SIZE * SECTION_SIZE * tempMaxVerticalData; - short tempMinHeight = Short.reverseBytes(inputData.readShort()); - if (tempMinHeight == Short.MAX_VALUE) { //FIXME: Temp hack flag for marking a empty section - return new long[x]; - } - isEmpty = false; - byte[] data = new byte[x * Long.BYTES]; - ByteBuffer bb = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN); - inputData.readFully(data); - long[] result = new long[x]; - bb.asLongBuffer().get(result); - if (tempMinHeight != yOffset) { - for (int i=0; i= SECTION_SIZE) - throw new IllegalArgumentException("X position is out of bounds"); - if (posZ < 0 || posZ >= SECTION_SIZE) - throw new IllegalArgumentException("Z position is out of bounds"); - } - int index = posX * SECTION_SIZE * verticalSize + posZ * verticalSize; - int compare = ColumnFormat.compareDatapointPriority(data.get(0), dataContainer[index]); - if (override) { - if (compare<0) return false; - } else { - if (compare<=0) return false; - } - data.copyTo(dataContainer, index, data.size()); - return true; - } - - @Override - public long getData(int posX, int posZ, int verticalIndex) - { - return dataContainer[posX * SECTION_SIZE * verticalSize + posZ * verticalSize + verticalIndex]; - } - - @Override - public long[] getAllData(int posX, int posZ) - { - long[] result = new long[verticalSize]; - int index = posX * SECTION_SIZE * verticalSize + posZ * verticalSize; - System.arraycopy(dataContainer, index, result, 0, verticalSize); - return result; - } - - @Override - public ColumnArrayView getVerticalDataView(int posX, int posZ) { - return new ColumnArrayView(dataContainer, verticalSize, - posX * SECTION_SIZE * verticalSize + posZ * verticalSize, verticalSize); - } - - @Override - public ColumnQuadView getDataInQuad(int quadX, int quadZ, int quadXSize, int quadZSize) { - return new ColumnQuadView(dataContainer, SECTION_SIZE, verticalSize, quadX, quadZ, quadXSize, quadZSize); - } - @Override - public ColumnQuadView getFullQuad() { - return new ColumnQuadView(dataContainer, SECTION_SIZE, verticalSize, 0, 0, SECTION_SIZE, SECTION_SIZE); - } - - @Override - public int getVerticalSize() - { - return verticalSize; - } - - @Override - public boolean doesItExist(int posX, int posZ) - { - return ColumnFormat.doesItExist(getSingleData(posX, posZ)); - } - - @Override - public void generateData(IColumnDatatype lowerDataContainer, int posX, int posZ) - { - ColumnQuadView quadView = lowerDataContainer.getDataInQuad(posX*2, posZ*2, 2,2); - ColumnArrayView outputView = getVerticalDataView(posX, posZ); - outputView.mergeMultiDataFrom(quadView); - } - - boolean writeData(DataOutputStream output) throws IOException { - output.writeByte(getDataDetail()); - output.writeByte((byte) verticalSize); - // FIXME: yOffset is a int, but we only are writing a short. - if (isEmpty) { - output.writeByte(Short.MAX_VALUE & 0xFF); - output.writeByte((Short.MAX_VALUE >> 8) & 0xFF); - return false; - } - output.writeByte((byte) (yOffset & 0xFF)); - output.writeByte((byte) ((yOffset >> 8) & 0xFF)); - boolean allGenerated = true; - int x = SECTION_SIZE * SECTION_SIZE; - for (int i = 0; i < x; i++) - { - for (int j = 0; j < verticalSize; j++) - { - long current = dataContainer[i * verticalSize + j]; - if (ColumnFormat.doesItExist(current)) - current = ColumnFormat.overrideGenerationMode(current, (byte) 1); - output.writeLong(Long.reverseBytes(current)); - } - if (!ColumnFormat.doesItExist(dataContainer[i])) - allGenerated = false; - } - return allGenerated; - } - - public String toString() - { - String LINE_DELIMITER = "\n"; - String DATA_DELIMITER = " "; - String SUBDATA_DELIMITER = ","; - StringBuilder stringBuilder = new StringBuilder(); - int size = sectionPos.getWidth().value; - stringBuilder.append(sectionPos); - stringBuilder.append(LINE_DELIMITER); - for (int z = 0; z < size; z++) - { - for (int x = 0; x < size; x++) - { - for (int y = 0; y < verticalSize; y++) { - //Converting the dataToHex - stringBuilder.append(Long.toHexString(getData(x,z,y))); - if (y != verticalSize-1) stringBuilder.append(SUBDATA_DELIMITER); - } - if (x != size-1) stringBuilder.append(DATA_DELIMITER); - } - if (z != size-1) stringBuilder.append(LINE_DELIMITER); - } - return stringBuilder.toString(); - } - - @Override - public int getMaxNumberOfLods() - { - return SECTION_SIZE * SECTION_SIZE * getVerticalSize(); - } - - @Override - public long getRoughRamUsage() - { - return (long) dataContainer.length * Long.BYTES; - } - - public DhSectionPos getSectionPos() { - return sectionPos; - } - - public byte getDataDetail() { - return (byte) (sectionPos.sectionDetail - SECTION_SIZE_OFFSET); - } - - @Override - public byte getDetailOffset() { - return SECTION_SIZE_OFFSET; - } - - private CompletableFuture inBuildRenderBuffer = null; - private Reference usedBuffer = new Reference<>(); - - - private void tryBuildBuffer(IDhClientLevel level, LodQuadTree quadTree) { - if (inBuildRenderBuffer == null && !ColumnRenderBuffer.isBusy() && !isEmpty) { - ColumnRenderSource[] data = new ColumnRenderSource[ELodDirection.ADJ_DIRECTIONS.length]; - for (ELodDirection direction : ELodDirection.ADJ_DIRECTIONS) { - LodRenderSection section = quadTree.getSection(sectionPos.getAdjacent(direction)); //FIXME: Handle traveling through different detail levels - if (section != null && section.getRenderSource() != null && section.getRenderSource() instanceof ColumnRenderSource) { - data[direction.ordinal()-2] = ((ColumnRenderSource) section.getRenderSource()); - } - } - inBuildRenderBuffer = ColumnRenderBuffer.build(level, usedBuffer, this, data); - } - } - private void cancelBuildBuffer() { - if (inBuildRenderBuffer != null) { - //LOGGER.info("Cancelling build of render buffer for {}", sectionPos); - inBuildRenderBuffer.cancel(true); - inBuildRenderBuffer = null; - } - } - - private IDhClientLevel level = null; //FIXME: hack to pass level into tryBuildBuffer - @Override - public void enableRender(IDhClientLevel level, LodQuadTree quadTree) { - this.level = level; - //tryBuildBuffer(level, quadTree); - } - - @Override - public void disableRender() { - cancelBuildBuffer(); - } - - @Override - public void dispose() { - cancelBuildBuffer(); - } - - //FIXME: Temp Hack - private long lastNs = -1; - private static final long SWAP_TIMEOUT = /* 10 sec */ 10_000_000_000L; - private static final long SWAP_BUSY_COLLISION_TIMEOUT = /* 1 sec */ 1_000_000_000L; - - @Override - public boolean trySwapRenderBuffer(LodQuadTree quadTree, AtomicReference referenceSlot) { - if (lastNs != -1 && System.nanoTime() - lastNs < SWAP_TIMEOUT) { - return false; - } - if (inBuildRenderBuffer != null) { - if (inBuildRenderBuffer.isDone()) { - lastNs = System.nanoTime(); - //LOGGER.info("Swapping render buffer for {}", sectionPos); - RenderBuffer newBuffer = inBuildRenderBuffer.join(); - RenderBuffer oldBuffer = referenceSlot.getAndSet(newBuffer); - if (oldBuffer instanceof ColumnRenderBuffer) { - ColumnRenderBuffer swapped = usedBuffer.swap((ColumnRenderBuffer) oldBuffer); - LodUtil.assertTrue(swapped == null); - } - inBuildRenderBuffer = null; - return true; - } - } else { - if (!isEmpty) { - if (ColumnRenderBuffer.isBusy()) { - lastNs += (long) (SWAP_BUSY_COLLISION_TIMEOUT * Math.random()); - } else tryBuildBuffer(level, quadTree); - } - } - return false; - } - - @Override - public void saveRender(IDhClientLevel level, RenderMetaFile file, OutputStream dataStream) throws IOException { - DataOutputStream dos = new DataOutputStream(dataStream); // DO NOT CLOSE - writeData(dos); - } - - @Override - public byte getRenderVersion() { - return LATEST_VERSION; - } - - @Override - public boolean isValid() { - return true; - } - - @Override - public boolean isEmpty() { - return isEmpty; - } - public void markNotEmpty() { - isEmpty = false; - } - - @Override - public void weakWrite(ILodRenderSource source) { - LodUtil.assertTrue(source instanceof ColumnRenderSource); - ColumnRenderSource src = (ColumnRenderSource) source; - - LodUtil.assertTrue(src.sectionPos.equals(sectionPos)); - LodUtil.assertTrue(src.verticalSize == verticalSize); - - if (src.isEmpty) return; - isEmpty = false; - - for (int i=0; i inBuildRenderBuffer = null; + private final Reference usedBuffer = new Reference<>(); + + + + + /** + * Creates an empty ColumnRenderSource. + * + * @param sectionPos the relative position of the container + * @param maxVerticalSize the maximum vertical size of the container + */ + public ColumnRenderSource(DhSectionPos sectionPos, int maxVerticalSize, int yOffset) + { + verticalSize = maxVerticalSize; + dataContainer = new long[SECTION_SIZE * SECTION_SIZE * verticalSize]; + airDataContainer = new int[AIR_SECTION_SIZE * AIR_SECTION_SIZE * verticalSize]; + debugSourceFlags = new DebugSourceFlag[SECTION_SIZE * SECTION_SIZE]; + this.sectionPos = sectionPos; + this.yOffset = yOffset; + } + + /** + * Creates a new ColumnRenderSource with data from the given DataInputStream. + * + * @param inputData Expected format: 1st byte: detail level, 2nd byte: vertical size, 3rd byte on: column data + * @throws IOException if the DataInputStream's detail level isn't what was expected + */ + public ColumnRenderSource(DhSectionPos sectionPos, DataInputStream inputData, int version, IDhLevel level) throws IOException + { + byte detailLevel = inputData.readByte(); + if (sectionPos.sectionDetail - SECTION_SIZE_OFFSET != detailLevel) + { + throw new IOException("Invalid data: detail level does not match"); + } + + this.sectionPos = sectionPos; + this.yOffset = level.getMinY(); + this.verticalSize = inputData.readByte() & 0b01111111; + this.dataContainer = loadData(inputData, version, this.verticalSize); + this.airDataContainer = new int[AIR_SECTION_SIZE * AIR_SECTION_SIZE * this.verticalSize]; + + this.debugSourceFlags = new DebugSourceFlag[SECTION_SIZE * SECTION_SIZE]; + debugFillFlag(0, 0, SECTION_SIZE, SECTION_SIZE, DebugSourceFlag.FILE); + } + + + + + public void debugFillFlag(int ox, int oz, int w, int h, DebugSourceFlag flag) + { + for (int x = ox; x < ox + w; x++) + { + for (int z = oz; z < oz + h; z++) + { + debugSourceFlags[x * SECTION_SIZE + z] = flag; + } + } + } + + public DebugSourceFlag debugGetFlag(int ox, int oz) { return debugSourceFlags[ox * SECTION_SIZE + oz]; } + + private long[] loadData(DataInputStream inputData, int version, int verticalSize) throws IOException + { + switch (version) + { + case 1: + return readDataV1(inputData, verticalSize); + default: + throw new IOException("Invalid Data: The version of the data is not supported"); + } + } + + private long[] readDataV1(DataInputStream inputData, int tempMaxVerticalData) throws IOException + { + int x = SECTION_SIZE * SECTION_SIZE * tempMaxVerticalData; + short tempMinHeight = Short.reverseBytes(inputData.readShort()); + if (tempMinHeight == Short.MAX_VALUE) + { //FIXME: Temp hack flag for marking a empty section + return new long[x]; + } + isEmpty = false; + byte[] data = new byte[x * Long.BYTES]; + ByteBuffer bb = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN); + inputData.readFully(data); + long[] result = new long[x]; + bb.asLongBuffer().get(result); + if (tempMinHeight != yOffset) + { + for (int i = 0; i < result.length; i++) + { + result[i] = ColumnFormat.shiftHeightAndDepth(result[i], (short) (tempMinHeight - yOffset)); + } + } + return result; + } + + @Override + public void clear(int posX, int posZ) + { + for (int verticalIndex = 0; verticalIndex < verticalSize; verticalIndex++) + dataContainer[posX * SECTION_SIZE * verticalSize + posZ * verticalSize + verticalIndex] = + ColumnFormat.EMPTY_DATA; + } + + + @Override + public boolean addData(long data, int posX, int posZ, int verticalIndex) + { + dataContainer[posX * SECTION_SIZE * verticalSize + posZ * verticalSize + verticalIndex] = data; + return true; + } + + @Override + public boolean copyVerticalData(IColumnDataView data, int posX, int posZ, boolean override) + { + if (DO_SAFETY_CHECKS) + { + if (data.size() != verticalSize) + throw new IllegalArgumentException("data size not the same as vertical size"); + if (posX < 0 || posX >= SECTION_SIZE) + throw new IllegalArgumentException("X position is out of bounds"); + if (posZ < 0 || posZ >= SECTION_SIZE) + throw new IllegalArgumentException("Z position is out of bounds"); + } + int index = posX * SECTION_SIZE * verticalSize + posZ * verticalSize; + int compare = ColumnFormat.compareDatapointPriority(data.get(0), dataContainer[index]); + if (override) + { + if (compare < 0) + return false; + } + else + { + if (compare <= 0) + return false; + } + data.copyTo(dataContainer, index, data.size()); + return true; + } + + @Override + public long getData(int posX, int posZ, int verticalIndex) { return dataContainer[posX * SECTION_SIZE * verticalSize + posZ * verticalSize + verticalIndex]; } + + @Override + public long[] getAllData(int posX, int posZ) + { + long[] result = new long[verticalSize]; + int index = posX * SECTION_SIZE * verticalSize + posZ * verticalSize; + System.arraycopy(dataContainer, index, result, 0, verticalSize); + return result; + } + + @Override + public ColumnArrayView getVerticalDataView(int posX, int posZ) + { + return new ColumnArrayView(dataContainer, verticalSize, + posX * SECTION_SIZE * verticalSize + posZ * verticalSize, verticalSize); + } + + @Override + public ColumnQuadView getDataInQuad(int quadX, int quadZ, int quadXSize, int quadZSize) { return new ColumnQuadView(dataContainer, SECTION_SIZE, verticalSize, quadX, quadZ, quadXSize, quadZSize); } + + @Override + public ColumnQuadView getFullQuad() { return new ColumnQuadView(dataContainer, SECTION_SIZE, verticalSize, 0, 0, SECTION_SIZE, SECTION_SIZE); } + + @Override + public int getVerticalSize() { return verticalSize; } + + @Override + public boolean doesItExist(int posX, int posZ) { return ColumnFormat.doesItExist(getSingleData(posX, posZ)); } + + @Override + public void generateData(IColumnDatatype lowerDataContainer, int posX, int posZ) + { + ColumnQuadView quadView = lowerDataContainer.getDataInQuad(posX * 2, posZ * 2, 2, 2); + ColumnArrayView outputView = getVerticalDataView(posX, posZ); + outputView.mergeMultiDataFrom(quadView); + } + + boolean writeData(DataOutputStream output) throws IOException + { + output.writeByte(getDataDetail()); + output.writeByte((byte) verticalSize); + // FIXME: yOffset is a int, but we only are writing a short. + if (isEmpty) + { + output.writeByte(Short.MAX_VALUE & 0xFF); + output.writeByte((Short.MAX_VALUE >> 8) & 0xFF); + return false; + } + output.writeByte((byte) (yOffset & 0xFF)); + output.writeByte((byte) ((yOffset >> 8) & 0xFF)); + boolean allGenerated = true; + int x = SECTION_SIZE * SECTION_SIZE; + for (int i = 0; i < x; i++) + { + for (int j = 0; j < verticalSize; j++) + { + long current = dataContainer[i * verticalSize + j]; + if (ColumnFormat.doesItExist(current)) + current = ColumnFormat.overrideGenerationMode(current, (byte) 1); + output.writeLong(Long.reverseBytes(current)); + } + if (!ColumnFormat.doesItExist(dataContainer[i])) + allGenerated = false; + } + return allGenerated; + } + + public String toString() + { + String LINE_DELIMITER = "\n"; + String DATA_DELIMITER = " "; + String SUBDATA_DELIMITER = ","; + StringBuilder stringBuilder = new StringBuilder(); + int size = sectionPos.getWidth().value; + stringBuilder.append(sectionPos); + stringBuilder.append(LINE_DELIMITER); + for (int z = 0; z < size; z++) + { + for (int x = 0; x < size; x++) + { + for (int y = 0; y < verticalSize; y++) + { + //Converting the dataToHex + stringBuilder.append(Long.toHexString(getData(x, z, y))); + if (y != verticalSize - 1) + stringBuilder.append(SUBDATA_DELIMITER); + } + if (x != size - 1) + stringBuilder.append(DATA_DELIMITER); + } + if (z != size - 1) + stringBuilder.append(LINE_DELIMITER); + } + return stringBuilder.toString(); + } + + @Override + public int getMaxNumberOfLods() { return SECTION_SIZE * SECTION_SIZE * getVerticalSize(); } + + @Override + public long getRoughRamUsageInBytes() { return (long) dataContainer.length * Long.BYTES; } + + public DhSectionPos getSectionPos() { return sectionPos; } + + public byte getDataDetail() { return (byte) (sectionPos.sectionDetail - SECTION_SIZE_OFFSET); } + + @Override + public byte getDetailOffset() { return SECTION_SIZE_OFFSET; } + + + private void tryBuildBuffer(IDhClientLevel level, LodQuadTree quadTree) + { + if (inBuildRenderBuffer == null && !ColumnRenderBuffer.isBusy() && !isEmpty) + { + ColumnRenderSource[] data = new ColumnRenderSource[ELodDirection.ADJ_DIRECTIONS.length]; + for (ELodDirection direction : ELodDirection.ADJ_DIRECTIONS) + { + LodRenderSection section = quadTree.getSection(sectionPos.getAdjacent(direction)); //FIXME: Handle traveling through different detail levels + if (section != null && section.getRenderSource() != null && section.getRenderSource() instanceof ColumnRenderSource) + { + data[direction.ordinal() - 2] = ((ColumnRenderSource) section.getRenderSource()); + } + } + inBuildRenderBuffer = ColumnRenderBuffer.build(level, usedBuffer, this, data); + } + } + + private void cancelBuildBuffer() + { + if (inBuildRenderBuffer != null) + { + //LOGGER.info("Cancelling build of render buffer for {}", sectionPos); + inBuildRenderBuffer.cancel(true); + inBuildRenderBuffer = null; + } + } + + @Override + public void enableRender(IDhClientLevel level, LodQuadTree quadTree) + { + this.level = level; + //tryBuildBuffer(level, quadTree); + } + + @Override + public void disableRender() { cancelBuildBuffer(); } + + @Override + public void dispose() { cancelBuildBuffer(); } + + @Override + public boolean trySwapRenderBuffer(LodQuadTree quadTree, AtomicReference referenceSlot) + { + if (lastNs != -1 && System.nanoTime() - lastNs < SWAP_TIMEOUT) + { + return false; + } + if (inBuildRenderBuffer != null) + { + if (inBuildRenderBuffer.isDone()) + { + lastNs = System.nanoTime(); + //LOGGER.info("Swapping render buffer for {}", sectionPos); + RenderBuffer newBuffer = inBuildRenderBuffer.join(); + RenderBuffer oldBuffer = referenceSlot.getAndSet(newBuffer); + if (oldBuffer instanceof ColumnRenderBuffer) + { + ColumnRenderBuffer swapped = usedBuffer.swap((ColumnRenderBuffer) oldBuffer); + LodUtil.assertTrue(swapped == null); + } + inBuildRenderBuffer = null; + return true; + } + } + else + { + if (!isEmpty) + { + if (ColumnRenderBuffer.isBusy()) + { + lastNs += (long) (SWAP_BUSY_COLLISION_TIMEOUT * Math.random()); + } + else + tryBuildBuffer(level, quadTree); + } + } + return false; + } + + @Override + public void saveRender(IDhClientLevel level, RenderMetaFile file, OutputStream dataStream) throws IOException + { + DataOutputStream dos = new DataOutputStream(dataStream); // DO NOT CLOSE + writeData(dos); + } + + @Override + public byte getRenderVersion() { return LATEST_VERSION; } + + @Override + public boolean isValid() { return true; } + + @Override + public boolean isEmpty() { return isEmpty; } + + public void markNotEmpty() { isEmpty = false; } + + @Override + public void weakWrite(ILodRenderSource source) + { + LodUtil.assertTrue(source instanceof ColumnRenderSource); + ColumnRenderSource src = (ColumnRenderSource) source; + + LodUtil.assertTrue(src.sectionPos.equals(sectionPos)); + LodUtil.assertTrue(src.verticalSize == verticalSize); + + if (src.isEmpty) + return; + isEmpty = false; + + for (int i = 0; i < dataContainer.length; i += verticalSize) + { + int genMode = ColumnFormat.getGenerationMode(dataContainer[i]); + int srcGenMode = ColumnFormat.getGenerationMode(src.dataContainer[i]); + if (srcGenMode == 0) + continue; + if (genMode <= srcGenMode) + { + new ColumnArrayView(dataContainer, verticalSize, i, verticalSize).copyFrom( + new ColumnArrayView(src.dataContainer, verticalSize, i, verticalSize)); + debugSourceFlags[i / verticalSize] = src.debugSourceFlags[i / verticalSize]; + } + } + } + + @Override + public void fastWrite(ChunkSizedData chunkData, IDhClientLevel level) { FullToColumnTransformer.writeFullDataChunkToColumnData(this, level, chunkData); } + + + + //==============// + // helper enums // + //==============// + + public enum DebugSourceFlag + { + FULL(ColorUtil.BLUE), + DIRECT(ColorUtil.WHITE), + SPARSE(ColorUtil.YELLOW), + FILE(ColorUtil.BROWN); + + public final int color; + + DebugSourceFlag(int color) { this.color = color; } + } + } diff --git a/core/src/main/java/com/seibel/lod/core/datatype/column/accessor/IColumnDatatype.java b/core/src/main/java/com/seibel/lod/core/datatype/column/accessor/IColumnDatatype.java index 98bf3dfb9..935efbef8 100644 --- a/core/src/main/java/com/seibel/lod/core/datatype/column/accessor/IColumnDatatype.java +++ b/core/src/main/java/com/seibel/lod/core/datatype/column/accessor/IColumnDatatype.java @@ -1,34 +1,46 @@ package com.seibel.lod.core.datatype.column.accessor; -public interface IColumnDatatype { - byte getDetailOffset(); - default int getDataSize() { - return 1 << getDetailOffset(); - } - int getMaxNumberOfLods(); - long getRoughRamUsage(); - - int getVerticalSize(); - boolean doesItExist(int posX, int posZ); - long getData(int posX, int posZ, int verticalIndex); - default long getSingleData(int posX, int posZ) {return getData(posX, posZ, 0);} - long[] getAllData(int posX, int posZ); - ColumnArrayView getVerticalDataView(int posX, int posZ); - ColumnQuadView getDataInQuad(int quadX, int quadZ, int quadXSize, int quadZSize); - ColumnQuadView getFullQuad(); - - /** - * This method will clear all data at relative section position - */ - void clear(int posX, int posZ); - /** - * This method will add the data given in input at the relative position and vertical index - */ - boolean addData(long data, int posX, int posZ, int verticalIndex); - /** - * This methods will add the data in the given position if certain condition are satisfied - * @param override if override is true we can override data created with same generation mode - */ - boolean copyVerticalData(IColumnDataView data, int posX, int posZ, boolean override); - void generateData(IColumnDatatype lowerDataContainer, int posX, int posZ); +public interface IColumnDatatype +{ + byte getDetailOffset(); + + default int getDataSize() + { + return 1 << getDetailOffset(); + } + + int getMaxNumberOfLods(); + + long getRoughRamUsageInBytes(); + + int getVerticalSize(); + + boolean doesItExist(int posX, int posZ); + + long getData(int posX, int posZ, int verticalIndex); + + default long getSingleData(int posX, int posZ) { return getData(posX, posZ, 0); } + + long[] getAllData(int posX, int posZ); + + ColumnArrayView getVerticalDataView(int posX, int posZ); + + ColumnQuadView getDataInQuad(int quadX, int quadZ, int quadXSize, int quadZSize); + + ColumnQuadView getFullQuad(); + + /** clears all data at the relative position */ + void clear(int posX, int posZ); + + /** adds the given data to the relative position and vertical index */ + boolean addData(long data, int posX, int posZ, int verticalIndex); + + /** + * This methods will add the data in the given position if certain condition are satisfied + * @param override if override is true we can override data created with same generation mode + */ + boolean copyVerticalData(IColumnDataView data, int posX, int posZ, boolean override); + + void generateData(IColumnDatatype lowerDataContainer, int posX, int posZ); + } diff --git a/core/src/main/java/com/seibel/lod/core/util/objects/Reference.java b/core/src/main/java/com/seibel/lod/core/util/objects/Reference.java index 699e58428..5ffb0206a 100644 --- a/core/src/main/java/com/seibel/lod/core/util/objects/Reference.java +++ b/core/src/main/java/com/seibel/lod/core/util/objects/Reference.java @@ -1,17 +1,21 @@ package com.seibel.lod.core.util.objects; -public class Reference { - public T v; - public Reference() {} - public Reference(T v) { - this.v = v; - } - public T swap(T v) { - T old = this.v; - this.v = v; - return old; - } - public boolean isEmpty() { - return v == null; - } +public class Reference +{ + public T value; + + + public Reference() { } + + public Reference(T value) { this.value = value; } + + public T swap(T v) + { + T old = this.value; + this.value = v; + return old; + } + + public boolean isEmpty() { return value == null; } + }