refactoring

This commit is contained in:
James Seibel
2023-02-13 21:02:06 -06:00
parent 0cb46c9b57
commit 92a8e16375
17 changed files with 133 additions and 118 deletions
@@ -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);
}
@@ -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);
@@ -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)
{
@@ -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)
{
@@ -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);
}
}
}
}