diff --git a/core/src/main/java/com/seibel/lod/core/datatype/AbstractRenderSourceLoader.java b/core/src/main/java/com/seibel/lod/core/datatype/AbstractRenderSourceLoader.java
index dd96472a9..f3443f0be 100644
--- a/core/src/main/java/com/seibel/lod/core/datatype/AbstractRenderSourceLoader.java
+++ b/core/src/main/java/com/seibel/lod/core/datatype/AbstractRenderSourceLoader.java
@@ -93,7 +93,12 @@ public abstract class AbstractRenderSourceLoader
LOADER_BY_SOURCE_TYPE.put(renderSourceClass, this);
}
- /** Can return null if the file is out of date or something */
+ /**
+ * Can return null if the file is out of date.
+ *
+ * @throws IOException if the file uses a unsupported data version
+ * or there was an issue reading the file
+ */
public abstract ILodRenderSource loadRenderSource(RenderMetaDataFile renderFile, InputStream data, IDhLevel level) throws IOException;
/** Should not return null */
public abstract ILodRenderSource createRenderSource(ILodDataSource dataSource, IDhClientLevel level);
diff --git a/core/src/main/java/com/seibel/lod/core/datatype/column/ColumnRenderLoader.java b/core/src/main/java/com/seibel/lod/core/datatype/column/ColumnRenderLoader.java
index 222ab2b58..52fc1d5ae 100644
--- a/core/src/main/java/com/seibel/lod/core/datatype/column/ColumnRenderLoader.java
+++ b/core/src/main/java/com/seibel/lod/core/datatype/column/ColumnRenderLoader.java
@@ -2,6 +2,7 @@ package com.seibel.lod.core.datatype.column;
import com.seibel.lod.core.datatype.IIncompleteDataSource;
import com.seibel.lod.core.datatype.ILodDataSource;
+import com.seibel.lod.core.datatype.column.accessor.ColumnFormat;
import com.seibel.lod.core.datatype.full.FullDataSource;
import com.seibel.lod.core.datatype.transform.FullToColumnTransformer;
import com.seibel.lod.core.level.IDhClientLevel;
@@ -14,9 +15,14 @@ import com.seibel.lod.core.util.LodUtil;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
/**
- * Can load {@link ColumnRenderSource}'s for the {@link ColumnRenderSource#LATEST_VERSION}
+ * Handles loading and parsing {@link RenderMetaDataFile}s to create {@link ColumnRenderSource}s.
+ *
+ * Please see the {@link ColumnRenderLoader#loadRenderSource} method to see what
+ * file versions this class can handle.
*/
public class ColumnRenderLoader extends AbstractRenderSourceLoader
{
@@ -30,8 +36,16 @@ public class ColumnRenderLoader extends AbstractRenderSourceLoader
@Override
public ILodRenderSource loadRenderSource(RenderMetaDataFile dataFile, InputStream data, IDhLevel level) throws IOException
{
- DataInputStream inputStream = new DataInputStream(data); // DO NOT CLOSE
- return new ColumnRenderSource(dataFile.pos, inputStream, dataFile.metaData.loaderVersion, level);
+ DataInputStream inputStream = new DataInputStream(data); // DO NOT CLOSE
+ int dataFileVersion = dataFile.metaData.loaderVersion;
+
+ switch (dataFileVersion)
+ {
+ case 1:
+ return new ColumnRenderSource(dataFile.pos, readDataV1(inputStream, level.getMinY()), level);
+ default:
+ throw new IOException("Invalid Data: The data version [" + dataFileVersion + "] is not supported");
+ }
}
@Override
@@ -49,4 +63,66 @@ public class ColumnRenderLoader extends AbstractRenderSourceLoader
return null;
}
+
+
+ //========================//
+ // versioned file parsing //
+ //========================//
+
+ /**
+ * @param inputData Expected format: 1st byte: detail level, 2nd byte: vertical size, 3rd byte on: column data
+ *
+ * @throws IOException if there was an issue reading the stream
+ */
+ private static ParsedColumnData readDataV1(DataInputStream inputData, int yOffset) throws IOException
+ {
+ byte detailLevel = inputData.readByte();
+ int verticalDataCount = inputData.readByte() & 0b01111111;
+
+ int maxNumberOfDataPoints = ColumnRenderSource.SECTION_SIZE * ColumnRenderSource.SECTION_SIZE * verticalDataCount;
+
+
+ //FIXME: Temp hack flag for marking a empty section
+ short tempMinHeight = Short.reverseBytes(inputData.readShort());
+ if (tempMinHeight == Short.MAX_VALUE)
+ {
+ return new ParsedColumnData(detailLevel, verticalDataCount, new long[maxNumberOfDataPoints], true);
+ }
+
+
+ // isEmpty = false
+ byte[] data = new byte[maxNumberOfDataPoints * Long.BYTES];
+ ByteBuffer byteBuffer = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN);
+ inputData.readFully(data);
+
+ long[] dataPoints = new long[maxNumberOfDataPoints];
+ byteBuffer.asLongBuffer().get(dataPoints);
+ if (tempMinHeight != yOffset)
+ {
+ for (int i = 0; i < dataPoints.length; i++)
+ {
+ dataPoints[i] = ColumnFormat.shiftHeightAndDepth(dataPoints[i], (short) (tempMinHeight - yOffset));
+ }
+ }
+
+ return new ParsedColumnData(detailLevel, verticalDataCount, dataPoints, false);
+ }
+
+ public static class ParsedColumnData
+ {
+ byte detailLevel;
+ int verticalSize;
+ long[] dataContainer;
+ boolean isEmpty;
+
+ public ParsedColumnData(byte detailLevel, int verticalSize, long[] dataContainer, boolean isEmpty)
+ {
+ this.detailLevel = detailLevel;
+ this.verticalSize = verticalSize;
+ this.dataContainer = dataContainer;
+ this.isEmpty = isEmpty;
+ }
+ }
+
+
}
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 2f034e55f..403582804 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
@@ -19,12 +19,9 @@ import com.seibel.lod.core.util.objects.Reference;
import com.seibel.lod.core.util.LodUtil;
import org.apache.logging.log4j.Logger;
-import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicReference;
@@ -88,23 +85,21 @@ public class ColumnRenderSource implements ILodRenderSource, IColumnDatatype
}
/**
- * Creates a new ColumnRenderSource with data from the given DataInputStream.
+ * Creates a new ColumnRenderSource from the parsedColumnData.
*
- * @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
+ public ColumnRenderSource(DhSectionPos sectionPos, ColumnRenderLoader.ParsedColumnData parsedColumnData, IDhLevel level) throws IOException
{
- byte detailLevel = inputData.readByte();
- if (sectionPos.sectionDetail - SECTION_SIZE_OFFSET != detailLevel)
+ if (sectionPos.sectionDetail - SECTION_SIZE_OFFSET != parsedColumnData.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 = this.loadData(inputData, version, this.verticalSize);
+ this.verticalSize = parsedColumnData.verticalSize;
+ this.dataContainer = parsedColumnData.dataContainer;
this.airDataContainer = new int[AIR_SECTION_SIZE * AIR_SECTION_SIZE * this.verticalSize];
this.debugSourceFlags = new DebugSourceFlag[SECTION_SIZE * SECTION_SIZE];
@@ -117,50 +112,6 @@ public class ColumnRenderSource implements ILodRenderSource, IColumnDatatype
// datapoint manipulation //
//========================//
- /**
- * Attempts to parse and load the given DataInputStream based on its
- * render data version
- *
- * @throws IOException if the version isn't supported
- */
- private long[] loadData(DataInputStream inputData, int version, int verticalSize) throws IOException
- {
- switch (version)
- {
- case 1:
- return this.readDataV1(inputData, verticalSize);
- default:
- throw new IOException("Invalid Data: The data version [" + version + "] is not supported");
- }
- }
-
- private static long[] readDataV1(DataInputStream inputData, int tempMaxVerticalData) throws IOException
- {
- int maxNumberOfDataPoints = 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[maxNumberOfDataPoints];
- }
-
- this.isEmpty = false;
- byte[] data = new byte[maxNumberOfDataPoints * Long.BYTES];
- ByteBuffer byteBuffer = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN);
- inputData.readFully(data);
-
- long[] result = new long[maxNumberOfDataPoints];
- byteBuffer.asLongBuffer().get(result);
- if (tempMinHeight != this.yOffset)
- {
- for (int i = 0; i < result.length; i++)
- {
- result[i] = ColumnFormat.shiftHeightAndDepth(result[i], (short) (tempMinHeight - this.yOffset));
- }
- }
- return result;
- }
-
@Override
public void clearDataPoint(int posX, int posZ)
{