Fix never ending world gen tasks

This commit is contained in:
James Seibel
2023-10-19 20:45:47 -05:00
parent b38b33e87e
commit fa03336a5d
@@ -284,12 +284,15 @@ public class WorldGenerationQueue implements IWorldGenerationQueue, IDebugRender
WorldGenTaskGroup closestTaskGroup = new WorldGenTaskGroup(closestTask.pos, (byte) 0); // TODO should 0 be replaced?
closestTaskGroup.worldGenTasks.add(closestTask); // TODO
InProgressWorldGenTaskGroup newInProgressTask = new InProgressWorldGenTaskGroup(closestTaskGroup);
InProgressWorldGenTaskGroup previousInProgressTask = this.inProgressGenTasksByLodPos.putIfAbsent(closestTask.pos, newInProgressTask);
if (previousInProgressTask == null)
if (!this.inProgressGenTasksByLodPos.containsKey(closestTask.pos))
{
// no task exists for this position, start one
this.startWorldGenTaskGroup(newInProgressTask);
InProgressWorldGenTaskGroup newTaskGroup = new InProgressWorldGenTaskGroup(closestTaskGroup);
boolean taskStarted = this.tryStartingWorldGenTaskGroup(newTaskGroup);
if (!taskStarted)
{
LOGGER.trace("Unable to start task: "+closestTask.pos+", skipping. Task position may have already been generated.");
}
}
else
{
@@ -330,10 +333,11 @@ public class WorldGenerationQueue implements IWorldGenerationQueue, IDebugRender
return true;
}
}
private void startWorldGenTaskGroup(InProgressWorldGenTaskGroup inProgressTaskGroup)
/** @return true if the task was started, false otherwise */
private boolean tryStartingWorldGenTaskGroup(InProgressWorldGenTaskGroup newTaskGroup)
{
byte taskDetailLevel = inProgressTaskGroup.group.dataDetail;
DhSectionPos taskPos = inProgressTaskGroup.group.pos;
byte taskDetailLevel = newTaskGroup.group.dataDetail;
DhSectionPos taskPos = newTaskGroup.group.pos;
byte granularity = (byte) (taskPos.getDetailLevel() - taskDetailLevel);
LodUtil.assertTrue(granularity >= this.minGranularity && granularity <= this.maxGranularity);
LodUtil.assertTrue(taskDetailLevel >= this.highestDataDetail && taskDetailLevel <= this.lowestDataDetail);
@@ -341,17 +345,17 @@ public class WorldGenerationQueue implements IWorldGenerationQueue, IDebugRender
DhChunkPos chunkPosMin = new DhChunkPos(taskPos.getSectionBBoxPos().getCornerBlockPos());
// check if this is a duplicate generation task
if (this.alreadyGeneratedPosHashSet.containsKey(inProgressTaskGroup.group.pos))
if (this.alreadyGeneratedPosHashSet.containsKey(newTaskGroup.group.pos))
{
// temporary solution to prevent generating the same section multiple times
LOGGER.trace("Duplicate generation section " + taskPos + " with granularity [" + granularity + "] at " + chunkPosMin + ". Skipping...");
// sending a success result is necessary to make sure the render sections are reloaded correctly
inProgressTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateSuccess(new DhSectionPos(granularity, taskPos.getX(), taskPos.getZ()))));
return;
newTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateSuccess(new DhSectionPos(granularity, taskPos.getX(), taskPos.getZ()))));
return false;
}
this.alreadyGeneratedPosHashSet.put(inProgressTaskGroup.group.pos, Thread.currentThread().getStackTrace());
this.alreadyGeneratedPosQueue.add(inProgressTaskGroup.group.pos);
this.alreadyGeneratedPosHashSet.put(newTaskGroup.group.pos, Thread.currentThread().getStackTrace());
this.alreadyGeneratedPosQueue.add(newTaskGroup.group.pos);
// remove extra tracked duplicate positions
while (this.alreadyGeneratedPosQueue.size() > MAX_ALREADY_GENERATED_COUNT)
@@ -364,28 +368,40 @@ public class WorldGenerationQueue implements IWorldGenerationQueue, IDebugRender
//LOGGER.info("Generating section "+taskPos+" with granularity "+granularity+" at "+chunkPosMin);
this.numberOfTasksQueued++;
inProgressTaskGroup.genFuture = this.startGenerationEvent(chunkPosMin, granularity, taskDetailLevel, inProgressTaskGroup.group::consumeChunkData);
inProgressTaskGroup.genFuture.whenComplete((voidObj, exception) ->
newTaskGroup.genFuture = this.startGenerationEvent(chunkPosMin, granularity, taskDetailLevel, newTaskGroup.group::consumeChunkData);
LodUtil.assertTrue(newTaskGroup.genFuture != null);
newTaskGroup.genFuture.whenComplete((voidObj, exception) ->
{
this.numberOfTasksQueued--;
if (exception != null)
try
{
// don't log the shutdown exceptions
if (!LodUtil.isInterruptOrReject(exception))
this.numberOfTasksQueued--;
if (exception != null)
{
LOGGER.error("Error generating data for section " + taskPos, exception);
// don't log the shutdown exceptions
if (!LodUtil.isInterruptOrReject(exception))
{
LOGGER.error("Error generating data for section " + taskPos, exception);
}
newTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateFail()));
}
inProgressTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateFail()));
else
{
//LOGGER.info("Section generation at "+pos+" completed");
newTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateSuccess(new DhSectionPos(granularity, taskPos.getX(), taskPos.getZ()))));
}
boolean worked = this.inProgressGenTasksByLodPos.remove(taskPos, newTaskGroup);
LodUtil.assertTrue(worked);
}
else
catch (Exception e)
{
//LOGGER.info("Section generation at "+pos+" completed");
inProgressTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateSuccess(new DhSectionPos(granularity, taskPos.getX(), taskPos.getZ()))));
LOGGER.error("Unexpected error completing world gen task: "+taskPos, e);
}
boolean worked = this.inProgressGenTasksByLodPos.remove(taskPos, inProgressTaskGroup);
LodUtil.assertTrue(worked);
});
this.inProgressGenTasksByLodPos.put(taskPos, newTaskGroup);
return true;
}
/**
* The chunkPos is always aligned to the granularity.
@@ -514,6 +530,7 @@ public class WorldGenerationQueue implements IWorldGenerationQueue, IDebugRender
if (genFuture == null)
{
// genFuture's shouldn't be null, but sometimes they are...
LOGGER.info("Null gen future: "+runningTaskGroup.group.pos);
return;
}