Fix gen tasks sometimes not submitting after LOD level changes
This commit is contained in:
+1
-3
@@ -21,7 +21,6 @@ package com.seibel.distanthorizons.core.file.fullDatafile;
|
|||||||
|
|
||||||
import com.seibel.distanthorizons.api.enums.config.EDhApiDataCompressionMode;
|
import com.seibel.distanthorizons.api.enums.config.EDhApiDataCompressionMode;
|
||||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||||
import com.seibel.distanthorizons.core.api.internal.SharedApi;
|
|
||||||
import com.seibel.distanthorizons.core.config.Config;
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV1;
|
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV1;
|
||||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
||||||
@@ -41,7 +40,6 @@ import com.seibel.distanthorizons.core.sql.repo.FullDataSourceV2Repo;
|
|||||||
import com.seibel.distanthorizons.core.util.ThreadUtil;
|
import com.seibel.distanthorizons.core.util.ThreadUtil;
|
||||||
import com.seibel.distanthorizons.core.util.objects.DataCorruptedException;
|
import com.seibel.distanthorizons.core.util.objects.DataCorruptedException;
|
||||||
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
|
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
|
||||||
import com.seibel.distanthorizons.core.world.EWorldEnvironment;
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||||
import it.unimi.dsi.fastutil.longs.LongArrayList;
|
import it.unimi.dsi.fastutil.longs.LongArrayList;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
@@ -606,7 +604,7 @@ public class FullDataSourceProviderV2
|
|||||||
|
|
||||||
/** @return true if the position was queued, false if not */
|
/** @return true if the position was queued, false if not */
|
||||||
@Nullable
|
@Nullable
|
||||||
public CompletableFuture<WorldGenResult> queuePositionForRetrieval(Long genPos) { return null; }
|
public CompletableFuture<WorldGenResult> queuePositionForRetrieval(long genPos, boolean allowAboveMaxGenRequests) { return null; }
|
||||||
|
|
||||||
/** does nothing if the given position isn't present in the queue */
|
/** does nothing if the given position isn't present in the queue */
|
||||||
public void removeRetrievalRequestIf(DhSectionPos.ICancelablePrimitiveLongConsumer removeIf) { }
|
public void removeRetrievalRequestIf(DhSectionPos.ICancelablePrimitiveLongConsumer removeIf) { }
|
||||||
|
|||||||
+14
-8
@@ -63,10 +63,10 @@ public class GeneratedFullDataSourceProvider extends FullDataSourceProviderV2 im
|
|||||||
* TODO this should be dynamically allocated based on CPU load
|
* TODO this should be dynamically allocated based on CPU load
|
||||||
* and abilities.
|
* and abilities.
|
||||||
*/
|
*/
|
||||||
public static final int MAX_WORLD_GEN_REQUESTS_PER_THREAD = 20;
|
public static final int MAX_WORLD_GEN_REQUESTS_PER_THREAD = 20;
|
||||||
|
|
||||||
|
|
||||||
private final AtomicReference<IFullDataSourceRetrievalQueue> worldGenQueueRef = new AtomicReference<>(null);
|
protected final AtomicReference<IFullDataSourceRetrievalQueue> worldGenQueueRef = new AtomicReference<>(null);
|
||||||
private final ArrayList<IOnWorldGenCompleteListener> onWorldGenTaskCompleteListeners = new ArrayList<>();
|
private final ArrayList<IOnWorldGenCompleteListener> onWorldGenTaskCompleteListeners = new ArrayList<>();
|
||||||
|
|
||||||
protected final DelayedFullDataSourceSaveCache delayedFullDataSourceSaveCache = new DelayedFullDataSourceSaveCache(this::onDataSourceSave, 5_000);
|
protected final DelayedFullDataSourceSaveCache delayedFullDataSourceSaveCache = new DelayedFullDataSourceSaveCache(this::onDataSourceSave, 5_000);
|
||||||
@@ -173,8 +173,7 @@ public class GeneratedFullDataSourceProvider extends FullDataSourceProviderV2 im
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
IFullDataSourceRetrievalQueue worldGenQueue = this.worldGenQueueRef.get();
|
if (this.worldGenQueueRef.get() == null)
|
||||||
if (worldGenQueue == null)
|
|
||||||
{
|
{
|
||||||
// we can't queue anything if the world generator isn't set up yet
|
// we can't queue anything if the world generator isn't set up yet
|
||||||
return false;
|
return false;
|
||||||
@@ -211,13 +210,11 @@ public class GeneratedFullDataSourceProvider extends FullDataSourceProviderV2 im
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
// don't queue additional world gen requests beyond the max allotted count
|
|
||||||
return worldGenQueue.getWaitingTaskCount() < maxQueueCount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<WorldGenResult> queuePositionForRetrieval(Long genPos)
|
public CompletableFuture<WorldGenResult> queuePositionForRetrieval(long genPos, boolean allowAboveMaxGenRequests)
|
||||||
{
|
{
|
||||||
IFullDataSourceRetrievalQueue worldGenQueue = this.worldGenQueueRef.get();
|
IFullDataSourceRetrievalQueue worldGenQueue = this.worldGenQueueRef.get();
|
||||||
if (worldGenQueue == null)
|
if (worldGenQueue == null)
|
||||||
@@ -225,6 +222,15 @@ public class GeneratedFullDataSourceProvider extends FullDataSourceProviderV2 im
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!allowAboveMaxGenRequests)
|
||||||
|
{
|
||||||
|
int maxQueueCount = MAX_WORLD_GEN_REQUESTS_PER_THREAD * Config.Common.MultiThreading.numberOfWorldGenerationThreads.get();
|
||||||
|
if (worldGenQueue.getWaitingTaskCount() >= maxQueueCount)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
WorldGenTaskTracker genTaskTracker = new WorldGenTaskTracker(genPos);
|
WorldGenTaskTracker genTaskTracker = new WorldGenTaskTracker(genPos);
|
||||||
CompletableFuture<WorldGenResult> worldGenFuture = worldGenQueue.submitRetrievalTask(genPos, (byte) (DhSectionPos.getDetailLevel(genPos) - DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL), genTaskTracker);
|
CompletableFuture<WorldGenResult> worldGenFuture = worldGenQueue.submitRetrievalTask(genPos, (byte) (DhSectionPos.getDetailLevel(genPos) - DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL), genTaskTracker);
|
||||||
worldGenFuture.whenComplete((genTaskResult, ex) ->
|
worldGenFuture.whenComplete((genTaskResult, ex) ->
|
||||||
|
|||||||
+20
-3
@@ -20,18 +20,20 @@
|
|||||||
package com.seibel.distanthorizons.core.file.fullDatafile;
|
package com.seibel.distanthorizons.core.file.fullDatafile;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
||||||
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
import com.seibel.distanthorizons.core.file.structure.ISaveStructure;
|
import com.seibel.distanthorizons.core.file.structure.ISaveStructure;
|
||||||
import com.seibel.distanthorizons.core.generation.RemoteWorldRetrievalQueue;
|
import com.seibel.distanthorizons.core.generation.RemoteWorldRetrievalQueue;
|
||||||
|
import com.seibel.distanthorizons.core.generation.tasks.WorldGenResult;
|
||||||
import com.seibel.distanthorizons.core.level.IDhLevel;
|
import com.seibel.distanthorizons.core.level.IDhLevel;
|
||||||
import com.seibel.distanthorizons.core.level.WorldGenModule;
|
import com.seibel.distanthorizons.core.level.WorldGenModule;
|
||||||
import com.seibel.distanthorizons.core.multiplayer.client.SyncOnLoadRequestQueue;
|
import com.seibel.distanthorizons.core.multiplayer.client.SyncOnLoadRequestQueue;
|
||||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
|
||||||
import com.seibel.distanthorizons.coreapi.util.BitShiftUtil;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -40,6 +42,8 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
*/
|
*/
|
||||||
public class RemoteFullDataSourceProvider extends GeneratedFullDataSourceProvider
|
public class RemoteFullDataSourceProvider extends GeneratedFullDataSourceProvider
|
||||||
{
|
{
|
||||||
|
private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private final SyncOnLoadRequestQueue syncOnLoadRequestQueue;
|
private final SyncOnLoadRequestQueue syncOnLoadRequestQueue;
|
||||||
private final Set<Long> visitedPositions = ConcurrentHashMap.newKeySet();
|
private final Set<Long> visitedPositions = ConcurrentHashMap.newKeySet();
|
||||||
@@ -123,6 +127,19 @@ public class RemoteFullDataSourceProvider extends GeneratedFullDataSourceProvide
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<WorldGenResult> queuePositionForRetrieval(long genPos, boolean allowAboveMaxGenRequests)
|
||||||
|
{
|
||||||
|
RemoteWorldRetrievalQueue worldGenQueue = (RemoteWorldRetrievalQueue) this.worldGenQueueRef.get();
|
||||||
|
if (worldGenQueue == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.queuePositionForRetrieval(genPos, worldGenQueue.isPosCloserThanFarthestWaiting(new DhBlockPos2D(MC_CLIENT.getPlayerBlockPos()), genPos));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//==========//
|
//==========//
|
||||||
// shutdown //
|
// shutdown //
|
||||||
|
|||||||
+14
-10
@@ -183,7 +183,7 @@ public abstract class AbstractFullDataNetworkRequestQueue implements IDebugRende
|
|||||||
Map.Entry<Long, RequestQueueEntry> mapEntry = this.waitingTasksBySectionPos
|
Map.Entry<Long, RequestQueueEntry> mapEntry = this.waitingTasksBySectionPos
|
||||||
.entrySet().stream()
|
.entrySet().stream()
|
||||||
.filter(task -> task.getValue().networkDataSourceFuture == null)
|
.filter(task -> task.getValue().networkDataSourceFuture == null)
|
||||||
.min(Comparator.comparingInt(x -> posDistanceSquared(targetPos, x.getKey())))
|
.min(Comparator.comparingInt(x -> DhSectionPos.getChebyshevSignedBlockDistance(x.getKey(), targetPos)))
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
|
|
||||||
if (mapEntry == null)
|
if (mapEntry == null)
|
||||||
@@ -305,6 +305,19 @@ public abstract class AbstractFullDataNetworkRequestQueue implements IDebugRende
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean isPosCloserThanFarthestWaiting(DhBlockPos2D targetPos, long pos)
|
||||||
|
{
|
||||||
|
Long farthestPos = this.waitingTasksBySectionPos
|
||||||
|
.keySet().stream()
|
||||||
|
.max(Comparator.comparingInt(x -> DhSectionPos.getChebyshevSignedBlockDistance(x, targetPos)))
|
||||||
|
.orElse(null);
|
||||||
|
if (farthestPos == null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DhSectionPos.getChebyshevSignedBlockDistance(pos, targetPos) <= DhSectionPos.getChebyshevSignedBlockDistance(farthestPos, targetPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//=========================================//
|
//=========================================//
|
||||||
@@ -404,15 +417,6 @@ public abstract class AbstractFullDataNetworkRequestQueue implements IDebugRende
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
//================//
|
|
||||||
// helper methods //
|
|
||||||
//================//
|
|
||||||
|
|
||||||
protected static int posDistanceSquared(DhBlockPos2D targetPos, long pos)
|
|
||||||
{ return (int) DhSectionPos.getCenterBlockPos(pos).distSquared(targetPos); }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//================//
|
//================//
|
||||||
// helper classes //
|
// helper classes //
|
||||||
//================//
|
//================//
|
||||||
|
|||||||
+1
-1
@@ -246,7 +246,7 @@ public class FullDataSourceRequestHandler
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOGGER.info("sending - queueing [" + DhSectionPos.toString(pos) + "]");
|
LOGGER.info("sending - queueing [" + DhSectionPos.toString(pos) + "]");
|
||||||
this.fullDataSourceProvider().queuePositionForRetrieval(pos);
|
this.fullDataSourceProvider().queuePositionForRetrieval(pos, true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -475,14 +475,8 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable
|
|||||||
// queue from last to first to prevent shifting the array unnecessarily
|
// queue from last to first to prevent shifting the array unnecessarily
|
||||||
for (int i = this.missingGenerationPos.size() - 1; i >= 0; i--)
|
for (int i = this.missingGenerationPos.size() - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
if (!this.fullDataSourceProvider.canQueueRetrieval())
|
|
||||||
{
|
|
||||||
// the data source provider isn't accepting any more jobs
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
long pos = this.missingGenerationPos.removeLong(i);
|
long pos = this.missingGenerationPos.removeLong(i);
|
||||||
boolean positionQueued = (this.fullDataSourceProvider.queuePositionForRetrieval(pos) != null);
|
boolean positionQueued = (this.fullDataSourceProvider.queuePositionForRetrieval(pos, false) != null);
|
||||||
if (!positionQueued)
|
if (!positionQueued)
|
||||||
{
|
{
|
||||||
// shouldn't normally happen, but just in case
|
// shouldn't normally happen, but just in case
|
||||||
|
|||||||
Reference in New Issue
Block a user