Fix WorldGen after restarting generation

This commit is contained in:
James Seibel
2025-11-15 12:08:03 -06:00
parent 254f51ea5e
commit f628a7f21e
3 changed files with 62 additions and 56 deletions
@@ -32,9 +32,11 @@ import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.logging.DhLogger;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.pos.DhChunkPos;
import com.seibel.distanthorizons.core.util.ExceptionUtil;
import com.seibel.distanthorizons.core.util.objects.EventTimer;
import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.util.gridList.ArrayGridList;
import com.seibel.distanthorizons.core.util.objects.UncheckedInterruptedException;
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.ChunkLightStorage;
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModChecker;
@@ -537,14 +539,10 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
PREF_LOGGER.debug(genEvent.timer.toString());
}
}
catch (CompletionException e)
catch (CompletionException | UncheckedInterruptedException e)
{
Throwable actualThrowable = e.getCause();
// interrupts mean the world generator is being shut down, no need to log that
boolean isShutdownException =
actualThrowable instanceof InterruptedException
|| actualThrowable instanceof ClosedByInterruptException;
boolean isShutdownException = ExceptionUtil.isShutdownException(e);
if (!isShutdownException)
{
EVENT_LOGGER.error("Completion error during world gen for min chunk pos ["+genEvent.minPos+"], error: ["+e.getMessage()+"].", e);
@@ -696,10 +694,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
actualThrowable = completionException.getCause();
}
// interrupts mean the world generator is being shut down, no need to log that
boolean isShutdownException =
actualThrowable instanceof InterruptedException
|| actualThrowable instanceof ClosedByInterruptException;
boolean isShutdownException = ExceptionUtil.isShutdownException(actualThrowable);
if (!isShutdownException)
{
CHUNK_LOAD_LOGGER.warn("DistantHorizons: Couldn't load or make chunk ["+chunkPos+"], error: ["+actualThrowable.getMessage()+"].", actualThrowable);
@@ -25,6 +25,7 @@ import java.util.function.Consumer;
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiDistantGeneratorMode;
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiWorldGenerationStep;
import com.seibel.distanthorizons.core.util.ExceptionUtil;
import com.seibel.distanthorizons.core.util.objects.UncheckedInterruptedException;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.pos.DhChunkPos;
@@ -33,6 +34,7 @@ import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.distanthorizons.core.logging.DhLogger;
import org.jetbrains.annotations.Nullable;
public final class GenerationEvent
{
@@ -49,7 +51,7 @@ public final class GenerationEvent
public EventTimer timer = null;
public long inQueueTime;
public long timeoutTime = -1;
public CompletableFuture<Void> future = null;
public final CompletableFuture<Void> future = new CompletableFuture<>();
public final Consumer<IChunkWrapper> resultConsumer;
@@ -76,56 +78,66 @@ public final class GenerationEvent
ExecutorService worldGeneratorThreadPool)
{
GenerationEvent generationEvent = new GenerationEvent(minPos, size, genEnvironment, generatorMode, target, resultConsumer);
generationEvent.future = CompletableFuture.supplyAsync(() ->
try
{
long runStartTime = System.nanoTime();
generationEvent.timeoutTime = runStartTime;
generationEvent.inQueueTime = runStartTime - generationEvent.inQueueTime;
generationEvent.timer = new EventTimer("setup");
BatchGenerationEnvironment.isDistantGeneratorThread.set(true);
try
worldGeneratorThreadPool.execute(() ->
{
genEnvironment.generateLodFromListAsync(generationEvent, (runnable) ->
try
{
worldGeneratorThreadPool.execute(() ->
long runStartTime = System.nanoTime();
generationEvent.timeoutTime = runStartTime;
generationEvent.inQueueTime = runStartTime - generationEvent.inQueueTime;
generationEvent.timer = new EventTimer("setup");
BatchGenerationEnvironment.isDistantGeneratorThread.set(true);
genEnvironment.generateLodFromListAsync(generationEvent, (runnable) ->
{
boolean alreadyMarked = BatchGenerationEnvironment.isCurrentThreadDistantGeneratorThread();
if (!alreadyMarked)
{
BatchGenerationEnvironment.isDistantGeneratorThread.set(true);
}
try
{
runnable.run();
}
catch (Throwable throwable)
{
handleWorldGenThrowable(generationEvent, throwable);
}
finally
worldGeneratorThreadPool.execute(() ->
{
boolean alreadyMarked = BatchGenerationEnvironment.isCurrentThreadDistantGeneratorThread();
if (!alreadyMarked)
{
BatchGenerationEnvironment.isDistantGeneratorThread.set(false);
BatchGenerationEnvironment.isDistantGeneratorThread.set(true);
}
}
try
{
runnable.run();
}
catch (Throwable throwable)
{
handleWorldGenThrowable(generationEvent, throwable);
}
finally
{
if (!alreadyMarked)
{
BatchGenerationEnvironment.isDistantGeneratorThread.set(false);
}
}
});
});
});
}
catch (Throwable initialThrowable)
{
handleWorldGenThrowable(generationEvent, initialThrowable);
}
finally
{
BatchGenerationEnvironment.isDistantGeneratorThread.remove();
}
return null;
}, worldGeneratorThreadPool);
generationEvent.future.complete(null);
}
catch (Throwable initialThrowable)
{
handleWorldGenThrowable(generationEvent, initialThrowable);
}
finally
{
BatchGenerationEnvironment.isDistantGeneratorThread.remove();
}
});
}
catch (RejectedExecutionException e)
{
generationEvent.future.completeExceptionally(e);
}
return generationEvent;
}
/** There's probably a better way to handle this, but it'll work for now */
@@ -137,9 +149,8 @@ public final class GenerationEvent
throwable = throwable.getCause();
}
if (throwable instanceof InterruptedException
|| throwable instanceof UncheckedInterruptedException
|| throwable instanceof RejectedExecutionException)
boolean isShutdownException = ExceptionUtil.isShutdownException(throwable);
if (isShutdownException)
{
// these exceptions can be ignored, generally they just mean
// the thread is busy so it'll need to try again later.