refactoring
This commit is contained in:
@@ -10,7 +10,7 @@ import java.io.InputStream;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Abstract for loading and creating {@link ILodRenderSource} objects
|
||||
* Abstract for loading and creating {@link IRenderSource} objects
|
||||
* from {@link RenderMetaDataFile}'s and {@link IFullDataSource}'s. <br><Br>
|
||||
*
|
||||
* Also holds all {@link AbstractRenderSourceLoader}'s
|
||||
@@ -18,8 +18,8 @@ import java.util.*;
|
||||
*/
|
||||
public abstract class AbstractRenderSourceLoader
|
||||
{
|
||||
public static final HashMultimap<Class<? extends ILodRenderSource>, AbstractRenderSourceLoader> LOADER_BY_SOURCE_TYPE = HashMultimap.create();
|
||||
public static final HashMap<Long, Class<? extends ILodRenderSource>> SOURCE_TYPE_BY_METADATA_VERSION = new HashMap<>();
|
||||
public static final HashMultimap<Class<? extends IRenderSource>, AbstractRenderSourceLoader> LOADER_BY_SOURCE_TYPE = HashMultimap.create();
|
||||
public static final HashMap<Long, Class<? extends IRenderSource>> SOURCE_TYPE_BY_METADATA_VERSION = new HashMap<>();
|
||||
|
||||
public static AbstractRenderSourceLoader getLoader(long renderTypeId, byte loaderVersion)
|
||||
{
|
||||
@@ -28,7 +28,7 @@ public abstract class AbstractRenderSourceLoader
|
||||
.findFirst().orElse(null);
|
||||
}
|
||||
|
||||
public static AbstractRenderSourceLoader getLoader(Class<? extends ILodRenderSource> clazz, byte loaderVersion)
|
||||
public static AbstractRenderSourceLoader getLoader(Class<? extends IRenderSource> clazz, byte loaderVersion)
|
||||
{
|
||||
return LOADER_BY_SOURCE_TYPE.get(clazz).stream()
|
||||
.filter(l -> Arrays.binarySearch(l.loaderSupportedRenderDataVersions, loaderVersion) >= 0)
|
||||
@@ -37,7 +37,7 @@ public abstract class AbstractRenderSourceLoader
|
||||
|
||||
|
||||
|
||||
public final Class<? extends ILodRenderSource> renderSourceClass;
|
||||
public final Class<? extends IRenderSource> renderSourceClass;
|
||||
public final long renderTypeId;
|
||||
public final byte[] loaderSupportedRenderDataVersions;
|
||||
public final byte detailOffset;
|
||||
@@ -50,7 +50,7 @@ public abstract class AbstractRenderSourceLoader
|
||||
*
|
||||
* @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
|
||||
public AbstractRenderSourceLoader(Class<? extends IRenderSource> renderSourceClass, long renderTypeId, byte[] loaderSupportedRenderDataVersions, byte detailOffset) throws IllegalArgumentException
|
||||
{
|
||||
this.renderTypeId = renderTypeId;
|
||||
this.loaderSupportedRenderDataVersions = loaderSupportedRenderDataVersions;
|
||||
@@ -99,8 +99,8 @@ public abstract class AbstractRenderSourceLoader
|
||||
* @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;
|
||||
public abstract IRenderSource loadRenderSource(RenderMetaDataFile renderFile, InputStream data, IDhLevel level) throws IOException;
|
||||
/** Should not return null */
|
||||
public abstract ILodRenderSource createRenderSource(IFullDataSource dataSource, IDhClientLevel level);
|
||||
public abstract IRenderSource createRenderSource(IFullDataSource dataSource, IDhClientLevel level);
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -17,7 +17,7 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
*
|
||||
* These are created via {@link com.seibel.lod.core.file.renderfile.ILodRenderSourceProvider ILodRenderSourceProvider}'s
|
||||
*/
|
||||
public interface ILodRenderSource
|
||||
public interface IRenderSource
|
||||
{
|
||||
DhSectionPos getSectionPos();
|
||||
|
||||
@@ -50,6 +50,6 @@ public interface ILodRenderSource
|
||||
void fastWrite(ChunkSizedData chunkData, IDhClientLevel level);
|
||||
|
||||
/** Overrides any data that has not been written directly using write(). Skips empty source dataPoints. */
|
||||
void updateFromRenderSource(ILodRenderSource source);
|
||||
void updateFromRenderSource(IRenderSource source);
|
||||
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class PlaceHolderRenderSource implements ILodRenderSource
|
||||
public class PlaceHolderRenderSource implements IRenderSource
|
||||
{
|
||||
final DhSectionPos pos;
|
||||
boolean isValid = true;
|
||||
@@ -57,6 +57,6 @@ public class PlaceHolderRenderSource implements ILodRenderSource
|
||||
public void fastWrite(ChunkSizedData chunkData, IDhClientLevel level) { /* TODO */ }
|
||||
|
||||
@Override
|
||||
public void updateFromRenderSource(ILodRenderSource source) { /* TODO */ }
|
||||
public void updateFromRenderSource(IRenderSource source) { /* TODO */ }
|
||||
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ 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;
|
||||
import com.seibel.lod.core.datatype.ILodRenderSource;
|
||||
import com.seibel.lod.core.datatype.IRenderSource;
|
||||
import com.seibel.lod.core.datatype.AbstractRenderSourceLoader;
|
||||
import com.seibel.lod.core.level.IDhLevel;
|
||||
import com.seibel.lod.core.file.renderfile.RenderMetaDataFile;
|
||||
@@ -34,7 +34,7 @@ public class ColumnRenderLoader extends AbstractRenderSourceLoader
|
||||
|
||||
|
||||
@Override
|
||||
public ILodRenderSource loadRenderSource(RenderMetaDataFile dataFile, InputStream data, IDhLevel level) throws IOException
|
||||
public IRenderSource loadRenderSource(RenderMetaDataFile dataFile, InputStream data, IDhLevel level) throws IOException
|
||||
{
|
||||
DataInputStream inputStream = new DataInputStream(data); // DO NOT CLOSE
|
||||
int dataFileVersion = dataFile.metaData.loaderVersion;
|
||||
@@ -49,7 +49,7 @@ public class ColumnRenderLoader extends AbstractRenderSourceLoader
|
||||
}
|
||||
|
||||
@Override
|
||||
public ILodRenderSource createRenderSource(IFullDataSource dataSource, IDhClientLevel level)
|
||||
public IRenderSource createRenderSource(IFullDataSource dataSource, IDhClientLevel level)
|
||||
{
|
||||
if (dataSource instanceof FullDataSource) // TODO replace with Java 7 method
|
||||
{
|
||||
|
||||
@@ -14,7 +14,7 @@ import com.seibel.lod.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.lod.core.level.IDhLevel;
|
||||
import com.seibel.lod.core.render.LodQuadTree;
|
||||
import com.seibel.lod.core.render.LodRenderSection;
|
||||
import com.seibel.lod.core.datatype.ILodRenderSource;
|
||||
import com.seibel.lod.core.datatype.IRenderSource;
|
||||
import com.seibel.lod.core.util.ColorUtil;
|
||||
import com.seibel.lod.core.util.objects.Reference;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
@@ -32,7 +32,7 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
* @author Leetom
|
||||
* @version 2022-2-7
|
||||
*/
|
||||
public class ColumnRenderSource implements ILodRenderSource, IColumnDatatype
|
||||
public class ColumnRenderSource implements IRenderSource, IColumnDatatype
|
||||
{
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
|
||||
@@ -248,7 +248,7 @@ public class ColumnRenderSource implements ILodRenderSource, IColumnDatatype
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFromRenderSource(ILodRenderSource source)
|
||||
public void updateFromRenderSource(IRenderSource source)
|
||||
{
|
||||
// TODO if we can only write this one type of data isn't it dangerous to have it in the interface?
|
||||
LodUtil.assertTrue(source instanceof ColumnRenderSource);
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
package com.seibel.lod.core.datatype.transform;
|
||||
|
||||
import com.seibel.lod.core.datatype.IFullDataSource;
|
||||
import com.seibel.lod.core.datatype.ILodRenderSource;
|
||||
import com.seibel.lod.core.datatype.IRenderSource;
|
||||
import com.seibel.lod.core.datatype.column.ColumnRenderLoader;
|
||||
import com.seibel.lod.core.datatype.column.ColumnRenderSource;
|
||||
import com.seibel.lod.core.level.IDhClientLevel;
|
||||
@@ -16,17 +16,17 @@ public class DataRenderTransformer
|
||||
public static final ExecutorService TRANSFORMER_THREADS
|
||||
= LodUtil.makeThreadPool(4, "Data/Render Transformer");
|
||||
|
||||
public static CompletableFuture<ILodRenderSource> transformDataSource(IFullDataSource data, IDhClientLevel level)
|
||||
public static CompletableFuture<IRenderSource> transformDataSource(IFullDataSource data, IDhClientLevel level)
|
||||
{
|
||||
return CompletableFuture.supplyAsync(() -> transform(data, level), TRANSFORMER_THREADS);
|
||||
}
|
||||
|
||||
public static CompletableFuture<ILodRenderSource> asyncTransformDataSource(CompletableFuture<IFullDataSource> data, IDhClientLevel level)
|
||||
public static CompletableFuture<IRenderSource> asyncTransformDataSource(CompletableFuture<IFullDataSource> data, IDhClientLevel level)
|
||||
{
|
||||
return data.thenApplyAsync((d) -> transform(d, level), TRANSFORMER_THREADS);
|
||||
}
|
||||
|
||||
private static ILodRenderSource transform(IFullDataSource dataSource, IDhClientLevel level)
|
||||
private static IRenderSource transform(IFullDataSource dataSource, IDhClientLevel level)
|
||||
{
|
||||
if (dataSource == null)
|
||||
{
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
package com.seibel.lod.core.datatype.transform;
|
||||
|
||||
import com.seibel.lod.core.datatype.IIncompleteFullDataSource;
|
||||
import com.seibel.lod.core.datatype.ILodRenderSource;
|
||||
import com.seibel.lod.core.datatype.IRenderSource;
|
||||
import com.seibel.lod.core.datatype.column.accessor.ColumnFormat;
|
||||
import com.seibel.lod.core.datatype.column.ColumnRenderSource;
|
||||
import com.seibel.lod.core.datatype.column.accessor.ColumnArrayView;
|
||||
@@ -66,7 +66,7 @@ public class FullToColumnTransformer {
|
||||
return columnSource;
|
||||
}
|
||||
|
||||
public static ILodRenderSource transformIncompleteDataToColumnData(IDhClientLevel level, IIncompleteFullDataSource data) {
|
||||
public static IRenderSource transformIncompleteDataToColumnData(IDhClientLevel level, IIncompleteFullDataSource data) {
|
||||
final DhSectionPos pos = data.getSectionPos();
|
||||
final byte dataDetail = data.getDataDetail();
|
||||
final int vertSize = Config.Client.Graphics.Quality.verticalQuality.get().calculateMaxVerticalData(data.getDataDetail());
|
||||
|
||||
@@ -117,15 +117,19 @@ public class FullDataMetaFile extends AbstractMetaDataFile
|
||||
return (this.metaData == null) ? 0 : this.metaData.dataVersion.get();
|
||||
}
|
||||
|
||||
public boolean isCacheVersionValid(long cacheVersion) {
|
||||
public boolean isCacheVersionValid(long cacheVersion)
|
||||
{
|
||||
debugCheck();
|
||||
boolean noWrite = writeQueue.get().queue.isEmpty();
|
||||
if (!noWrite) {
|
||||
boolean noWrite = this.writeQueue.get().queue.isEmpty();
|
||||
if (!noWrite)
|
||||
{
|
||||
return false;
|
||||
} else {
|
||||
MetaData getData = metaData;
|
||||
//NOTE: Do this instead of direct compare so values that wrapped around still works correctly.
|
||||
return (getData == null ? 0 : metaData.dataVersion.get()) - cacheVersion <= 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
MetaData getData = this.metaData;
|
||||
//NOTE: Do this instead of direct compare so values that wrapped around still work correctly.
|
||||
return (getData == null ? 0 : this.metaData.dataVersion.get()) - cacheVersion <= 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -354,31 +358,31 @@ public class FullDataMetaFile extends AbstractMetaDataFile
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Return whether any write has happened to the data
|
||||
private boolean applyWriteQueue(IFullDataSource data)
|
||||
{
|
||||
// Poll the write queue
|
||||
// First check if write queue is empty, then swap the write queue.
|
||||
// Must be done in this order to ensure isMemoryAddressValid work properly. See isMemoryAddressValid() for details.
|
||||
boolean isEmpty = writeQueue.get().queue.isEmpty();
|
||||
boolean isEmpty = this.writeQueue.get().queue.isEmpty();
|
||||
if (!isEmpty)
|
||||
{
|
||||
swapWriteQueue();
|
||||
int count = _backQueue.queue.size();
|
||||
for (ChunkSizedData chunk : _backQueue.queue)
|
||||
this.swapWriteQueue();
|
||||
int count = this._backQueue.queue.size();
|
||||
for (ChunkSizedData chunk : this._backQueue.queue)
|
||||
{
|
||||
data.update(chunk);
|
||||
}
|
||||
_backQueue.queue.clear();
|
||||
LOGGER.info("Updated Data file at {} for sect {} with {} chunk writes.", path, pos, count);
|
||||
this._backQueue.queue.clear();
|
||||
//LOGGER.info("Updated Data file at {} for sect {} with {} chunk writes.", path, pos, count);
|
||||
}
|
||||
return !isEmpty;
|
||||
}
|
||||
|
||||
|
||||
private FileInputStream getDataContent() throws IOException
|
||||
{
|
||||
FileInputStream fin = new FileInputStream(path);
|
||||
FileInputStream fin = new FileInputStream(this.path);
|
||||
int toSkip = METADATA_SIZE;
|
||||
while (toSkip > 0)
|
||||
{
|
||||
|
||||
+4
-4
@@ -1,6 +1,6 @@
|
||||
package com.seibel.lod.core.file.renderfile;
|
||||
|
||||
import com.seibel.lod.core.datatype.ILodRenderSource;
|
||||
import com.seibel.lod.core.datatype.IRenderSource;
|
||||
import com.seibel.lod.core.datatype.full.ChunkSizedData;
|
||||
import com.seibel.lod.core.pos.DhSectionPos;
|
||||
|
||||
@@ -12,17 +12,17 @@ import java.util.concurrent.CompletableFuture;
|
||||
* This represents LOD data that is stored in long term storage (IE LOD files stored on the hard drive) <br>
|
||||
* Example: {@link RenderFileHandler RenderFileHandler} <br><br>
|
||||
*
|
||||
* This is used to create {@link ILodRenderSource}'s
|
||||
* This is used to create {@link IRenderSource}'s
|
||||
*/
|
||||
public interface ILodRenderSourceProvider extends AutoCloseable
|
||||
{
|
||||
CompletableFuture<ILodRenderSource> read(DhSectionPos pos);
|
||||
CompletableFuture<IRenderSource> read(DhSectionPos pos);
|
||||
void addScannedFile(Collection<File> detectedFiles);
|
||||
void write(DhSectionPos sectionPos, ChunkSizedData chunkData);
|
||||
CompletableFuture<Void> flushAndSave();
|
||||
|
||||
/** Returns true if the data was refreshed, false otherwise */
|
||||
boolean refreshRenderSource(ILodRenderSource source);
|
||||
boolean refreshRenderSource(IRenderSource source);
|
||||
|
||||
/** Deletes any data stored in the render cache so it can be re-created */
|
||||
void deleteRenderCache();
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.seibel.lod.core.file.renderfile;
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.seibel.lod.core.datatype.IFullDataSource;
|
||||
import com.seibel.lod.core.datatype.PlaceHolderRenderSource;
|
||||
import com.seibel.lod.core.datatype.ILodRenderSource;
|
||||
import com.seibel.lod.core.datatype.IRenderSource;
|
||||
import com.seibel.lod.core.datatype.AbstractRenderSourceLoader;
|
||||
import com.seibel.lod.core.datatype.column.ColumnRenderSource;
|
||||
import com.seibel.lod.core.datatype.full.ChunkSizedData;
|
||||
@@ -35,7 +35,7 @@ public class RenderFileHandler implements ILodRenderSourceProvider
|
||||
|
||||
private final IDhClientLevel level;
|
||||
private final File saveDir;
|
||||
private final IFullDataSourceProvider dataSourceProvider;
|
||||
private final IFullDataSourceProvider fullDataSourceProvider;
|
||||
|
||||
private final ConcurrentHashMap<DhSectionPos, Object> cacheUpdateLockBySectionPos = new ConcurrentHashMap<>();
|
||||
|
||||
@@ -44,7 +44,7 @@ public class RenderFileHandler implements ILodRenderSourceProvider
|
||||
|
||||
public RenderFileHandler(IFullDataSourceProvider sourceProvider, IDhClientLevel level, File saveRootDir)
|
||||
{
|
||||
this.dataSourceProvider = sourceProvider;
|
||||
this.fullDataSourceProvider = sourceProvider;
|
||||
this.level = level;
|
||||
this.saveDir = saveRootDir;
|
||||
}
|
||||
@@ -154,7 +154,7 @@ public class RenderFileHandler implements ILodRenderSourceProvider
|
||||
|
||||
/** This call is concurrent. I.e. it supports multiple threads calling this method at the same time. */
|
||||
@Override
|
||||
public CompletableFuture<ILodRenderSource> read(DhSectionPos pos)
|
||||
public CompletableFuture<IRenderSource> read(DhSectionPos pos)
|
||||
{
|
||||
RenderMetaDataFile metaFile = this.filesBySectionPos.get(pos);
|
||||
if (metaFile == null)
|
||||
@@ -201,7 +201,7 @@ public class RenderFileHandler implements ILodRenderSourceProvider
|
||||
}
|
||||
|
||||
this.writeRecursively(sectionPos,chunkData);
|
||||
this.dataSourceProvider.write(sectionPos, chunkData);
|
||||
this.fullDataSourceProvider.write(sectionPos, chunkData);
|
||||
}
|
||||
|
||||
private void writeRecursively(DhSectionPos sectPos, ChunkSizedData chunkData)
|
||||
@@ -262,7 +262,7 @@ public class RenderFileHandler implements ILodRenderSourceProvider
|
||||
return new File(this.saveDir, pos.serialize() + ".lod");
|
||||
}
|
||||
|
||||
public CompletableFuture<ILodRenderSource> onCreateRenderFile(RenderMetaDataFile file)
|
||||
public CompletableFuture<IRenderSource> onCreateRenderFile(RenderMetaDataFile file)
|
||||
{
|
||||
final int vertSize = Config.Client.Graphics.Quality.verticalQuality
|
||||
.get().calculateMaxVerticalData((byte) (file.pos.sectionDetailLevel - ColumnRenderSource.SECTION_SIZE_OFFSET));
|
||||
@@ -271,18 +271,18 @@ public class RenderFileHandler implements ILodRenderSourceProvider
|
||||
new ColumnRenderSource(file.pos, vertSize, this.level.getMinY()));
|
||||
}
|
||||
|
||||
private void updateCache(ILodRenderSource data, RenderMetaDataFile file)
|
||||
private void updateCache(IRenderSource data, RenderMetaDataFile file)
|
||||
{
|
||||
if (this.cacheUpdateLockBySectionPos.putIfAbsent(file.pos, new Object()) != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final WeakReference<ILodRenderSource> dataRef = new WeakReference<>(data);
|
||||
CompletableFuture<IFullDataSource> fullDataSourceFuture = this.dataSourceProvider.read(data.getSectionPos());
|
||||
final WeakReference<IRenderSource> renderSourceReference = new WeakReference<>(data);
|
||||
CompletableFuture<IFullDataSource> fullDataSourceFuture = this.fullDataSourceProvider.read(data.getSectionPos());
|
||||
fullDataSourceFuture = fullDataSourceFuture.thenApply((dataSource) ->
|
||||
{
|
||||
if (dataRef.get() == null)
|
||||
if (renderSourceReference.get() == null)
|
||||
{
|
||||
throw new UncheckedInterruptedException();
|
||||
}
|
||||
@@ -294,9 +294,9 @@ public class RenderFileHandler implements ILodRenderSourceProvider
|
||||
return null;
|
||||
});
|
||||
|
||||
LOGGER.info("Recreating cache for {}", data.getSectionPos());
|
||||
//LOGGER.info("Recreating cache for {}", data.getSectionPos());
|
||||
DataRenderTransformer.asyncTransformDataSource(fullDataSourceFuture, this.level)
|
||||
.thenAccept((newRenderDataSource) -> this.write(dataRef.get(), file, newRenderDataSource, this.dataSourceProvider.getCacheVersion(data.getSectionPos())))
|
||||
.thenAccept((newRenderDataSource) -> this.write(renderSourceReference.get(), file, newRenderDataSource, this.fullDataSourceProvider.getCacheVersion(data.getSectionPos())))
|
||||
.exceptionally((ex) ->
|
||||
{
|
||||
if (!UncheckedInterruptedException.isThrowableInterruption(ex))
|
||||
@@ -307,19 +307,19 @@ public class RenderFileHandler implements ILodRenderSourceProvider
|
||||
}).thenRun(() -> this.cacheUpdateLockBySectionPos.remove(file.pos));
|
||||
}
|
||||
|
||||
public ILodRenderSource onRenderFileLoaded(ILodRenderSource data, RenderMetaDataFile file)
|
||||
public IRenderSource onRenderFileLoaded(IRenderSource data, RenderMetaDataFile file)
|
||||
{
|
||||
if (!this.dataSourceProvider.isCacheVersionValid(file.pos, file.metaData.dataVersion.get()))
|
||||
if (!this.fullDataSourceProvider.isCacheVersionValid(file.pos, file.metaData.dataVersion.get()))
|
||||
{
|
||||
this.updateCache(data, file);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
public ILodRenderSource onLoadingRenderFile(RenderMetaDataFile file) { return null; /* Default behavior: do nothing */ }
|
||||
public IRenderSource onLoadingRenderFile(RenderMetaDataFile file) { return null; /* Default behavior: do nothing */ }
|
||||
|
||||
private void write(ILodRenderSource target, RenderMetaDataFile file,
|
||||
ILodRenderSource newData, long newDataVersion)
|
||||
private void write(IRenderSource target, RenderMetaDataFile file,
|
||||
IRenderSource newData, long newDataVersion)
|
||||
{
|
||||
if (target == null || newData == null)
|
||||
{
|
||||
@@ -336,15 +336,15 @@ public class RenderFileHandler implements ILodRenderSourceProvider
|
||||
file.save(target, this.level);
|
||||
}
|
||||
|
||||
public void onReadRenderSourceFromCache(RenderMetaDataFile file, ILodRenderSource data)
|
||||
public void onReadRenderSourceFromCache(RenderMetaDataFile file, IRenderSource data)
|
||||
{
|
||||
if (!this.dataSourceProvider.isCacheVersionValid(file.pos, file.metaData.dataVersion.get()))
|
||||
if (!this.fullDataSourceProvider.isCacheVersionValid(file.pos, file.metaData.dataVersion.get()))
|
||||
{
|
||||
this.updateCache(data, file);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean refreshRenderSource(ILodRenderSource source)
|
||||
public boolean refreshRenderSource(IRenderSource source)
|
||||
{
|
||||
RenderMetaDataFile file = this.filesBySectionPos.get(source.getSectionPos());
|
||||
if (source instanceof PlaceHolderRenderSource)
|
||||
@@ -357,7 +357,7 @@ public class RenderFileHandler implements ILodRenderSourceProvider
|
||||
|
||||
LodUtil.assertTrue(file != null);
|
||||
LodUtil.assertTrue(file.metaData != null);
|
||||
if (!this.dataSourceProvider.isCacheVersionValid(file.pos, file.metaData.dataVersion.get()))
|
||||
if (!this.fullDataSourceProvider.isCacheVersionValid(file.pos, file.metaData.dataVersion.get()))
|
||||
{
|
||||
this.updateCache(source, file);
|
||||
return true;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.seibel.lod.core.file.renderfile;
|
||||
|
||||
import com.seibel.lod.core.datatype.ILodRenderSource;
|
||||
import com.seibel.lod.core.datatype.IRenderSource;
|
||||
import com.seibel.lod.core.datatype.AbstractRenderSourceLoader;
|
||||
import com.seibel.lod.core.datatype.full.ChunkSizedData;
|
||||
import com.seibel.lod.core.file.metaData.MetaData;
|
||||
@@ -25,7 +25,7 @@ public class RenderMetaDataFile extends AbstractMetaDataFile
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
|
||||
public AbstractRenderSourceLoader loader;
|
||||
public Class<? extends ILodRenderSource> dataType;
|
||||
public Class<? extends IRenderSource> dataType;
|
||||
|
||||
// The '?' type should either be:
|
||||
// SoftReference<LodRenderSource>, or - File that may still be loaded
|
||||
@@ -84,7 +84,7 @@ public class RenderMetaDataFile extends AbstractMetaDataFile
|
||||
DhLodPos chunkPos = new DhLodPos((byte) (chunkData.dataDetail + 4), chunkData.x, chunkData.z);
|
||||
LodUtil.assertTrue(this.pos.getSectionBBoxPos().overlaps(chunkPos), "Chunk pos {} doesn't overlap with section {}", chunkPos, pos);
|
||||
|
||||
CompletableFuture<ILodRenderSource> source = this._readCached(this.data.get());
|
||||
CompletableFuture<IRenderSource> source = this._readCached(this.data.get());
|
||||
if (source == null)
|
||||
{
|
||||
return;
|
||||
@@ -100,7 +100,7 @@ public class RenderMetaDataFile extends AbstractMetaDataFile
|
||||
return CompletableFuture.completedFuture(null); // No need to save if the file doesn't exist.
|
||||
}
|
||||
|
||||
CompletableFuture<ILodRenderSource> source = this._readCached(this.data.get());
|
||||
CompletableFuture<IRenderSource> source = this._readCached(this.data.get());
|
||||
if (source == null)
|
||||
{
|
||||
return CompletableFuture.completedFuture(null); // If there is no cached data, there is no need to save.
|
||||
@@ -111,7 +111,7 @@ public class RenderMetaDataFile extends AbstractMetaDataFile
|
||||
|
||||
// Suppress casting of CompletableFuture<?> to CompletableFuture<LodRenderSource>
|
||||
@SuppressWarnings("unchecked")
|
||||
private CompletableFuture<ILodRenderSource> _readCached(Object obj)
|
||||
private CompletableFuture<IRenderSource> _readCached(Object obj)
|
||||
{
|
||||
// Has file cached in RAM and not freed yet.
|
||||
if ((obj instanceof SoftReference<?>))
|
||||
@@ -119,9 +119,9 @@ public class RenderMetaDataFile extends AbstractMetaDataFile
|
||||
Object inner = ((SoftReference<?>) obj).get();
|
||||
if (inner != null)
|
||||
{
|
||||
LodUtil.assertTrue(inner instanceof ILodRenderSource);
|
||||
fileHandler.onReadRenderSourceFromCache(this, (ILodRenderSource) inner);
|
||||
return CompletableFuture.completedFuture((ILodRenderSource) inner);
|
||||
LodUtil.assertTrue(inner instanceof IRenderSource);
|
||||
fileHandler.onReadRenderSourceFromCache(this, (IRenderSource) inner);
|
||||
return CompletableFuture.completedFuture((IRenderSource) inner);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,18 +129,18 @@ public class RenderMetaDataFile extends AbstractMetaDataFile
|
||||
// Someone is already trying to complete it. so just return the obj.
|
||||
if ((obj instanceof CompletableFuture<?>))
|
||||
{
|
||||
return (CompletableFuture<ILodRenderSource>) obj;
|
||||
return (CompletableFuture<IRenderSource>) obj;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Cause: Generic Type runtime casting cannot safety check it.
|
||||
// However, the Union type ensures the 'data' should only contain the listed type.
|
||||
public CompletableFuture<ILodRenderSource> loadOrGetCached(Executor fileReaderThreads, IDhLevel level)
|
||||
public CompletableFuture<IRenderSource> loadOrGetCached(Executor fileReaderThreads, IDhLevel level)
|
||||
{
|
||||
Object obj = this.data.get();
|
||||
|
||||
CompletableFuture<ILodRenderSource> cached = this._readCached(obj);
|
||||
CompletableFuture<IRenderSource> cached = this._readCached(obj);
|
||||
if (cached != null)
|
||||
{
|
||||
return cached;
|
||||
@@ -149,7 +149,7 @@ public class RenderMetaDataFile extends AbstractMetaDataFile
|
||||
// Create an empty and non-completed future.
|
||||
// Note: I do this before actually filling in the future so that I can ensure only
|
||||
// one task is submitted to the thread pool.
|
||||
CompletableFuture<ILodRenderSource> future = new CompletableFuture<>();
|
||||
CompletableFuture<IRenderSource> future = new CompletableFuture<>();
|
||||
|
||||
// Would use faster and non-nesting Compare and exchange. But java 8 doesn't have it! :(
|
||||
boolean worked = this.data.compareAndSet(obj, future);
|
||||
@@ -197,7 +197,7 @@ public class RenderMetaDataFile extends AbstractMetaDataFile
|
||||
}
|
||||
|
||||
// Load the file.
|
||||
ILodRenderSource data;
|
||||
IRenderSource data;
|
||||
data = this.fileHandler.onLoadingRenderFile(this);
|
||||
if (data == null)
|
||||
{
|
||||
@@ -231,7 +231,7 @@ public class RenderMetaDataFile extends AbstractMetaDataFile
|
||||
return future;
|
||||
}
|
||||
|
||||
private static MetaData makeMetaData(ILodRenderSource data)
|
||||
private static MetaData makeMetaData(IRenderSource data)
|
||||
{
|
||||
AbstractRenderSourceLoader loader = AbstractRenderSourceLoader.getLoader(data.getClass(), data.getRenderVersion());
|
||||
return new MetaData(data.getSectionPos(), -1, -1,
|
||||
@@ -258,7 +258,7 @@ public class RenderMetaDataFile extends AbstractMetaDataFile
|
||||
return fin;
|
||||
}
|
||||
|
||||
public void save(ILodRenderSource data, IDhClientLevel level)
|
||||
public void save(IRenderSource data, IDhClientLevel level)
|
||||
{
|
||||
if (data.isEmpty())
|
||||
{
|
||||
@@ -273,7 +273,7 @@ public class RenderMetaDataFile extends AbstractMetaDataFile
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGGER.info("Saving updated render file v[{}] at sect {}", this.metaData.dataVersion.get(), this.pos);
|
||||
//LOGGER.info("Saving updated render file v[{}] at sect {}", this.metaData.dataVersion.get(), this.pos);
|
||||
try
|
||||
{
|
||||
super.writeData((out) -> data.saveRender(level, this, out));
|
||||
|
||||
@@ -50,7 +50,7 @@ public class DhClientLevel implements IDhClientLevel
|
||||
MC_CLIENT.getPlayerBlockPos().x, MC_CLIENT.getPlayerBlockPos().z, this.renderFileHandler);
|
||||
this.renderBufferHandler = new RenderBufferHandler(this.tree);
|
||||
this.level = level;
|
||||
FileScanUtil.scanFile(save, level, this.dataFileHandler, this.renderFileHandler);
|
||||
FileScanUtil.scanFiles(save, level, this.dataFileHandler, this.renderFileHandler);
|
||||
LOGGER.info("Started DHLevel for {} with saves at {}", level, save);
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ public class DhClientServerLevel implements IDhClientLevel, IDhServerLevel
|
||||
save.getDataFolder(level).mkdirs();
|
||||
save.getRenderCacheFolder(level).mkdirs();
|
||||
this.dataFileHandler = new GeneratedFullDataFileHandler(this, save.getDataFolder(level));
|
||||
FileScanUtil.scanFile(save, this.serverLevel, this.dataFileHandler, null);
|
||||
FileScanUtil.scanFiles(save, this.serverLevel, this.dataFileHandler, null);
|
||||
LOGGER.info("Started DHLevel for {} with saves at {}", level, save);
|
||||
this.f3Msg = new F3Screen.NestedMessage(this::f3Log);
|
||||
this.chunkToLodBuilder = new ChunkToLodBuilder();
|
||||
@@ -375,7 +375,7 @@ public class DhClientServerLevel implements IDhClientLevel, IDhServerLevel
|
||||
this.tree = new LodQuadTree(DhClientServerLevel.this, Config.Client.Graphics.Quality.lodChunkRenderDistance.get() * 16,
|
||||
MC_CLIENT.getPlayerBlockPos().x, MC_CLIENT.getPlayerBlockPos().z, this.renderFileHandler);
|
||||
this.renderBufferHandler = new RenderBufferHandler(this.tree);
|
||||
FileScanUtil.scanFile(thisParent.save, thisParent.serverLevel, null, this.renderFileHandler);
|
||||
FileScanUtil.scanFiles(thisParent.save, thisParent.serverLevel, null, this.renderFileHandler);
|
||||
this.renderer = new LodRenderer(this.renderBufferHandler);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ public class DhServerLevel implements IDhServerLevel
|
||||
this.level = level;
|
||||
save.getDataFolder(level).mkdirs();
|
||||
this.dataFileHandler = new FullDataFileHandler(this, save.getDataFolder(level)); //FIXME: GenerationQueue
|
||||
FileScanUtil.scanFile(save, level, this.dataFileHandler, null);
|
||||
FileScanUtil.scanFiles(save, level, this.dataFileHandler, null);
|
||||
LOGGER.info("Started DHLevel for {} with saves at {}", level, save);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
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.logging.DhLoggerBuilder;
|
||||
import com.seibel.lod.core.pos.DhSectionPos;
|
||||
import com.seibel.lod.core.datatype.ILodRenderSource;
|
||||
import com.seibel.lod.core.datatype.IRenderSource;
|
||||
import com.seibel.lod.core.file.renderfile.ILodRenderSourceProvider;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@@ -25,11 +23,11 @@ public class LodRenderSection
|
||||
// (Should always be 4 after tick() is done, or 0 only if this is an unloaded node)
|
||||
public byte childCount = 0;
|
||||
|
||||
private CompletableFuture<ILodRenderSource> loadFuture;
|
||||
private CompletableFuture<IRenderSource> loadFuture;
|
||||
private boolean isRenderEnabled = false;
|
||||
|
||||
// TODO: Should I provide a way to change the render source?
|
||||
private ILodRenderSource renderSource;
|
||||
private IRenderSource renderSource;
|
||||
private ILodRenderSourceProvider renderSourceProvider = null;
|
||||
|
||||
|
||||
@@ -154,7 +152,7 @@ public class LodRenderSection
|
||||
|
||||
public boolean isOutdated() { return this.renderSource != null && !this.renderSource.isValid(); }
|
||||
|
||||
public ILodRenderSource getRenderSource() { return this.renderSource; }
|
||||
public IRenderSource getRenderSource() { return this.renderSource; }
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.seibel.lod.core.render;
|
||||
|
||||
import com.seibel.lod.core.datatype.ILodRenderSource;
|
||||
import com.seibel.lod.core.datatype.IRenderSource;
|
||||
import com.seibel.lod.core.enums.ELodDirection;
|
||||
import com.seibel.lod.core.pos.Pos2D;
|
||||
import com.seibel.lod.core.pos.DhSectionPos;
|
||||
@@ -132,7 +132,7 @@ public class RenderBufferHandler {
|
||||
// If this fails, there may be concurrent modification of the quad tree
|
||||
// (as this update() should be called from the same thread that calls update() on the quad tree)
|
||||
LodUtil.assertTrue(section != null);
|
||||
ILodRenderSource container = section.getRenderSource();
|
||||
IRenderSource container = section.getRenderSource();
|
||||
|
||||
// Update self's render buffer state
|
||||
boolean shouldRender = section.canRender();
|
||||
|
||||
@@ -14,32 +14,45 @@ import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
// Static util class??
|
||||
public class FileScanUtil {
|
||||
public class FileScanUtil
|
||||
{
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
public static final int MAX_SCAN_DEPTH = 5;
|
||||
public static final String LOD_FILE_POSTFIX = ".lod";
|
||||
public static void scanFile(AbstractSaveStructure save, ILevelWrapper level,
|
||||
@Nullable IFullDataSourceProvider dataSource,
|
||||
@Nullable ILodRenderSourceProvider renderSource) {
|
||||
if (dataSource != null) {
|
||||
try (Stream<Path> pathStream = Files.walk(save.getDataFolder(level).toPath(), MAX_SCAN_DEPTH)) {
|
||||
dataSource.addScannedFile(pathStream.filter(
|
||||
path -> path.toFile().getName().endsWith(LOD_FILE_POSTFIX) && path.toFile().isFile()
|
||||
).map(Path::toFile).collect(Collectors.toList())
|
||||
);
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Failed to scan and collect data files for {} in {}", level, save, e);
|
||||
}
|
||||
}
|
||||
if (renderSource != null) {
|
||||
try (Stream<Path> pathStream = Files.walk(save.getRenderCacheFolder(level).toPath(), MAX_SCAN_DEPTH)) {
|
||||
renderSource.addScannedFile(pathStream.filter((
|
||||
path -> path.toFile().getName().endsWith(LOD_FILE_POSTFIX) && path.toFile().isFile())
|
||||
).map(Path::toFile).collect(Collectors.toList())
|
||||
);
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Failed to scan and collect data files for {} in {}", level, save, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void scanFiles(AbstractSaveStructure saveStructure, ILevelWrapper levelWrapper,
|
||||
@Nullable IFullDataSourceProvider dataSourceProvider,
|
||||
@Nullable ILodRenderSourceProvider renderSourceProvider)
|
||||
{
|
||||
if (dataSourceProvider != null)
|
||||
{
|
||||
try (Stream<Path> pathStream = Files.walk(saveStructure.getDataFolder(levelWrapper).toPath(), MAX_SCAN_DEPTH))
|
||||
{
|
||||
dataSourceProvider.addScannedFile(pathStream.filter(
|
||||
path -> path.toFile().getName().endsWith(LOD_FILE_POSTFIX) && path.toFile().isFile()
|
||||
).map(Path::toFile).collect(Collectors.toList())
|
||||
);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOGGER.error("Failed to scan and collect data files for {} in {}", levelWrapper, saveStructure, e);
|
||||
}
|
||||
}
|
||||
|
||||
if (renderSourceProvider != null)
|
||||
{
|
||||
try (Stream<Path> pathStream = Files.walk(saveStructure.getRenderCacheFolder(levelWrapper).toPath(), MAX_SCAN_DEPTH))
|
||||
{
|
||||
renderSourceProvider.addScannedFile(pathStream.filter((
|
||||
path -> path.toFile().getName().endsWith(LOD_FILE_POSTFIX) && path.toFile().isFile())
|
||||
).map(Path::toFile).collect(Collectors.toList())
|
||||
);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOGGER.error("Failed to scan and collect data files for {} in {}", levelWrapper, saveStructure, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user