only run world gen for rendering levels

Also fix world gen progress getting stuck on a single level
This commit is contained in:
James Seibel
2026-04-11 21:40:28 -05:00
parent b4e0687e2a
commit 1d9bffe64e
10 changed files with 289 additions and 192 deletions
@@ -27,7 +27,7 @@ import com.seibel.distanthorizons.core.file.fullDatafile.V2.FullDataSourceProvid
import com.seibel.distanthorizons.core.util.delayedSaveCache.DelayedDataSourceSaveCache;
import com.seibel.distanthorizons.core.file.structure.ISaveStructure;
import com.seibel.distanthorizons.core.generation.DhLightingEngine;
import com.seibel.distanthorizons.core.generation.IFullDataSourceRetrievalQueue;
import com.seibel.distanthorizons.core.generation.queues.IFullDataSourceRetrievalQueue;
import com.seibel.distanthorizons.core.generation.tasks.DataSourceRetrievalResult;
import com.seibel.distanthorizons.core.generation.tasks.ERetrievalResultState;
import com.seibel.distanthorizons.core.level.IDhLevel;
@@ -22,10 +22,10 @@ package com.seibel.distanthorizons.core.file.fullDatafile;
import com.google.common.cache.CacheBuilder;
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
import com.seibel.distanthorizons.core.file.structure.ISaveStructure;
import com.seibel.distanthorizons.core.generation.RemoteWorldRetrievalQueue;
import com.seibel.distanthorizons.core.generation.queues.RemoteWorldRetrievalQueue;
import com.seibel.distanthorizons.core.generation.tasks.DataSourceRetrievalResult;
import com.seibel.distanthorizons.core.level.IDhLevel;
import com.seibel.distanthorizons.core.level.LodRequestModule;
import com.seibel.distanthorizons.core.generation.queues.LodRequestModule;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.generation.tasks.ERetrievalResultState;
import com.seibel.distanthorizons.core.multiplayer.client.SyncOnLoadRequestQueue;
@@ -0,0 +1,227 @@
package com.seibel.distanthorizons.core.generation.queues;
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiDistantGeneratorProgressDisplayLocation;
import com.seibel.distanthorizons.core.api.internal.ClientApi;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.level.DhServerLevel;
import com.seibel.distanthorizons.core.level.IDhLevel;
import com.seibel.distanthorizons.core.logging.DhLogger;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
import com.seibel.distanthorizons.core.util.FormatUtil;
import com.seibel.distanthorizons.core.util.ThreadUtil;
import com.seibel.distanthorizons.core.util.objects.RollingAverage;
import com.seibel.distanthorizons.core.util.threading.PriorityTaskPicker;
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
import java.time.Duration;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
/**
* Handles the {@link IFullDataSourceRetrievalQueue} and any other necessary world gen information.
*
* @see LodRequestModule
* @see IFullDataSourceRetrievalQueue
*/
public abstract class AbstractLodRequestState
{
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
/** static so we only send the disable message once per session */
private static long firstProgressMessageSentMs = 0;
public final IDhLevel dhLevel;
public final IFullDataSourceRetrievalQueue retrievalQueue;
private final ThreadPoolExecutor progressUpdaterThread = ThreadUtil.makeSingleDaemonThreadPool("World Gen Progress Updater");
private boolean progressUpdateThreadRunning = false;
//===========================//
// request queue and logging //
//===========================//
//region
public AbstractLodRequestState(IDhLevel dhLevel, IFullDataSourceRetrievalQueue retrievalQueue)
{
this.dhLevel = dhLevel;
this.retrievalQueue = retrievalQueue;
}
//endregion
//===========================//
// request queue and logging //
//===========================//
//region
/** @param targetPosForRequest the position that world generation should be centered around */
public void startRequestQueueAndSetTargetPos(DhBlockPos2D targetPosForRequest)
{
this.retrievalQueue.startAndSetTargetPos(targetPosForRequest);
this.startProgressUpdateThread();
}
private void startProgressUpdateThread()
{
// only start the thread once
if (!this.progressUpdateThreadRunning)
{
this.progressUpdateThreadRunning = true;
progressUpdaterThread.execute(() ->
{
while (this.progressUpdateThreadRunning)
{
try
{
this.sendRetrievalProgress();
// sleep so we only see an update once in a while
int sleepTimeInSec = Config.Common.WorldGenerator.generationProgressDisplayIntervalInSeconds.get();
Thread.sleep(sleepTimeInSec * 1_000L);
}
catch (Exception e)
{
LOGGER.error("Unexpected issue displaying chunk retrieval progress [" + e.getMessage() + "].", e);
}
}
});
}
}
private void sendRetrievalProgress()
{
// format the remaining chunks
int remainingChunkCount = this.retrievalQueue.getRetrievalEstimatedRemainingChunkCount();
remainingChunkCount += this.retrievalQueue.getQueuedChunkCount();
String remainingChunkCountStr = F3Screen.NUMBER_FORMAT.format(remainingChunkCount);
String message = "DH is generating chunks. ";
if (this.dhLevel.getClass() == DhServerLevel.class)
{
// server levels can have multiple world generators running at once,
// this helps us track of which queue is which
message += "For " + this.dhLevel.getLevelWrapper().getDimensionName() + " ";
}
message += remainingChunkCountStr + " left.";
// show a message about how to disable progress logging if requested
int msToShowDisableInstructions = Config.Common.WorldGenerator.generationProgressDisableMessageDisplayTimeInSeconds.get() * 1_000;
if (msToShowDisableInstructions > 0)
{
long timeSinceFirstMessageInMs = (System.currentTimeMillis() - firstProgressMessageSentMs);
// always show this message for the first tick
if (firstProgressMessageSentMs == 0
// show this message if there is still time
|| timeSinceFirstMessageInMs < msToShowDisableInstructions)
{
// append to the current message
message += " This message can be hidden in the DH config.";
}
}
// add the remaining time estimate if available
double chunksPerSec = this.getEstimatedChunksPerSecond();
if (chunksPerSec > 0)
{
long estimatedRemainingTime = (long) (remainingChunkCount / chunksPerSec);
message += " ETA: " + FormatUtil.formatEta(Duration.ofSeconds(estimatedRemainingTime));
if (Config.Common.WorldGenerator.generationProgressIncludeChunksPerSecond.get())
{
message += " at " + F3Screen.NUMBER_FORMAT.format(chunksPerSec) + " chunks/sec";
}
}
// only log if there are chunks needing to be generated
if (remainingChunkCount != 0)
{
// determine where to log
EDhApiDistantGeneratorProgressDisplayLocation displayLocation = Config.Common.WorldGenerator.showGenerationProgress.get();
if (displayLocation == EDhApiDistantGeneratorProgressDisplayLocation.OVERLAY)
{
ClientApi.INSTANCE.showOverlayMessageNextFrame(message);
}
else if (displayLocation == EDhApiDistantGeneratorProgressDisplayLocation.CHAT)
{
ClientApi.INSTANCE.showChatMessageNextFrame(message);
}
else if (displayLocation == EDhApiDistantGeneratorProgressDisplayLocation.LOG)
{
LOGGER.info(message);
}
// mark when the first message was sent
if (firstProgressMessageSentMs == 0)
{
firstProgressMessageSentMs = System.currentTimeMillis();
}
}
}
/** @return -1 if this method isn't supported or available */
public double getEstimatedChunksPerSecond()
{
RollingAverage avg = this.retrievalQueue.getRollingAverageChunkGenTimeInMs();
if (avg == null)
{
return -1;
}
PriorityTaskPicker.Executor executor = ThreadPoolUtil.getWorldGenExecutor();
int threadCount = 1;
if (executor != null)
{
threadCount = executor.getPoolSize();
}
// convert chunk generation time in milliseconds to chunks per second
double chunksPerSecond = (1 / avg.getAverage()) * 1_000;
// estimate the number of chunks that can be processed per second by all threads
// Note: this is probably higher than the actual number, we might want to drop this by 1 or 2 to give a more realistic estimate
chunksPerSecond = threadCount * chunksPerSecond;
return chunksPerSecond;
}
//endregion
//================//
// base overrides //
//================//
//region
public CompletableFuture<Void> closeAsync(boolean doInterrupt)
{
// this should stop the updater thread
this.progressUpdateThreadRunning = false;
return this.retrievalQueue.startClosingAsync(true, doInterrupt)
.exceptionally(e ->
{
LOGGER.error("Error during first stage of generation queue shutdown, Error: [" + e.getMessage() + "].", e);
return null;
}
).thenRun(this.retrievalQueue::close)
.exceptionally(e ->
{
LOGGER.error("Error during second stage of generation queue shutdown, Error: [" + e.getMessage() + "].", e);
return null;
});
}
//endregion
}
@@ -17,7 +17,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.core.generation;
package com.seibel.distanthorizons.core.generation.queues;
import com.seibel.distanthorizons.core.generation.tasks.DataSourceRetrievalResult;
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
@@ -42,6 +42,8 @@ import java.util.concurrent.CompletableFuture;
* Used by both world gen and server networking.
*
* @see LodQuadTree
* @see AbstractLodRequestState
* @see LodRequestModule
*/
public interface IFullDataSourceRetrievalQueue extends Closeable
{
@@ -17,39 +17,35 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.core.level;
package com.seibel.distanthorizons.core.generation.queues;
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiDistantGeneratorProgressDisplayLocation;
import com.seibel.distanthorizons.core.api.internal.ClientApi;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.file.fullDatafile.GeneratedFullDataSourceProvider;
import com.seibel.distanthorizons.core.generation.IFullDataSourceRetrievalQueue;
import com.seibel.distanthorizons.core.level.*;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
import com.seibel.distanthorizons.core.util.FormatUtil;
import com.seibel.distanthorizons.core.util.ThreadUtil;
import com.seibel.distanthorizons.core.util.objects.RollingAverage;
import com.seibel.distanthorizons.core.util.threading.PriorityTaskPicker;
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
import com.seibel.distanthorizons.core.world.DhApiWorldProxy;
import com.seibel.distanthorizons.core.logging.DhLogger;
import java.io.Closeable;
import java.time.Duration;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
/**
* Handles both single-player/server-side world gen and client side LOD requests.
*
* @see AbstractLodRequestState
* @see IFullDataSourceRetrievalQueue
*/
public class LodRequestModule implements Closeable
{
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
private final IDhLevel level;
private final GeneratedFullDataSourceProvider.IOnWorldGenCompleteListener onWorldGenCompleteListener;
private final ThreadPoolExecutor tickerThread;
@@ -63,6 +59,7 @@ public class LodRequestModule implements Closeable
//=============//
// constructor //
//=============//
//region
public LodRequestModule(
IDhLevel level,
@@ -71,20 +68,24 @@ public class LodRequestModule implements Closeable
Supplier<? extends AbstractLodRequestState> worldGenStateSupplier
)
{
this.level = level;
this.onWorldGenCompleteListener = onWorldGenCompleteListener;
this.dataSourceProvider = dataSourceProvider;
this.worldGenStateSupplier = worldGenStateSupplier;
String levelId = level.getLevelWrapper().getDhIdentifier();
String levelId = this.level.getLevelWrapper().getDhIdentifier();
this.tickerThread = ThreadUtil.makeSingleDaemonThreadPool("Request Module Ticker ["+levelId+"]");
this.tickerThread.execute(this::tickLoop);
}
//endregion
//=========//
// ticking //
//=========//
//region
private void tickLoop()
{
@@ -101,9 +102,23 @@ public class LodRequestModule implements Closeable
private void tick()
{
boolean shouldDoWorldGen = this.onWorldGenCompleteListener.shouldDoWorldGen();
// if the world is read only don't generate anything
shouldDoWorldGen &= !DhApiWorldProxy.INSTANCE.getReadOnly();
// don't generate chunks for client levels that aren't being rendered
// (this can happen when moving between dimensions)
if (this.level instanceof IDhClientLevel)
{
boolean isRendering = ((IDhClientLevel) this.level).isRendering();
if (!isRendering)
{
shouldDoWorldGen = false;
}
}
boolean isWorldGenRunning = this.isWorldGenRunning();
if (shouldDoWorldGen && !isWorldGenRunning)
{
@@ -130,11 +145,14 @@ public class LodRequestModule implements Closeable
}
}
//endregion
//===================//
// world gen control //
//===================//
//region
public void startWorldGen(GeneratedFullDataSourceProvider dataFileHandler, AbstractLodRequestState newWgs)
{
@@ -173,11 +191,14 @@ public class LodRequestModule implements Closeable
dataFileHandler.removeWorldGenCompleteListener(this.onWorldGenCompleteListener);
}
//endregion
//=======================//
// base method overrides //
//=======================//
//region
@Override
public void close()
@@ -205,11 +226,14 @@ public class LodRequestModule implements Closeable
}
}
//endregion
//=========//
// getters //
//=========//
//region
public boolean isWorldGenRunning() { return this.lodRequestStateRef.get() != null; }
@@ -241,170 +265,7 @@ public class LodRequestModule implements Closeable
worldGenState.retrievalQueue.addDebugMenuStringsToList(messageList);
}
//================//
// helper classes //
//================//
/** Handles the {@link IFullDataSourceRetrievalQueue} and any other necessary world gen information. */
public static abstract class AbstractLodRequestState
{
/** static so we only send the disable message once per session */
private static long firstProgressMessageSentMs = 0;
public IFullDataSourceRetrievalQueue retrievalQueue;
private static final ThreadPoolExecutor PROGRESS_UPDATER_THREAD = ThreadUtil.makeSingleDaemonThreadPool("World Gen Progress Updater");
private boolean progressUpdateThreadRunning = false;
/** @param targetPosForRequest the position that world generation should be centered around */
public void startRequestQueueAndSetTargetPos(DhBlockPos2D targetPosForRequest)
{
this.retrievalQueue.startAndSetTargetPos(targetPosForRequest);
this.startProgressUpdateThread();
}
private void startProgressUpdateThread()
{
// only start the thread once
if (!this.progressUpdateThreadRunning)
{
this.progressUpdateThreadRunning = true;
PROGRESS_UPDATER_THREAD.execute(() ->
{
while (this.progressUpdateThreadRunning)
{
try
{
this.sendRetrievalProgress();
// sleep so we only see an update once in a while
int sleepTimeInSec = Config.Common.WorldGenerator.generationProgressDisplayIntervalInSeconds.get();
Thread.sleep(sleepTimeInSec * 1_000L);
}
catch (Exception e)
{
LOGGER.error("Unexpected issue displaying chunk retrieval progress [" + e.getMessage() + "].", e);
}
}
});
}
}
private void sendRetrievalProgress()
{
// format the remaining chunks
int remainingChunkCount = this.retrievalQueue.getRetrievalEstimatedRemainingChunkCount();
remainingChunkCount += this.retrievalQueue.getQueuedChunkCount();
String remainingChunkCountStr = F3Screen.NUMBER_FORMAT.format(remainingChunkCount);
String message = "DH is generating chunks. " + remainingChunkCountStr + " left."; // TODO getting stuck at 32 chunks remaining
// show a message about how to disable progress logging if requested
int msToShowDisableInstructions = Config.Common.WorldGenerator.generationProgressDisableMessageDisplayTimeInSeconds.get() * 1_000;
if (msToShowDisableInstructions > 0)
{
long timeSinceFirstMessageInMs = (System.currentTimeMillis() - firstProgressMessageSentMs);
// always show this message for the first tick
if (firstProgressMessageSentMs == 0
// show this message if there is still time
|| timeSinceFirstMessageInMs < msToShowDisableInstructions)
{
// append to the current message
message += " This message can be hidden in the DH config.";
}
}
// add the remaining time estimate if available
double chunksPerSec = this.getEstimatedChunksPerSecond();
if (chunksPerSec > 0)
{
long estimatedRemainingTime = (long) (remainingChunkCount / chunksPerSec);
message += " ETA: " + FormatUtil.formatEta(Duration.ofSeconds(estimatedRemainingTime));
if (Config.Common.WorldGenerator.generationProgressIncludeChunksPerSecond.get())
{
message += " at " + F3Screen.NUMBER_FORMAT.format(chunksPerSec) + " chunks/sec";
}
}
// only log if there are chunks needing to be generated
if (remainingChunkCount != 0)
{
// determine where to log
EDhApiDistantGeneratorProgressDisplayLocation displayLocation = Config.Common.WorldGenerator.showGenerationProgress.get();
if (displayLocation == EDhApiDistantGeneratorProgressDisplayLocation.OVERLAY)
{
ClientApi.INSTANCE.showOverlayMessageNextFrame(message);
}
else if (displayLocation == EDhApiDistantGeneratorProgressDisplayLocation.CHAT)
{
ClientApi.INSTANCE.showChatMessageNextFrame(message);
}
else if (displayLocation == EDhApiDistantGeneratorProgressDisplayLocation.LOG)
{
LOGGER.info(message);
}
// mark when the first message was sent
if (firstProgressMessageSentMs == 0)
{
firstProgressMessageSentMs = System.currentTimeMillis();
}
}
}
/** @return -1 if this method isn't supported or available */
public double getEstimatedChunksPerSecond()
{
RollingAverage avg = this.retrievalQueue.getRollingAverageChunkGenTimeInMs();
if (avg == null)
{
return -1;
}
PriorityTaskPicker.Executor executor = ThreadPoolUtil.getWorldGenExecutor();
int threadCount = 1;
if (executor != null)
{
threadCount = executor.getPoolSize();
}
// convert chunk generation time in milliseconds to chunks per second
double chunksPerSecond = (1 / avg.getAverage()) * 1_000;
// estimate the number of chunks that can be processed per second by all threads
// Note: this is probably higher than the actual number, we might want to drop this by 1 or 2 to give a more realistic estimate
chunksPerSecond = threadCount * chunksPerSecond;
return chunksPerSecond;
}
CompletableFuture<Void> closeAsync(boolean doInterrupt)
{
// this should stop the updater thread
this.progressUpdateThreadRunning = false;
return this.retrievalQueue.startClosingAsync(true, doInterrupt)
.exceptionally(e ->
{
LOGGER.error("Error during first stage of generation queue shutdown, Error: ["+e.getMessage()+"].", e);
return null;
}
).thenRun(this.retrievalQueue::close)
.exceptionally(e ->
{
LOGGER.error("Error during second stage of generation queue shutdown, Error: ["+e.getMessage()+"].", e);
return null;
});
}
}
//endregion
@@ -1,4 +1,4 @@
package com.seibel.distanthorizons.core.generation;
package com.seibel.distanthorizons.core.generation.queues;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.file.fullDatafile.V2.FullDataSourceProviderV2;
@@ -15,7 +15,6 @@ import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.util.WorldGenUtil;
import com.seibel.distanthorizons.core.util.objects.RollingAverage;
import com.seibel.distanthorizons.core.logging.DhLogger;
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
import java.util.concurrent.*;
@@ -17,7 +17,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.core.generation;
package com.seibel.distanthorizons.core.generation.queues;
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiDistantGeneratorMode;
import com.seibel.distanthorizons.api.interfaces.override.worldGenerator.IDhApiWorldGenerator;
@@ -27,6 +27,7 @@ import com.seibel.distanthorizons.api.objects.data.IDhApiFullDataSource;
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.file.fullDatafile.V2.FullDataSourceProviderV2;
import com.seibel.distanthorizons.core.generation.DhLightingEngine;
import com.seibel.distanthorizons.core.generation.tasks.DataSourceRetrievalResult;
import com.seibel.distanthorizons.core.generation.tasks.DataSourceRetrievalTask;
import com.seibel.distanthorizons.core.level.IDhServerLevel;
@@ -27,7 +27,9 @@ import com.seibel.distanthorizons.core.enums.MinecraftTextFormat;
import com.seibel.distanthorizons.core.file.fullDatafile.V2.FullDataSourceProviderV2;
import com.seibel.distanthorizons.core.file.fullDatafile.RemoteFullDataSourceProvider;
import com.seibel.distanthorizons.core.file.structure.ISaveStructure;
import com.seibel.distanthorizons.core.generation.RemoteWorldRetrievalQueue;
import com.seibel.distanthorizons.core.generation.queues.RemoteWorldRetrievalQueue;
import com.seibel.distanthorizons.core.generation.queues.AbstractLodRequestState;
import com.seibel.distanthorizons.core.generation.queues.LodRequestModule;
import com.seibel.distanthorizons.core.logging.DhLogger;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.multiplayer.client.ClientNetworkState;
@@ -396,12 +398,10 @@ public class DhClientLevel extends AbstractDhLevel implements IDhClientLevel
//================//
//region
private static class LodRequestState extends LodRequestModule.AbstractLodRequestState
private static class LodRequestState extends AbstractLodRequestState
{
LodRequestState(DhClientLevel clientLevel, ClientNetworkState networkState)
{
this.retrievalQueue = new RemoteWorldRetrievalQueue(networkState, clientLevel);
}
{ super(clientLevel, new RemoteWorldRetrievalQueue(networkState, clientLevel)); }
}
//endregion
@@ -23,7 +23,10 @@ import com.seibel.distanthorizons.api.interfaces.override.worldGenerator.IDhApiW
import com.seibel.distanthorizons.core.file.fullDatafile.GeneratedFullDataSourceProvider;
import com.seibel.distanthorizons.core.file.structure.ISaveStructure;
import com.seibel.distanthorizons.core.generation.BatchGenerator;
import com.seibel.distanthorizons.core.generation.WorldGenerationQueue;
import com.seibel.distanthorizons.core.generation.queues.IFullDataSourceRetrievalQueue;
import com.seibel.distanthorizons.core.generation.queues.WorldGenerationQueue;
import com.seibel.distanthorizons.core.generation.queues.AbstractLodRequestState;
import com.seibel.distanthorizons.core.generation.queues.LodRequestModule;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.coreapi.DependencyInjection.WorldGeneratorInjector;
import com.seibel.distanthorizons.core.logging.DhLogger;
@@ -75,9 +78,11 @@ public class ServerLevelModule implements AutoCloseable
// helper classes //
//================//
public static class LodRequestState extends LodRequestModule.AbstractLodRequestState
public static class LodRequestState extends AbstractLodRequestState
{
LodRequestState(IDhServerLevel level)
{ super(level, createRetrievalQueue(level)); }
private static IFullDataSourceRetrievalQueue createRetrievalQueue(IDhServerLevel level)
{
IDhApiWorldGenerator worldGenerator = WorldGeneratorInjector.INSTANCE.get(level.getLevelWrapper());
if (worldGenerator == null)
@@ -88,9 +93,11 @@ public class ServerLevelModule implements AutoCloseable
// since core world generator's should have the lowest override priority
WorldGeneratorInjector.INSTANCE.bind(level.getLevelWrapper(), worldGenerator);
}
this.retrievalQueue = new WorldGenerationQueue(worldGenerator, level);
return new WorldGenerationQueue(worldGenerator, level);
}
}
}
@@ -1,7 +1,7 @@
package com.seibel.distanthorizons.core.multiplayer.client;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.generation.RemoteWorldRetrievalQueue;
import com.seibel.distanthorizons.core.generation.queues.RemoteWorldRetrievalQueue;
import com.seibel.distanthorizons.core.generation.tasks.DataSourceRetrievalResult;
import com.seibel.distanthorizons.core.level.DhClientLevel;
import com.seibel.distanthorizons.core.pos.DhSectionPos;