diff --git a/core/src/main/java/com/seibel/lod/core/dataObjects/transformers/ChunkToLodBuilder.java b/core/src/main/java/com/seibel/lod/core/dataObjects/transformers/ChunkToLodBuilder.java index 03791961a..18947a1cf 100644 --- a/core/src/main/java/com/seibel/lod/core/dataObjects/transformers/ChunkToLodBuilder.java +++ b/core/src/main/java/com/seibel/lod/core/dataObjects/transformers/ChunkToLodBuilder.java @@ -9,12 +9,16 @@ import com.seibel.lod.core.logging.ConfigBasedLogger; import com.seibel.lod.core.pos.DhChunkPos; import com.seibel.lod.core.util.*; import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper; +import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; +import com.seibel.lod.core.dependencyInjection.SingletonInjector; import org.apache.logging.log4j.LogManager; //FIXME: To-Be-Used class public class ChunkToLodBuilder { public static final ConfigBasedLogger LOGGER = new ConfigBasedLogger(LogManager.getLogger(), () -> Config.Client.Advanced.Debugging.DebugSwitch.logLodBuilderEvent.get()); + private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); + public static final long MAX_TICK_TIME_NS = 1000000000L / 20L; public static final int THREAD_COUNT = 1; @@ -56,8 +60,25 @@ public class ChunkToLodBuilder public void tick() { - if (runningCount.get() >= THREAD_COUNT) return; - if (taskToBuild.isEmpty()) return; + if (runningCount.get() >= THREAD_COUNT) + { + return; + } + else if (taskToBuild.isEmpty()) + { + return; + } + else if (!MC.playerExists()) + { + // MC hasn't finished loading (or is currently unloaded) + + // TODO these should be cleared whenever a level is unloaded, + // but for now, just assume any previous chunks are invalid if the player doesn't exist + taskToBuild.clear(); + return; + } + + for (int i = 0; i MAX_TICK_TIME_NS && !taskToBuild.isEmpty()) + if (System.nanoTime() - time > MAX_TICK_TIME_NS && !taskToBuild.isEmpty()) + { break; + } Task task = taskToBuild.pollFirst(); if (task == null) 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 adae1d7ed..0aaf67b9f 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 @@ -130,8 +130,6 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile 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 loadOrGetCached(Executor fileReaderThreads, IDhLevel level) { Object obj = this.data.get(); 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 c42a78bb1..8afb9205b 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 @@ -48,7 +48,10 @@ public class LodRenderSection return; } - this.loadFuture = this.renderSourceProvider.read(this.pos); + if (this.renderSource == null) + { + this.loadFuture = this.renderSourceProvider.read(this.pos); + } this.isRenderEnabled = true; } public void disableRender() diff --git a/core/src/main/java/com/seibel/lod/core/wrapperInterfaces/world/ILevelWrapper.java b/core/src/main/java/com/seibel/lod/core/wrapperInterfaces/world/ILevelWrapper.java index f815d823a..a593d49fc 100644 --- a/core/src/main/java/com/seibel/lod/core/wrapperInterfaces/world/ILevelWrapper.java +++ b/core/src/main/java/com/seibel/lod/core/wrapperInterfaces/world/ILevelWrapper.java @@ -66,4 +66,7 @@ public interface ILevelWrapper extends IDhApiLevelWrapper, IBindable @Override Object getWrappedMcObject_UNSAFE(); + // TODO implement onUnload + // necessary so ChunkToLodBuilder can have its cache cleared after the level closes + }