WorldGen: Added thread timeout failsafe
This commit is contained in:
@@ -121,9 +121,10 @@ public class Config extends ConfigGui
|
||||
@Entry
|
||||
public static FogDrawMode fogDrawMode = IFogQuality.FOG_DRAW_MODE_DEFAULT;
|
||||
|
||||
// FIXME: Currently worldFogColor gives black.
|
||||
@Category("client.graphics.fogQuality")
|
||||
@Entry
|
||||
public static FogColorMode fogColorMode = IFogQuality.FOG_COLOR_MODE_DEFAULT;
|
||||
public static FogColorMode fogColorMode = FogColorMode.USE_SKY_COLOR; //IFogQuality.FOG_COLOR_MODE_DEFAULT;
|
||||
|
||||
@Category("client.graphics.fogQuality")
|
||||
@Entry
|
||||
|
||||
+16
-41
@@ -4,8 +4,10 @@ import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.seibel.lod.common.wrappers.world.WorldWrapper;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.WorldGenerationStep.GenerationEvent;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.WorldGenerationStep.Steps;
|
||||
import com.seibel.lod.core.builders.lodBuilding.LodBuilder;
|
||||
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
|
||||
@@ -21,44 +23,14 @@ import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractExperimenta
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
|
||||
public class ExperimentalGenerator extends AbstractExperimentalWorldGeneratorWrapper {
|
||||
private static class GenerationEvent {
|
||||
private static int generationFutureDebugIDs = 0;
|
||||
ChunkPos p;
|
||||
int r;
|
||||
Future<?> f;
|
||||
public GenerationEvent(ChunkPos pos, int range, WorldGenerationStep generationGroup) {
|
||||
p = pos;
|
||||
r = range;
|
||||
f = generationGroup.executors.submit(() -> {
|
||||
generationGroup.generateLodFromList(generationFutureDebugIDs++, pos, range,
|
||||
Steps.Features);
|
||||
});
|
||||
}
|
||||
public boolean isCompleted() {
|
||||
return f.isDone();
|
||||
}
|
||||
public void join() {
|
||||
try {
|
||||
f.get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
public boolean tooClose(int cx, int cz, int cr) {
|
||||
int dist = Math.min(Math.abs(cx - p.x), Math.abs(cz - p.z));
|
||||
return dist<r+cr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static final IMinecraftWrapper MC = SingletonHandler.get(IMinecraftWrapper.class);
|
||||
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
|
||||
public WorldGenerationStep generationGroup;
|
||||
public LodDimension targetLodDim;
|
||||
public static final int generationGroupSize = 8;
|
||||
public static final int generationGroupSize = 4;
|
||||
public static final int generationGroupSizeFar = 0;
|
||||
public static int numberOfGenerationPoints = 8;
|
||||
public static int numberOfGenerationPoints = CONFIG.client().advanced().threading().getNumberOfWorldGenerationThreads()*2;
|
||||
|
||||
private int estimatedSampleNeeded = 128;
|
||||
|
||||
@@ -81,6 +53,7 @@ public class ExperimentalGenerator extends AbstractExperimentalWorldGeneratorWra
|
||||
@Override
|
||||
public void queueGenerationRequests(LodDimension lodDim, LodBuilder lodBuilder) {
|
||||
DistanceGenerationMode mode = CONFIG.client().worldGenerator().getDistanceGenerationMode();
|
||||
numberOfGenerationPoints = CONFIG.client().advanced().threading().getNumberOfWorldGenerationThreads();
|
||||
|
||||
if (mode == DistanceGenerationMode.NONE || !MC.hasSinglePlayerServer())
|
||||
return;
|
||||
@@ -92,6 +65,10 @@ public class ExperimentalGenerator extends AbstractExperimentalWorldGeneratorWra
|
||||
if (event.isCompleted()) {
|
||||
event.join();
|
||||
iter.remove();
|
||||
} else if (event.hasTimeout(5, TimeUnit.SECONDS)) {
|
||||
System.err.println(event.id+": Timed out and terminated!");
|
||||
event.terminate();
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +97,7 @@ public class ExperimentalGenerator extends AbstractExperimentalWorldGeneratorWra
|
||||
int maxIteration = Math.max(nearCount, farCount);
|
||||
|
||||
for (int i = 0; i < maxIteration; i++) {
|
||||
|
||||
|
||||
// We have nearPos to go though
|
||||
if (i < nearCount && posToGenerate.getNthDetail(i, true) != 0) {
|
||||
positionGoneThough++;
|
||||
@@ -131,12 +108,12 @@ public class ExperimentalGenerator extends AbstractExperimentalWorldGeneratorWra
|
||||
int chunkZ = LevelPosUtil.getChunkPos(detailLevel, posToGenerate.getNthPosZ(i, true));
|
||||
if (checkIfPositionIsValid(chunkX, chunkZ, generationGroupSize)) {
|
||||
ChunkPos chunkPos = new ChunkPos(chunkX, chunkZ);
|
||||
events.add(new GenerationEvent(chunkPos, generationGroupSize, generationGroup));
|
||||
events.add(new GenerationEvent(chunkPos, generationGroupSize, generationGroup, Steps.Features));
|
||||
toGenerate--;
|
||||
}
|
||||
}
|
||||
if (toGenerate <= 0)
|
||||
break;
|
||||
//if (toGenerate <= 0)
|
||||
// break;
|
||||
|
||||
// We have farPos to go though
|
||||
if (i < farCount && posToGenerate.getNthDetail(i, false) != 0) {
|
||||
@@ -148,18 +125,16 @@ public class ExperimentalGenerator extends AbstractExperimentalWorldGeneratorWra
|
||||
int chunkZ = LevelPosUtil.getChunkPos(detailLevel, posToGenerate.getNthPosZ(i, false));
|
||||
if (checkIfPositionIsValid(chunkX, chunkZ, generationGroupSizeFar)) {
|
||||
ChunkPos chunkPos = new ChunkPos(chunkX, chunkZ);
|
||||
events.add(new GenerationEvent(chunkPos, generationGroupSizeFar, generationGroup));
|
||||
events.add(new GenerationEvent(chunkPos, generationGroupSizeFar, generationGroup, Steps.Surface));
|
||||
toGenerate--;
|
||||
}
|
||||
}
|
||||
if (toGenerate <= 0)
|
||||
break;
|
||||
|
||||
|
||||
|
||||
}
|
||||
if (targetToGenerate != toGenerate) {
|
||||
if (toGenerate == 0) {
|
||||
if (toGenerate <= 0) {
|
||||
System.out.println(
|
||||
"WorldGenerator: Sampled " + posToGenerate.getNumberOfPos() + " out of " + estimatedSampleNeeded
|
||||
+ " points, started all targeted " + targetToGenerate + " generations.");
|
||||
@@ -179,7 +154,7 @@ public class ExperimentalGenerator extends AbstractExperimentalWorldGeneratorWra
|
||||
estimatedSampleNeeded = 32768;
|
||||
System.out.println("WorldGenerator: Increasing estimatedSampleNeeeded to " + estimatedSampleNeeded);
|
||||
|
||||
} else if (toGenerate == 0 && positionGoneThough * 1.5 < posToGenerate.getNumberOfPos()) {
|
||||
} else if (toGenerate <= 0 && positionGoneThough * 1.5 < posToGenerate.getNumberOfPos()) {
|
||||
// We haven't gone though half of them and it's already enough.
|
||||
// Let's shink the estimatedSampleNeeded.
|
||||
estimatedSampleNeeded /= 1.2;
|
||||
|
||||
+97
-44
@@ -15,11 +15,13 @@ import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import com.seibel.lod.common.wrappers.chunk.ChunkWrapper;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.WorldGenerationStep.Steps;
|
||||
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.WorldGenRegion;
|
||||
@@ -38,6 +40,65 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureMana
|
||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||
|
||||
public class WorldGenerationStep {
|
||||
|
||||
public static class GenerationEvent {
|
||||
private static int generationFutureDebugIDs = 0;
|
||||
ChunkPos pos;
|
||||
int range;
|
||||
Future<?> future;
|
||||
long nanotime;
|
||||
int id;
|
||||
Steps target;
|
||||
|
||||
public GenerationEvent(ChunkPos pos, int range, WorldGenerationStep generationGroup, Steps target) {
|
||||
nanotime = System.nanoTime();
|
||||
this.pos = pos;
|
||||
this.range = range;
|
||||
id = generationFutureDebugIDs++;
|
||||
this.target = target;
|
||||
future = generationGroup.executors.submit(() -> {
|
||||
generationGroup.generateLodFromList(this);
|
||||
});
|
||||
}
|
||||
public boolean isCompleted() {
|
||||
return future.isDone();
|
||||
}
|
||||
public boolean hasTimeout(int duration, TimeUnit unit) {
|
||||
long currentTime = System.nanoTime();
|
||||
long delta = currentTime - nanotime;
|
||||
return (delta > TimeUnit.NANOSECONDS.convert(duration, unit));
|
||||
}
|
||||
public void terminate() {
|
||||
future.cancel(true);
|
||||
}
|
||||
public void join() {
|
||||
try {
|
||||
future.get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
public boolean tooClose(int cx, int cz, int cr) {
|
||||
int dist = Math.min(Math.abs(cx - pos.x), Math.abs(cz - pos.z));
|
||||
return dist<range+cr;
|
||||
}
|
||||
public void refreshTimeout() {
|
||||
nanotime = System.nanoTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return id + ":"+ range + "@"+ pos+"("+target+")";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private static <T> T joinAsync(CompletableFuture<T> f) {
|
||||
//while (!f.isDone()) Thread.yield();
|
||||
@@ -155,39 +216,41 @@ public class WorldGenerationStep {
|
||||
return chunk;
|
||||
}
|
||||
|
||||
public void generateLodFromList(int i, ChunkPos pos, int range, Steps step) {
|
||||
System.out.println(i+": generateLodFromList("+pos.toString()+", "+range+", "+step+")");
|
||||
public void generateLodFromList(GenerationEvent event) {
|
||||
|
||||
System.out.println("Started event: "+event);
|
||||
GridList<ChunkSynconizer> referencedChunks;
|
||||
DistanceGenerationMode generationMode;
|
||||
switch (step) {
|
||||
Runnable lambda = () -> {event.refreshTimeout();};
|
||||
switch (event.target) {
|
||||
case Empty:
|
||||
return;
|
||||
case StructureStart:
|
||||
referencedChunks = generateStructureStart(pos, range);
|
||||
referencedChunks = generateStructureStart(lambda, event.pos, event.range);
|
||||
generationMode = DistanceGenerationMode.NONE;
|
||||
break;
|
||||
case StructureReference:
|
||||
referencedChunks = generateStructureReference(pos, range);
|
||||
referencedChunks = generateStructureReference(lambda, event.pos, event.range);
|
||||
generationMode = DistanceGenerationMode.NONE;
|
||||
break;
|
||||
case Biomes:
|
||||
referencedChunks = generateBiomes(pos, range);
|
||||
referencedChunks = generateBiomes(lambda, event.pos, event.range);
|
||||
generationMode = DistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT;
|
||||
break;
|
||||
case Noise:
|
||||
referencedChunks = generateNoise(pos, range);
|
||||
referencedChunks = generateNoise(lambda, event.pos, event.range);
|
||||
generationMode = DistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT;
|
||||
break;
|
||||
case Surface:
|
||||
referencedChunks = generateSurface(pos, range);
|
||||
referencedChunks = generateSurface(lambda, event.pos, event.range);
|
||||
generationMode = DistanceGenerationMode.SURFACE;
|
||||
break;
|
||||
case Carvers:
|
||||
referencedChunks = generateCarvers(pos, range);
|
||||
referencedChunks = generateCarvers(lambda, event.pos, event.range);
|
||||
generationMode = DistanceGenerationMode.SURFACE;
|
||||
break;
|
||||
case Features:
|
||||
referencedChunks = generateFeatures(pos, range);
|
||||
referencedChunks = generateFeatures(lambda, event.pos, event.range);
|
||||
generationMode = DistanceGenerationMode.FEATURES;
|
||||
break;
|
||||
case LiquidCarvers:
|
||||
@@ -199,27 +262,25 @@ public class WorldGenerationStep {
|
||||
}
|
||||
int centreIndex = referencedChunks.size() / 2;
|
||||
|
||||
for (int ox = -range; ox <= range; ox++) {
|
||||
for (int oy = -range; oy <= range; oy++) {
|
||||
for (int ox = -event.range; ox <= event.range; ox++) {
|
||||
for (int oy = -event.range; oy <= event.range; oy++) {
|
||||
int targetIndex = referencedChunks.offsetOf(centreIndex, ox, oy);
|
||||
ChunkSynconizer target = referencedChunks.get(targetIndex);
|
||||
lodBuilder.generateLodNodeFromChunk(lodDim, new ChunkWrapper(target.chunk), new LodBuilderConfig(generationMode));
|
||||
}
|
||||
}
|
||||
lambda.run();
|
||||
for (ChunkSynconizer sync : referencedChunks) {
|
||||
chunks.remove(sync.chunk.getPos().toLong());
|
||||
}
|
||||
|
||||
System.out.println(i+": EXIT: generateLodFromList("+pos.toString()+", "+range+", "+step+")");
|
||||
System.out.println("Ended event: "+event);
|
||||
}
|
||||
|
||||
public GridList<ChunkSynconizer> generateStructureStart(ChunkPos pos, int range) {
|
||||
//System.out.println("generateStructureStart("+pos.toString()+", "+range+")");
|
||||
public GridList<ChunkSynconizer> generateStructureStart(Runnable r, ChunkPos pos, int range) {
|
||||
int cx = pos.x;
|
||||
int cy = pos.z;
|
||||
GridList<ChunkSynconizer> chunks = new GridList<ChunkSynconizer>(range);
|
||||
|
||||
|
||||
for (int ox = -range; ox <= range; ox++) {
|
||||
for (int oy = -range; oy <= range; oy++) {
|
||||
ChunkSynconizer target = getChunkSynconizer(toLongPos(cx + ox, cy + oy));
|
||||
@@ -242,14 +303,13 @@ public class WorldGenerationStep {
|
||||
}
|
||||
}
|
||||
}
|
||||
//System.out.println("EXIT: generateStructureStart("+pos.toString()+", "+range+") -> "+chunks);
|
||||
r.run();
|
||||
return chunks;
|
||||
}
|
||||
|
||||
public GridList<ChunkSynconizer> generateStructureReference(ChunkPos pos, int range) {
|
||||
public GridList<ChunkSynconizer> generateStructureReference(Runnable r, ChunkPos pos, int range) {
|
||||
int prestepRange = range + StepStructureReference.RANGE;
|
||||
GridList<ChunkSynconizer> referencedChunks = generateStructureStart(pos, prestepRange);
|
||||
//System.out.println("generateStructureReference(" + pos.toString() + ", " + range + ")");
|
||||
GridList<ChunkSynconizer> referencedChunks = generateStructureStart(r, pos, prestepRange);
|
||||
int centreIndex = referencedChunks.size() / 2;
|
||||
|
||||
for (int ox = -range; ox <= range; ox++) {
|
||||
@@ -275,15 +335,13 @@ public class WorldGenerationStep {
|
||||
}
|
||||
}
|
||||
}
|
||||
//System.out.println(
|
||||
// "EXIT: generateStructureReference(" + pos.toString() + ", " + range + ") -> " + referencedChunks);
|
||||
r.run();
|
||||
return referencedChunks;
|
||||
}
|
||||
|
||||
public GridList<ChunkSynconizer> generateBiomes(ChunkPos pos, int range) {
|
||||
public GridList<ChunkSynconizer> generateBiomes(Runnable r, ChunkPos pos, int range) {
|
||||
int prestepRange = range + 1;
|
||||
GridList<ChunkSynconizer> referencedChunks = generateStructureReference(pos, prestepRange);
|
||||
//System.out.println("generateBiomes("+pos.toString()+", "+range+")");
|
||||
GridList<ChunkSynconizer> referencedChunks = generateStructureReference(r, pos, prestepRange);
|
||||
int centreIndex = referencedChunks.size() / 2;
|
||||
|
||||
for (int ox = -range; ox <= range; ox++) {
|
||||
@@ -308,15 +366,13 @@ public class WorldGenerationStep {
|
||||
}
|
||||
}
|
||||
}
|
||||
//System.out.println("EXIT: generateBiomes("+pos.toString()+", "+range+") -> "+referencedChunks);
|
||||
r.run();
|
||||
return referencedChunks;
|
||||
}
|
||||
|
||||
public GridList<ChunkSynconizer> generateNoise(ChunkPos pos, int range) {
|
||||
// System.out.println("generateNoise("+pos.toString()+", "+range+")");
|
||||
public GridList<ChunkSynconizer> generateNoise(Runnable r, ChunkPos pos, int range) {
|
||||
int prestepRange = range + 1;
|
||||
GridList<ChunkSynconizer> referencedChunks = generateBiomes(pos, prestepRange);
|
||||
//System.out.println("generateNoise("+pos.toString()+", "+range+")");
|
||||
GridList<ChunkSynconizer> referencedChunks = generateBiomes(r, pos, prestepRange);
|
||||
int centreIndex = referencedChunks.size() / 2;
|
||||
|
||||
for (int ox = -range; ox <= range; ox++) {
|
||||
@@ -342,14 +398,13 @@ public class WorldGenerationStep {
|
||||
}
|
||||
}
|
||||
}
|
||||
//System.out.println("EXIT: generateNoise(" + pos.toString() + ", " + range + ") -> " + referencedChunks);
|
||||
r.run();
|
||||
return referencedChunks;
|
||||
}
|
||||
|
||||
public GridList<ChunkSynconizer> generateSurface(ChunkPos pos, int range) {
|
||||
public GridList<ChunkSynconizer> generateSurface(Runnable r, ChunkPos pos, int range) {
|
||||
int prestepRange = range + 1;
|
||||
GridList<ChunkSynconizer> referencedChunks = generateNoise(pos, prestepRange);
|
||||
//System.out.println("generateSurface("+pos.toString()+", "+range+")");
|
||||
GridList<ChunkSynconizer> referencedChunks = generateNoise(r, pos, prestepRange);
|
||||
int centreIndex = referencedChunks.size() / 2;
|
||||
|
||||
for (int ox = -range; ox <= range; ox++) {
|
||||
@@ -376,15 +431,14 @@ public class WorldGenerationStep {
|
||||
}
|
||||
}
|
||||
}
|
||||
//System.out.println("EXIT: generateNoise(" + pos.toString() + ", " + range + ") -> " + referencedChunks);
|
||||
r.run();
|
||||
return referencedChunks;
|
||||
}
|
||||
|
||||
|
||||
public GridList<ChunkSynconizer> generateCarvers(ChunkPos pos, int range) {
|
||||
public GridList<ChunkSynconizer> generateCarvers(Runnable r, ChunkPos pos, int range) {
|
||||
int prestepRange = range + 1;
|
||||
GridList<ChunkSynconizer> referencedChunks = generateSurface(pos, prestepRange);
|
||||
//System.out.println("generateCarvers("+pos.toString()+", "+range+")");
|
||||
GridList<ChunkSynconizer> referencedChunks = generateSurface(r, pos, prestepRange);
|
||||
int centreIndex = referencedChunks.size() / 2;
|
||||
|
||||
for (int ox = -range; ox <= range; ox++) {
|
||||
@@ -410,15 +464,14 @@ public class WorldGenerationStep {
|
||||
}
|
||||
}
|
||||
}
|
||||
//System.out.println("EXIT: generateNoise(" + pos.toString() + ", " + range + ") -> " + referencedChunks);
|
||||
r.run();
|
||||
return referencedChunks;
|
||||
}
|
||||
|
||||
|
||||
public GridList<ChunkSynconizer> generateFeatures(ChunkPos pos, int range) {
|
||||
public GridList<ChunkSynconizer> generateFeatures(Runnable r, ChunkPos pos, int range) {
|
||||
int prestepRange = range + 1;
|
||||
GridList<ChunkSynconizer> referencedChunks = generateCarvers(pos, prestepRange);
|
||||
//System.out.println("generateFeatures("+pos.toString()+", "+range+")");
|
||||
GridList<ChunkSynconizer> referencedChunks = generateCarvers(r, pos, prestepRange);
|
||||
int centreIndex = referencedChunks.size() / 2;
|
||||
|
||||
for (int ox = -range; ox <= range; ox++) {
|
||||
@@ -444,7 +497,7 @@ public class WorldGenerationStep {
|
||||
}
|
||||
}
|
||||
}
|
||||
//System.out.println("EXIT: generateNoise(" + pos.toString() + ", " + range + ") -> " + referencedChunks);
|
||||
r.run();
|
||||
return referencedChunks;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user