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 940f7f75a..dd96472a9 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
@@ -9,63 +9,93 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.*;
+/**
+ * Abstract for loading and creating {@link ILodRenderSource} objects
+ * from {@link RenderMetaDataFile}'s and {@link ILodDataSource}'s.
+ *
+ * Also holds all {@link AbstractRenderSourceLoader}'s
+ * that have been created to allow for migrating old render data formats.
+ */
public abstract class AbstractRenderSourceLoader
{
- public static final HashMultimap, AbstractRenderSourceLoader> loaderRegistry = HashMultimap.create();
- public static final HashMap> renderTypeIdRegistry = new HashMap<>();
+ public static final HashMultimap, AbstractRenderSourceLoader> LOADER_BY_SOURCE_TYPE = HashMultimap.create();
+ public static final HashMap> SOURCE_TYPE_BY_METADATA_VERSION = new HashMap<>();
public static AbstractRenderSourceLoader getLoader(long renderTypeId, byte loaderVersion)
{
- return loaderRegistry.get(renderTypeIdRegistry.get(renderTypeId)).stream()
- .filter(l -> Arrays.binarySearch(l.loaderSupportedVersions, loaderVersion) >= 0)
+ return LOADER_BY_SOURCE_TYPE.get(SOURCE_TYPE_BY_METADATA_VERSION.get(renderTypeId)).stream()
+ .filter(loader -> Arrays.binarySearch(loader.loaderSupportedRenderDataVersions, loaderVersion) >= 0)
.findFirst().orElse(null);
}
public static AbstractRenderSourceLoader getLoader(Class extends ILodRenderSource> clazz, byte loaderVersion)
{
- return loaderRegistry.get(clazz).stream()
- .filter(l -> Arrays.binarySearch(l.loaderSupportedVersions, loaderVersion) >= 0)
+ return LOADER_BY_SOURCE_TYPE.get(clazz).stream()
+ .filter(l -> Arrays.binarySearch(l.loaderSupportedRenderDataVersions, loaderVersion) >= 0)
.findFirst().orElse(null);
}
- public final Class extends ILodRenderSource> clazz;
+
+
+ public final Class extends ILodRenderSource> renderSourceClass;
public final long renderTypeId;
- public final byte[] loaderSupportedVersions;
+ public final byte[] loaderSupportedRenderDataVersions;
public final byte detailOffset;
- public AbstractRenderSourceLoader(Class extends ILodRenderSource> clazz, long renderTypeId, byte[] loaderSupportedVersions, byte detailOffset)
+
+
+ /**
+ * Will automatically add the new render source to the
+ * {@link AbstractRenderSourceLoader#LOADER_BY_SOURCE_TYPE}
+ *
+ * @throws IllegalArgumentException if another render source already exists for the given renderTypeId or supported render data versions
+ */
+ public AbstractRenderSourceLoader(Class extends ILodRenderSource> renderSourceClass, long renderTypeId, byte[] loaderSupportedRenderDataVersions, byte detailOffset) throws IllegalArgumentException
{
this.renderTypeId = renderTypeId;
- this.loaderSupportedVersions = loaderSupportedVersions;
- Arrays.sort(loaderSupportedVersions); // sort to allow fast access
- this.clazz = clazz;
- if (renderTypeIdRegistry.containsKey(renderTypeId) && renderTypeIdRegistry.get(renderTypeId) != clazz)
+ this.loaderSupportedRenderDataVersions = loaderSupportedRenderDataVersions;
+ Arrays.sort(loaderSupportedRenderDataVersions); // sort to allow fast access
+ this.renderSourceClass = renderSourceClass;
+ this.detailOffset = detailOffset;
+
+
+ // register the loader //
+
+ // validate there isn't another loader for the given renderTypeId
+ if (SOURCE_TYPE_BY_METADATA_VERSION.containsKey(renderTypeId)
+ && SOURCE_TYPE_BY_METADATA_VERSION.get(renderTypeId) != renderSourceClass)
{
throw new IllegalArgumentException("Loader for renderTypeId " + renderTypeId + " already registered with different class: "
- + renderTypeIdRegistry.get(renderTypeId) + " != " + clazz);
+ + SOURCE_TYPE_BY_METADATA_VERSION.get(renderTypeId) + " != " + renderSourceClass);
}
- Set loaders = loaderRegistry.get(clazz);
- if (loaders.stream().anyMatch(other -> {
- // see if any loaderSupportsVersion conflicts with this one
- for (byte otherVer : other.loaderSupportedVersions)
+ Set loaders = LOADER_BY_SOURCE_TYPE.get(renderSourceClass);
+
+ // validate there isn't another loader that supports the same render data version(s)
+ boolean loaderAlreadyExistsForDataVersion = loaders.stream().anyMatch(other ->
+ {
+ for (byte otherVer : other.loaderSupportedRenderDataVersions)
{
- if (Arrays.binarySearch(loaderSupportedVersions, otherVer) >= 0)
+ if (Arrays.binarySearch(loaderSupportedRenderDataVersions, otherVer) >= 0)
+ {
return true;
+ }
}
return false;
- }))
+ });
+ if (loaderAlreadyExistsForDataVersion)
{
- throw new IllegalArgumentException("Loader for class " + clazz + " that supports one of the version in "
- + Arrays.toString(loaderSupportedVersions) + " already registered!");
+ throw new IllegalArgumentException("Loader for class " + renderSourceClass + " that supports one of the render data versions in "
+ + Arrays.toString(loaderSupportedRenderDataVersions) + " already registered!");
}
- renderTypeIdRegistry.put(renderTypeId, clazz);
- loaderRegistry.put(clazz, this);
- this.detailOffset = detailOffset;
+
+ // register the loader
+ SOURCE_TYPE_BY_METADATA_VERSION.put(renderTypeId, renderSourceClass);
+ LOADER_BY_SOURCE_TYPE.put(renderSourceClass, this);
}
/** Can return null if the file is out of date or something */
- public abstract ILodRenderSource loadRender(RenderMetaDataFile renderFile, InputStream data, IDhLevel level) throws IOException;
- public abstract ILodRenderSource createRender(ILodDataSource dataSource, IDhClientLevel level);
-
+ 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 119bc1d77..222ab2b58 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
@@ -15,28 +15,38 @@ import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
+/**
+ * Can load {@link ColumnRenderSource}'s for the {@link ColumnRenderSource#LATEST_VERSION}
+ */
public class ColumnRenderLoader extends AbstractRenderSourceLoader
{
- public ColumnRenderLoader() {
- super(ColumnRenderSource.class, ColumnRenderSource.TYPE_ID, new byte[]{ColumnRenderSource.LATEST_VERSION}, ColumnRenderSource.SECTION_SIZE_OFFSET);
+ public ColumnRenderLoader()
+ {
+ super(ColumnRenderSource.class, ColumnRenderSource.TYPE_ID, new byte[]{ ColumnRenderSource.LATEST_VERSION }, ColumnRenderSource.SECTION_SIZE_OFFSET);
}
-
+
+
+
@Override
- public ILodRenderSource loadRender(RenderMetaDataFile dataFile, InputStream data, IDhLevel level) throws IOException {
- DataInputStream dis = new DataInputStream(data); // DO NOT CLOSE
- return new ColumnRenderSource(dataFile.pos, dis, dataFile.metaData.loaderVersion, level);
+ 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);
}
-
+
@Override
- public ILodRenderSource createRender(ILodDataSource dataSource, IDhClientLevel level) {
- if (dataSource instanceof FullDataSource) {
- return FullToColumnTransformer.transformFullDataToColumnData(level, (FullDataSource) dataSource);
- } else if (dataSource instanceof IIncompleteDataSource) {
- return FullToColumnTransformer.transformIncompleteDataToColumnData(level, (IIncompleteDataSource) dataSource);
- }
- LodUtil.assertNotReach();
- return null;
+ public ILodRenderSource createRenderSource(ILodDataSource dataSource, IDhClientLevel level)
+ {
+ if (dataSource instanceof FullDataSource) // TODO replace with Java 7 method
+ {
+ return FullToColumnTransformer.transformFullDataToColumnData(level, (FullDataSource) dataSource);
+ }
+ else if (dataSource instanceof IIncompleteDataSource)
+ {
+ return FullToColumnTransformer.transformIncompleteDataToColumnData(level, (IIncompleteDataSource) dataSource);
+ }
+ LodUtil.assertNotReach();
+ return null;
}
-
-
+
}
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 9fbf1e7c8..2f034e55f 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
@@ -29,6 +29,8 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicReference;
/**
+ * Stores the color data used when generating OpenGL buffers.
+ *
* @author Leetom
* @version 2022-10-5
*/
@@ -77,10 +79,10 @@ public class ColumnRenderSource implements ILodRenderSource, IColumnDatatype
*/
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.verticalSize = maxVerticalSize;
+ this.dataContainer = new long[SECTION_SIZE * SECTION_SIZE * verticalSize];
+ this.airDataContainer = new int[AIR_SECTION_SIZE * AIR_SECTION_SIZE * verticalSize];
+ this.debugSourceFlags = new DebugSourceFlag[SECTION_SIZE * SECTION_SIZE];
this.sectionPos = sectionPos;
this.yOffset = yOffset;
}
@@ -116,7 +118,8 @@ public class ColumnRenderSource implements ILodRenderSource, IColumnDatatype
//========================//
/**
- * Attempts to parse and load the given DataInputStream.
+ * Attempts to parse and load the given DataInputStream based on its
+ * render data version
*
* @throws IOException if the version isn't supported
*/
@@ -125,13 +128,13 @@ public class ColumnRenderSource implements ILodRenderSource, IColumnDatatype
switch (version)
{
case 1:
- return readDataV1(inputData, verticalSize);
+ return this.readDataV1(inputData, verticalSize);
default:
throw new IOException("Invalid Data: The data version [" + version + "] is not supported");
}
}
- private long[] readDataV1(DataInputStream inputData, int tempMaxVerticalData) throws IOException
+ private static long[] readDataV1(DataInputStream inputData, int tempMaxVerticalData) throws IOException
{
int maxNumberOfDataPoints = SECTION_SIZE * SECTION_SIZE * tempMaxVerticalData;
@@ -246,10 +249,10 @@ public class ColumnRenderSource implements ILodRenderSource, IColumnDatatype
/** @return true if this object had data written in every column */
boolean writeData(DataOutputStream outputStream) throws IOException
{
- outputStream.writeByte(getDataDetail());
+ outputStream.writeByte(this.getDataDetail());
outputStream.writeByte((byte) this.verticalSize);
- if (isEmpty)
+ if (this.isEmpty)
{
outputStream.writeByte(Short.MAX_VALUE & 0xFF);
outputStream.writeByte((Short.MAX_VALUE >> 8) & 0xFF);
@@ -266,9 +269,9 @@ public class ColumnRenderSource implements ILodRenderSource, IColumnDatatype
boolean allGenerated = true;
for (int x = 0; x < SECTION_SIZE * SECTION_SIZE; x++)
{
- for (int z = 0; z < verticalSize; z++)
+ for (int z = 0; z < this.verticalSize; z++)
{
- long currentDatapoint = dataContainer[x * verticalSize + z];
+ long currentDatapoint = this.dataContainer[x * this.verticalSize + z];
if (ColumnFormat.doesDataPointExist(currentDatapoint))
{
// TODO: the "1" is a placeholder debug line
@@ -277,7 +280,7 @@ public class ColumnRenderSource implements ILodRenderSource, IColumnDatatype
outputStream.writeLong(Long.reverseBytes(currentDatapoint));
}
- if (!ColumnFormat.doesDataPointExist(dataContainer[x]))
+ if (!ColumnFormat.doesDataPointExist(this.dataContainer[x]))
{
allGenerated = false;
}
@@ -453,7 +456,7 @@ public class ColumnRenderSource implements ILodRenderSource, IColumnDatatype
public void saveRender(IDhClientLevel level, RenderMetaDataFile file, OutputStream dataStream) throws IOException
{
DataOutputStream dos = new DataOutputStream(dataStream); // DO NOT CLOSE
- writeData(dos);
+ this.writeData(dos);
}
@Override
@@ -479,7 +482,7 @@ public class ColumnRenderSource implements ILodRenderSource, IColumnDatatype
{
for (int z = startZ; z < startZ + height; z++)
{
- debugSourceFlags[x * SECTION_SIZE + z] = flag;
+ this.debugSourceFlags[x * SECTION_SIZE + z] = flag;
}
}
}
@@ -500,19 +503,19 @@ public class ColumnRenderSource implements ILodRenderSource, IColumnDatatype
String SUBDATA_DELIMITER = ",";
StringBuilder stringBuilder = new StringBuilder();
- stringBuilder.append(sectionPos);
+ stringBuilder.append(this.sectionPos);
stringBuilder.append(LINE_DELIMITER);
- int size = sectionPos.getWidth().numberOfLodSectionsWide;
+ int size = this.sectionPos.getWidth().numberOfLodSectionsWide;
for (int z = 0; z < size; z++)
{
for (int x = 0; x < size; x++)
{
- for (int y = 0; y < verticalSize; y++)
+ for (int y = 0; y < this.verticalSize; y++)
{
//Converting the dataToHex
stringBuilder.append(Long.toHexString(getDataPoint(x, z, y)));
- if (y != verticalSize - 1)
+ if (y != this.verticalSize - 1)
stringBuilder.append(SUBDATA_DELIMITER);
}
diff --git a/core/src/main/java/com/seibel/lod/core/datatype/transform/DataRenderTransformer.java b/core/src/main/java/com/seibel/lod/core/datatype/transform/DataRenderTransformer.java
index bfac956f4..f91bc5a72 100644
--- a/core/src/main/java/com/seibel/lod/core/datatype/transform/DataRenderTransformer.java
+++ b/core/src/main/java/com/seibel/lod/core/datatype/transform/DataRenderTransformer.java
@@ -29,8 +29,8 @@ public class DataRenderTransformer
private static ILodRenderSource transform(ILodDataSource dataSource, IDhClientLevel level)
{
if (dataSource == null) return null;
- return ColumnRenderLoader.loaderRegistry.get(ColumnRenderSource.class)
- .stream().findFirst().get().createRender(dataSource, level);
+ return ColumnRenderLoader.LOADER_BY_SOURCE_TYPE.get(ColumnRenderSource.class)
+ .stream().findFirst().get().createRenderSource(dataSource, level);
}
}
diff --git a/core/src/main/java/com/seibel/lod/core/file/renderfile/RenderMetaDataFile.java b/core/src/main/java/com/seibel/lod/core/file/renderfile/RenderMetaDataFile.java
index d3e48b797..5e36f2d5f 100644
--- a/core/src/main/java/com/seibel/lod/core/file/renderfile/RenderMetaDataFile.java
+++ b/core/src/main/java/com/seibel/lod/core/file/renderfile/RenderMetaDataFile.java
@@ -71,7 +71,7 @@ public class RenderMetaDataFile extends AbstractMetaDataFile
throw new IOException("Invalid file: Data type loader not found: "
+ this.metaData.dataTypeId + "(v" + this.metaData.loaderVersion + ")");
}
- this.dataType = this.loader.clazz;
+ this.dataType = this.loader.renderSourceClass;
this.doesFileExist = true;
}
@@ -203,7 +203,7 @@ public class RenderMetaDataFile extends AbstractMetaDataFile
{
try (FileInputStream fio = getDataContent())
{
- data = this.loader.loadRender(this, fio, level);
+ data = this.loader.loadRenderSource(this, fio, level);
}
catch (IOException e)
{
diff --git a/core/src/main/java/com/seibel/lod/core/render/LodRenderSection.java b/core/src/main/java/com/seibel/lod/core/render/LodRenderSection.java
index 51f5f12bb..9d67b0427 100644
--- a/core/src/main/java/com/seibel/lod/core/render/LodRenderSection.java
+++ b/core/src/main/java/com/seibel/lod/core/render/LodRenderSection.java
@@ -1,5 +1,7 @@
package com.seibel.lod.core.render;
+import com.seibel.lod.api.enums.config.EVerticalQuality;
+import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.level.IDhClientLevel;
import com.seibel.lod.core.pos.DhSectionPos;
import com.seibel.lod.core.datatype.ILodRenderSource;
@@ -7,7 +9,8 @@ import com.seibel.lod.core.file.renderfile.IRenderSourceProvider;
import java.util.concurrent.CompletableFuture;
-public class LodRenderSection {
+public class LodRenderSection
+{
public final DhSectionPos pos;
/* Following used for LodQuadTree tick() method, and ONLY for that method! */
@@ -45,8 +48,10 @@ public class LodRenderSection {
isRenderEnabled = false;
}
- public void load(IRenderSourceProvider renderDataProvider) {
+ public void load(IRenderSourceProvider renderDataProvider)
+ {
provider = renderDataProvider;
+ this.previousQualitySetting = Config.Client.Graphics.Quality.verticalQuality.get();
}
public void reload(IRenderSourceProvider renderDataProvider) {
if (loadFuture != null) {
@@ -58,18 +63,24 @@ public class LodRenderSection {
lodRenderSource = null;
}
loadFuture = renderDataProvider.read(pos);
+ this.previousQualitySetting = Config.Client.Graphics.Quality.verticalQuality.get();
}
- public void tick(LodQuadTree quadTree, IDhClientLevel level) {
- if (loadFuture != null && loadFuture.isDone()) {
- lodRenderSource = loadFuture.join();
- loadFuture = null;
- if (isRenderEnabled) {
- lodRenderSource.enableRender(level, quadTree);
+ public void tick(LodQuadTree quadTree, IDhClientLevel level)
+ {
+ if (this.loadFuture != null && this.loadFuture.isDone())
+ {
+ this.lodRenderSource = this.loadFuture.join();
+ this.loadFuture = null;
+ if (this.isRenderEnabled)
+ {
+ this.lodRenderSource.enableRender(level, quadTree);
}
}
- if (lodRenderSource != null) {
- provider.refreshRenderSource(lodRenderSource);
+
+ if (this.lodRenderSource != null)
+ {
+ this.provider.refreshRenderSource(this.lodRenderSource);
}
}
@@ -97,9 +108,12 @@ public class LodRenderSection {
public boolean isLoading() {
return false;
}
-
- public boolean isOutdated() {
- return lodRenderSource != null && !lodRenderSource.isValid();
+
+ private EVerticalQuality previousQualitySetting = null;
+
+ public boolean isOutdated()
+ {
+ return this.previousQualitySetting != Config.Client.Graphics.Quality.verticalQuality.get() || (lodRenderSource != null && !lodRenderSource.isValid());
}
public ILodRenderSource getRenderSource() {