Fix and port batch generator to new Generator API. Now if we just fix up forge, and there's no bugs (impossible), then there's enough implemented to finally have something shown! Yay!
This commit is contained in:
@@ -21,8 +21,8 @@ package com.seibel.lod.common.wrappers;
|
||||
|
||||
import com.seibel.lod.common.wrappers.block.BlockStateWrapper;
|
||||
import com.seibel.lod.common.wrappers.world.BiomeWrapper;
|
||||
import com.seibel.lod.core.builders.lodBuilding.LodBuilder;
|
||||
import com.seibel.lod.core.objects.lod.LodDimension;
|
||||
import com.seibel.lod.core.a7.level.ILevel;
|
||||
import com.seibel.lod.core.a7.level.IServerLevel;
|
||||
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.IBlockStateWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IBiomeWrapper;
|
||||
@@ -40,10 +40,16 @@ public class WrapperFactory implements IWrapperFactory
|
||||
{
|
||||
public static final WrapperFactory INSTANCE = new WrapperFactory();
|
||||
|
||||
public AbstractBatchGenerationEnvionmentWrapper createBatchGenerator(LodBuilder newLodBuilder,
|
||||
LodDimension newLodDimension, ILevelWrapper worldWrapper)
|
||||
{
|
||||
return new BatchGenerationEnvironment(worldWrapper, newLodBuilder, newLodDimension);
|
||||
@Override
|
||||
public AbstractBatchGenerationEnvionmentWrapper createBatchGenerator(ILevel targetLevel) {
|
||||
if (targetLevel instanceof IServerLevel)
|
||||
{
|
||||
return new BatchGenerationEnvironment((IServerLevel) targetLevel);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException("The target level must be a server-side level.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+171
-236
@@ -30,6 +30,9 @@ import com.seibel.lod.core.logging.ConfigBasedSpamLogger;
|
||||
import com.seibel.lod.core.builders.lodBuilding.LodBuilderConfig;
|
||||
import com.seibel.lod.core.enums.config.EDistanceGenerationMode;
|
||||
import com.seibel.lod.core.enums.config.ELightGenerationMode;
|
||||
import com.seibel.lod.core.objects.DHChunkPos;
|
||||
import com.seibel.lod.core.util.EventTimer;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.util.gridList.ArrayGridList;
|
||||
import com.seibel.lod.core.util.LodThreadFactory;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
@@ -37,6 +40,8 @@ import com.seibel.lod.core.wrapperInterfaces.world.ILevelWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractBatchGenerationEnvionmentWrapper;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
@@ -74,6 +79,7 @@ import net.minecraft.core.Registry;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.checkerframework.checker.units.qual.C;
|
||||
|
||||
/*
|
||||
Total: 3.135214124s
|
||||
@@ -102,121 +108,56 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
() -> Config.Client.Advanced.Debugging.DebugSwitch.logWorldGenLoadEvent.get());
|
||||
|
||||
//TODO: Make actual proper support for StarLight
|
||||
|
||||
public static class PrefEvent
|
||||
{
|
||||
long beginNano = 0;
|
||||
long emptyNano = 0;
|
||||
long structStartNano = 0;
|
||||
long structRefNano = 0;
|
||||
long biomeNano = 0;
|
||||
long noiseNano = 0;
|
||||
long surfaceNano = 0;
|
||||
long carverNano = 0;
|
||||
long featureNano = 0;
|
||||
long lightNano = 0;
|
||||
long endNano = 0;
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "beginNano: " + beginNano + ",\n" +
|
||||
"emptyNano: " + emptyNano + ",\n" +
|
||||
"structStartNano: " + structStartNano + ",\n" +
|
||||
"structRefNano: " + structRefNano + ",\n" +
|
||||
"biomeNano: " + biomeNano + ",\n" +
|
||||
"noiseNano: " + noiseNano + ",\n" +
|
||||
"surfaceNano: " + surfaceNano + ",\n" +
|
||||
"carverNano: " + carverNano + ",\n" +
|
||||
"featureNano: " + featureNano + ",\n" +
|
||||
"lightNano: " + lightNano + ",\n" +
|
||||
"endNano: " + endNano + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class PerfCalculator
|
||||
{
|
||||
private static final String[] TIME_NAMES = {
|
||||
"total",
|
||||
"setup",
|
||||
"structStart",
|
||||
"structRef",
|
||||
"biome",
|
||||
"noise",
|
||||
"surface",
|
||||
"carver",
|
||||
"feature",
|
||||
"light",
|
||||
"cleanup",
|
||||
//"lodCreation" (No longer used)
|
||||
};
|
||||
|
||||
public static final int SIZE = 50;
|
||||
Rolling totalTime = new Rolling(SIZE);
|
||||
Rolling emptyTime = new Rolling(SIZE);
|
||||
Rolling structStartTime = new Rolling(SIZE);
|
||||
Rolling structRefTime = new Rolling(SIZE);
|
||||
Rolling biomeTime = new Rolling(SIZE);
|
||||
Rolling noiseTime = new Rolling(SIZE);
|
||||
Rolling surfaceTime = new Rolling(SIZE);
|
||||
Rolling carverTime = new Rolling(SIZE);
|
||||
Rolling featureTime = new Rolling(SIZE);
|
||||
Rolling lightTime = new Rolling(SIZE);
|
||||
Rolling lodTime = new Rolling(SIZE);
|
||||
|
||||
public void recordEvent(PrefEvent e)
|
||||
ArrayList<Rolling> times = new ArrayList<>();
|
||||
|
||||
public PerfCalculator()
|
||||
{
|
||||
long preTime = e.beginNano;
|
||||
totalTime.add(e.endNano - preTime);
|
||||
if (e.emptyNano != 0)
|
||||
for(int i = 0; i < 11; i++)
|
||||
{
|
||||
emptyTime.add(e.emptyNano - preTime);
|
||||
preTime = e.emptyNano;
|
||||
times.add(new Rolling(SIZE));
|
||||
}
|
||||
if (e.structStartNano != 0)
|
||||
}
|
||||
|
||||
public void recordEvent(EventTimer event)
|
||||
{
|
||||
for (EventTimer.Event e : event.events)
|
||||
{
|
||||
structStartTime.add(e.structStartNano - preTime);
|
||||
preTime = e.structStartNano;
|
||||
}
|
||||
if (e.structRefNano != 0)
|
||||
{
|
||||
structRefTime.add(e.structRefNano - preTime);
|
||||
preTime = e.structRefNano;
|
||||
}
|
||||
if (e.biomeNano != 0)
|
||||
{
|
||||
biomeTime.add(e.biomeNano - preTime);
|
||||
preTime = e.biomeNano;
|
||||
}
|
||||
if (e.noiseNano != 0)
|
||||
{
|
||||
noiseTime.add(e.noiseNano - preTime);
|
||||
preTime = e.noiseNano;
|
||||
}
|
||||
if (e.surfaceNano != 0)
|
||||
{
|
||||
surfaceTime.add(e.surfaceNano - preTime);
|
||||
preTime = e.surfaceNano;
|
||||
}
|
||||
if (e.carverNano != 0)
|
||||
{
|
||||
carverTime.add(e.carverNano - preTime);
|
||||
preTime = e.carverNano;
|
||||
}
|
||||
if (e.featureNano != 0)
|
||||
{
|
||||
featureTime.add(e.featureNano - preTime);
|
||||
preTime = e.featureNano;
|
||||
}
|
||||
if (e.lightNano != 0)
|
||||
{
|
||||
lightTime.add(e.lightNano - preTime);
|
||||
preTime = e.lightNano;
|
||||
}
|
||||
if (e.endNano != 0)
|
||||
{
|
||||
lodTime.add(e.endNano - preTime);
|
||||
String name = e.name;
|
||||
int index = Arrays.asList(TIME_NAMES).indexOf(name);
|
||||
if(index == -1) continue;
|
||||
times.get(index).add(e.timeNs);
|
||||
}
|
||||
times.get(0).add(event.getTotalTimeNs());
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "Total: " + Duration.ofNanos((long) totalTime.getAverage()) + ", Empty/LoadChunk: "
|
||||
+ Duration.ofNanos((long) emptyTime.getAverage()) + ", StructStart: "
|
||||
+ Duration.ofNanos((long) structStartTime.getAverage()) + ", StructRef: "
|
||||
+ Duration.ofNanos((long) structRefTime.getAverage()) + ", Biome: "
|
||||
+ Duration.ofNanos((long) biomeTime.getAverage()) + ", Noise: "
|
||||
+ Duration.ofNanos((long) noiseTime.getAverage()) + ", Surface: "
|
||||
+ Duration.ofNanos((long) surfaceTime.getAverage()) + ", Carver: "
|
||||
+ Duration.ofNanos((long) carverTime.getAverage()) + ", Feature: "
|
||||
+ Duration.ofNanos((long) featureTime.getAverage()) + ", Light: "
|
||||
+ Duration.ofNanos((long) lightTime.getAverage()) + ", Lod: "
|
||||
+ Duration.ofNanos((long) lodTime.getAverage());
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < times.size(); i++)
|
||||
{
|
||||
if (times.get(i).getAverage() == 0) continue;
|
||||
sb.append(TIME_NAMES[i]).append(": ").append(times.get(i).getAverage()).append("\n");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,23 +214,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
executors = Executors.newFixedThreadPool(newThreadCount,
|
||||
new LodThreadFactory("Gen-Worker-Thread", Thread.MIN_PRIORITY));
|
||||
}
|
||||
|
||||
public boolean tryAddPoint(int px, int pz, int range, Steps target, boolean genAllDetails, double runTimeRatio)
|
||||
{
|
||||
int boxSize = range * 2 + 1;
|
||||
int x = Math.floorDiv(px, boxSize) * boxSize + range;
|
||||
int z = Math.floorDiv(pz, boxSize) * boxSize + range;
|
||||
|
||||
for (GenerationEvent event : events)
|
||||
{
|
||||
if (event.tooClose(x, z, range))
|
||||
return false;
|
||||
}
|
||||
// System.out.println(x + ", "+z);
|
||||
events.add(new GenerationEvent(new ChunkPos(x, z), range, this, target, genAllDetails, runTimeRatio));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public void updateAllFutures()
|
||||
{
|
||||
if (unknownExceptionCount > 0) {
|
||||
@@ -297,36 +222,32 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
unknownExceptionCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Update all current out standing jobs
|
||||
Iterator<GenerationEvent> iter = events.iterator();
|
||||
while (iter.hasNext())
|
||||
{
|
||||
GenerationEvent event = iter.next();
|
||||
if (event.isCompleted())
|
||||
if (event.future.isDone())
|
||||
{
|
||||
try
|
||||
{
|
||||
event.join();
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
EVENT_LOGGER.error("Batching World Generator: Event {} gotten an exception", event);
|
||||
EVENT_LOGGER.error("Exception: ", e);
|
||||
unknownExceptionCount++;
|
||||
lastExceptionTriggerTime = System.nanoTime();
|
||||
}
|
||||
finally
|
||||
{
|
||||
iter.remove();
|
||||
if (event.future.isCompletedExceptionally() && !event.future.isCancelled()) {
|
||||
try {
|
||||
event.future.get(); // Should throw exception
|
||||
LodUtil.assertNotReach();
|
||||
} catch (Exception e) {
|
||||
unknownExceptionCount++;
|
||||
lastExceptionTriggerTime = System.nanoTime();
|
||||
EVENT_LOGGER.error("Batching World Generator: Event {} gotten an exception", event);
|
||||
EVENT_LOGGER.error("Exception: ", e);
|
||||
}
|
||||
}
|
||||
iter.remove();
|
||||
}
|
||||
else if (event.hasTimeout(TIMEOUT_SECONDS, TimeUnit.SECONDS))
|
||||
{
|
||||
EVENT_LOGGER.error("Batching World Generator: " + event + " timed out and terminated!");
|
||||
EVENT_LOGGER.info("Dump PrefEvent: " + event.pEvent);
|
||||
try
|
||||
{
|
||||
EVENT_LOGGER.info("Dump PrefEvent: " + event.timer);
|
||||
try {
|
||||
if (!event.terminate())
|
||||
EVENT_LOGGER.error("Failed to terminate the stuck generation event!");
|
||||
}
|
||||
@@ -336,13 +257,14 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (unknownExceptionCount > EXCEPTION_COUNTER_TRIGGER) {
|
||||
EVENT_LOGGER.error("Too many exceptions in Batching World Generator! Disabling the generator.");
|
||||
unknownExceptionCount = 0;
|
||||
Config.Client.WorldGenerator.enableDistantGeneration.set(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public BatchGenerationEnvironment(IServerLevel serverlevel)
|
||||
{
|
||||
super(serverlevel);
|
||||
@@ -400,19 +322,19 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
|
||||
}
|
||||
|
||||
public void generateLodFromList(GenerationEvent e)
|
||||
public ArrayGridList<IChunkWrapper> generateLodFromList(GenerationEvent e)
|
||||
{
|
||||
EVENT_LOGGER.debug("Lod Generate Event: " + e.pos);
|
||||
e.pEvent.beginNano = System.nanoTime();
|
||||
EVENT_LOGGER.debug("Lod Generate Event: " + e.minPos);
|
||||
ArrayGridList<ChunkAccess> referencedChunks;
|
||||
ArrayGridList<ChunkAccess> genChunks;
|
||||
EDistanceGenerationMode generationMode;
|
||||
LightedWorldGenRegion region;
|
||||
WorldGenLevelLightEngine lightEngine;
|
||||
LightGetterAdaptor adaptor;
|
||||
int refRange = e.range + RANGE_TO_RANGE_EMPTY_EXTENSION;
|
||||
int refOffsetX = e.pos.x - refRange;
|
||||
int refOffsetZ = e.pos.z - refRange;
|
||||
int refSize = e.size+2; // +2 for the border referenced chunks
|
||||
int refPosX = e.minPos.x - 1; // -1 for the border referenced chunks
|
||||
int refPosZ = e.minPos.z - 1; // -1 for the border referenced chunks
|
||||
|
||||
try
|
||||
{
|
||||
adaptor = new LightGetterAdaptor(params.level);
|
||||
@@ -439,109 +361,118 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
return target;
|
||||
};
|
||||
|
||||
referencedChunks = new ArrayGridList<>(refRange*2+1,
|
||||
(x,z) -> generator.generate(x + refOffsetX,z + refOffsetZ)
|
||||
referencedChunks = new ArrayGridList<>(refSize,
|
||||
(x,z) -> generator.generate(x + refPosX,z + refPosZ)
|
||||
);
|
||||
e.pEvent.emptyNano = System.nanoTime();
|
||||
e.refreshTimeout();
|
||||
region = new LightedWorldGenRegion(params.level, lightEngine, referencedChunks,
|
||||
ChunkStatus.STRUCTURE_STARTS, refRange, e.lightMode, generator);
|
||||
ChunkStatus.STRUCTURE_STARTS, refSize/2, e.lightMode, generator);
|
||||
adaptor.setRegion(region);
|
||||
e.tParam.makeStructFeat(region, params);
|
||||
genChunks = new ArrayGridList<>(referencedChunks, RANGE_TO_RANGE_EMPTY_EXTENSION,
|
||||
referencedChunks.gridSize - RANGE_TO_RANGE_EMPTY_EXTENSION);
|
||||
generateDirect(e, genChunks, e.target, region);
|
||||
e.timer.nextEvent("cleanup");
|
||||
}
|
||||
catch (StepStructureStart.StructStartCorruptedException f)
|
||||
{
|
||||
e.tParam.markAsInvalid();
|
||||
return;
|
||||
throw (RuntimeException)f.getCause();
|
||||
}
|
||||
|
||||
switch (e.target)
|
||||
{
|
||||
case Empty:
|
||||
case StructureStart:
|
||||
case StructureReference:
|
||||
generationMode = EDistanceGenerationMode.NONE;
|
||||
break;
|
||||
case Biomes:
|
||||
generationMode = EDistanceGenerationMode.BIOME_ONLY;
|
||||
case Noise:
|
||||
generationMode = EDistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT;
|
||||
break;
|
||||
case Surface:
|
||||
case Carvers:
|
||||
generationMode = EDistanceGenerationMode.SURFACE;
|
||||
break;
|
||||
case Features:
|
||||
generationMode = EDistanceGenerationMode.FEATURES;
|
||||
break;
|
||||
case Light:
|
||||
case LiquidCarvers:
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
for (int oy = 0; oy < genChunks.gridSize; oy++)
|
||||
{
|
||||
for (int ox = 0; ox < genChunks.gridSize; ox++)
|
||||
{
|
||||
ChunkAccess target = genChunks.get(ox, oy);
|
||||
ChunkWrapper wrappedChunk = new ChunkWrapper(target, region);
|
||||
if (!wrappedChunk.isLightCorrect()) {
|
||||
throw new RuntimeException("The generated chunk somehow has isLightCorrect() returning false");
|
||||
}
|
||||
|
||||
boolean isFull = target.getStatus() == ChunkStatus.FULL || target instanceof LevelChunk;
|
||||
#if POST_MC_1_18_1
|
||||
boolean isPartial = target.isOldNoiseGeneration();
|
||||
#endif
|
||||
if (isFull)
|
||||
{
|
||||
LOAD_LOGGER.info("Detected full existing chunk at {}", target.getPos());
|
||||
ChunkSizedData data = LodDataBuilder.createChunkData(wrappedChunk);
|
||||
if (data != null)
|
||||
{
|
||||
//params.lodLevel.submitChunkData(data);
|
||||
}
|
||||
// switch (e.target)
|
||||
// {
|
||||
// case Empty:
|
||||
// case StructureStart:
|
||||
// case StructureReference:
|
||||
// generationMode = EDistanceGenerationMode.NONE;
|
||||
// break;
|
||||
// case Biomes:
|
||||
// generationMode = EDistanceGenerationMode.BIOME_ONLY;
|
||||
// case Noise:
|
||||
// generationMode = EDistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT;
|
||||
// break;
|
||||
// case Surface:
|
||||
// case Carvers:
|
||||
// generationMode = EDistanceGenerationMode.SURFACE;
|
||||
// break;
|
||||
// case Features:
|
||||
// generationMode = EDistanceGenerationMode.FEATURES;
|
||||
// break;
|
||||
// case Light:
|
||||
// case LiquidCarvers:
|
||||
// default:
|
||||
// throw new IllegalArgumentException("Unknown/Unsupported target: " + e.target);
|
||||
// }
|
||||
// for (int oy = 0; oy < genChunks.gridSize; oy++)
|
||||
// {
|
||||
// for (int ox = 0; ox < genChunks.gridSize; ox++)
|
||||
// {
|
||||
// ChunkAccess target = genChunks.get(ox, oy);
|
||||
// ChunkWrapper wrappedChunk = new ChunkWrapper(target, region);
|
||||
// if (!wrappedChunk.isLightCorrect()) {
|
||||
// throw new RuntimeException("The generated chunk somehow has isLightCorrect() returning false");
|
||||
// }
|
||||
//
|
||||
// boolean isFull = target.getStatus() == ChunkStatus.FULL || target instanceof LevelChunk;
|
||||
// #if POST_MC_1_18_1
|
||||
// boolean isPartial = target.isOldNoiseGeneration();
|
||||
// #endif
|
||||
// if (isFull)
|
||||
// {
|
||||
// LOAD_LOGGER.info("Detected full existing chunk at {}", target.getPos());
|
||||
// ChunkSizedData data = LodDataBuilder.createChunkData(wrappedChunk);
|
||||
// if (data != null)
|
||||
// {
|
||||
// params.lodLevel.submitChunkData(data);
|
||||
// }
|
||||
//
|
||||
// //FIXME: Fix this
|
||||
// params.lodBuilder.generateLodNodeFromChunk(params.lodDim, wrappedChunk,
|
||||
// new LodBuilderConfig(EDistanceGenerationMode.FULL), true, e.genAllDetails);
|
||||
// }
|
||||
// #if POST_MC_1_18_1
|
||||
// else if (isPartial)
|
||||
// {
|
||||
// LOAD_LOGGER.info("Detected old existing chunk at {}", target.getPos());
|
||||
// params.lodBuilder.generateLodNodeFromChunk(params.lodDim, wrappedChunk,
|
||||
// new LodBuilderConfig(generationMode), true, e.genAllDetails);
|
||||
// }
|
||||
// #endif
|
||||
// else if (target.getStatus() == ChunkStatus.EMPTY && generationMode == EDistanceGenerationMode.NONE)
|
||||
// {
|
||||
// params.lodBuilder.generateLodNodeFromChunk(params.lodDim,wrappedChunk,
|
||||
// LodBuilderConfig.getFillVoidConfig(), true, e.genAllDetails);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// params.lodBuilder.generateLodNodeFromChunk(params.lodDim, wrappedChunk,
|
||||
// new LodBuilderConfig(generationMode), true, e.genAllDetails);
|
||||
// }
|
||||
// if (e.lightMode == ELightGenerationMode.FANCY || isFull)
|
||||
// {
|
||||
// lightEngine.retainData(target.getPos(), false);
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// }
|
||||
|
||||
//FIXME: Fix this
|
||||
//params.lodBuilder.generateLodNodeFromChunk(params.lodDim, wrappedChunk,
|
||||
// new LodBuilderConfig(EDistanceGenerationMode.FULL), true, e.genAllDetails);
|
||||
}
|
||||
#if POST_MC_1_18_1
|
||||
else if (isPartial)
|
||||
{
|
||||
LOAD_LOGGER.info("Detected old existing chunk at {}", target.getPos());
|
||||
//params.lodBuilder.generateLodNodeFromChunk(params.lodDim, wrappedChunk,
|
||||
// new LodBuilderConfig(generationMode), true, e.genAllDetails);
|
||||
}
|
||||
#endif
|
||||
else if (target.getStatus() == ChunkStatus.EMPTY && generationMode == EDistanceGenerationMode.NONE)
|
||||
{
|
||||
//params.lodBuilder.generateLodNodeFromChunk(params.lodDim,wrappedChunk,
|
||||
// LodBuilderConfig.getFillVoidConfig(), true, e.genAllDetails);
|
||||
}
|
||||
else
|
||||
{
|
||||
//params.lodBuilder.generateLodNodeFromChunk(params.lodDim, wrappedChunk,
|
||||
// new LodBuilderConfig(generationMode), true, e.genAllDetails);
|
||||
}
|
||||
if (e.lightMode == ELightGenerationMode.FANCY || isFull)
|
||||
{
|
||||
lightEngine.retainData(target.getPos(), false);
|
||||
}
|
||||
|
||||
ArrayGridList<IChunkWrapper> result = new ArrayGridList<>(e.size);
|
||||
for (int oy = 0; oy < e.size; oy++)
|
||||
{
|
||||
for (int ox = 0; ox < e.size; ox++)
|
||||
{
|
||||
result.set(ox, oy, new ChunkWrapper(genChunks.get(ox, oy), region));
|
||||
}
|
||||
}
|
||||
e.pEvent.endNano = System.nanoTime();
|
||||
e.timer.complete();
|
||||
e.refreshTimeout();
|
||||
if (PREF_LOGGER.canMaybeLog())
|
||||
{
|
||||
e.tParam.perf.recordEvent(e.pEvent);
|
||||
PREF_LOGGER.infoInc("{}", e.tParam.perf);
|
||||
e.tParam.perf.recordEvent(e.timer);
|
||||
PREF_LOGGER.infoInc("{}", e.timer);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void generateDirect(GenerationEvent e, ArrayGridList<ChunkAccess> subRange, Steps step,
|
||||
@@ -559,39 +490,41 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
});
|
||||
if (step == Steps.Empty)
|
||||
return;
|
||||
e.timer.nextEvent("structStart");
|
||||
stepStructureStart.generateGroup(e.tParam, region, subRange);
|
||||
e.pEvent.structStartNano = System.nanoTime();
|
||||
e.refreshTimeout();
|
||||
if (step == Steps.StructureStart)
|
||||
return;
|
||||
e.timer.nextEvent("structRef");
|
||||
stepStructureReference.generateGroup(e.tParam, region, subRange);
|
||||
e.pEvent.structRefNano = System.nanoTime();
|
||||
e.refreshTimeout();
|
||||
if (step == Steps.StructureReference)
|
||||
return;
|
||||
e.timer.nextEvent("biome");
|
||||
stepBiomes.generateGroup(e.tParam, region, subRange);
|
||||
e.pEvent.biomeNano = System.nanoTime();
|
||||
e.refreshTimeout();
|
||||
if (step == Steps.Biomes)
|
||||
return;
|
||||
e.timer.nextEvent("noise");
|
||||
stepNoise.generateGroup(e.tParam, region, subRange);
|
||||
e.pEvent.noiseNano = System.nanoTime();
|
||||
e.refreshTimeout();
|
||||
if (step == Steps.Noise)
|
||||
return;
|
||||
e.timer.nextEvent("surface");
|
||||
stepSurface.generateGroup(e.tParam, region, subRange);
|
||||
e.pEvent.surfaceNano = System.nanoTime();
|
||||
e.refreshTimeout();
|
||||
if (step == Steps.Surface)
|
||||
return;
|
||||
e.timer.nextEvent("carver");
|
||||
if (step == Steps.Carvers)
|
||||
return;
|
||||
e.timer.nextEvent("feature");
|
||||
stepFeatures.generateGroup(e.tParam, region, subRange);
|
||||
e.pEvent.featureNano = System.nanoTime();
|
||||
e.refreshTimeout();
|
||||
}
|
||||
finally
|
||||
{
|
||||
e.timer.nextEvent("light");
|
||||
switch (region.lightMode)
|
||||
{
|
||||
case FANCY:
|
||||
@@ -611,7 +544,6 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
});
|
||||
break;
|
||||
}
|
||||
e.pEvent.lightNano = System.nanoTime();
|
||||
e.refreshTimeout();
|
||||
}
|
||||
}
|
||||
@@ -641,6 +573,9 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
|
||||
@Override
|
||||
public CompletableFuture<ArrayGridList<IChunkWrapper>> generateChunks(int minX, int minZ, int genSize, Steps targetStep, double runTimeRatio) {
|
||||
return null; // TODO: Implement generateChunks
|
||||
// TODO: Check event overlap via e.tooClose()
|
||||
GenerationEvent e = GenerationEvent.startEvent(new DHChunkPos(minX, minZ), genSize, this, targetStep, runTimeRatio);
|
||||
events.add(e);
|
||||
return e.future;
|
||||
}
|
||||
}
|
||||
+68
-68
@@ -20,86 +20,92 @@
|
||||
package com.seibel.lod.common.wrappers.worldGeneration;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment.PrefEvent;
|
||||
import com.seibel.lod.core.config.Config;
|
||||
import com.seibel.lod.core.enums.config.ELightGenerationMode;
|
||||
import com.seibel.lod.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.lod.core.objects.DHChunkPos;
|
||||
import com.seibel.lod.core.util.EventTimer;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.util.gridList.ArrayGridList;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractBatchGenerationEnvionmentWrapper.Steps;
|
||||
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
//======================= Main Event class======================
|
||||
public final class GenerationEvent
|
||||
{
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger(MethodHandles.lookup().lookupClass().getSimpleName());
|
||||
|
||||
private static int generationFutureDebugIDs = 0;
|
||||
final ThreadedParameters tParam;
|
||||
final ChunkPos pos;
|
||||
final int range;
|
||||
final Future<?> future;
|
||||
long creationNanotime;
|
||||
final int id;
|
||||
final ThreadedParameters tParam;
|
||||
final DHChunkPos minPos;
|
||||
final int size;
|
||||
final Steps target;
|
||||
final ELightGenerationMode lightMode;
|
||||
final PrefEvent pEvent = new PrefEvent();
|
||||
final boolean genAllDetails;
|
||||
|
||||
final double runTimeRatio;
|
||||
|
||||
public GenerationEvent(ChunkPos pos, int range, BatchGenerationEnvironment generationGroup,
|
||||
Steps target, boolean genAllDetails, double runTimeRatio)
|
||||
EventTimer timer = null;
|
||||
long inQueueTime;
|
||||
long timeoutTime = -1;
|
||||
public CompletableFuture<ArrayGridList<IChunkWrapper>> future = null;
|
||||
|
||||
public GenerationEvent(DHChunkPos minPos, int size, BatchGenerationEnvironment generationGroup,
|
||||
Steps target, double runTimeRatio)
|
||||
{
|
||||
creationNanotime = System.nanoTime();
|
||||
this.pos = pos;
|
||||
this.range = range;
|
||||
id = generationFutureDebugIDs++;
|
||||
inQueueTime = System.nanoTime();
|
||||
this.id = generationFutureDebugIDs++;
|
||||
this.minPos = minPos;
|
||||
this.size = size;
|
||||
this.target = target;
|
||||
this.tParam = ThreadedParameters.getOrMake(generationGroup.params);
|
||||
ELightGenerationMode mode = Config.Client.WorldGenerator.lightGenerationMode.get();
|
||||
|
||||
this.lightMode = mode;
|
||||
this.genAllDetails = genAllDetails;
|
||||
this.lightMode = Config.Client.WorldGenerator.lightGenerationMode.get();
|
||||
this.runTimeRatio = runTimeRatio;
|
||||
|
||||
future = generationGroup.executors.submit(() ->
|
||||
{
|
||||
long startTime = System.nanoTime();
|
||||
BatchGenerationEnvironment.isDistantGeneratorThread.set(true);
|
||||
try {
|
||||
generationGroup.generateLodFromList(this);
|
||||
} finally {
|
||||
BatchGenerationEnvironment.isDistantGeneratorThread.remove();
|
||||
if (!Thread.interrupted() && runTimeRatio < 1.0) {
|
||||
long endTime = System.nanoTime();
|
||||
try {
|
||||
long deltaMs = TimeUnit.NANOSECONDS.toMillis(endTime - startTime);
|
||||
Thread.sleep((long) (deltaMs/runTimeRatio - deltaMs));
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public boolean isCompleted()
|
||||
|
||||
public static GenerationEvent startEvent(DHChunkPos minPos, int size, BatchGenerationEnvironment generationGroup,
|
||||
Steps target, double runTimeRatio)
|
||||
{
|
||||
if (size % 2 == 0) size += 1; // size must be odd for vanilla world gen region to work
|
||||
GenerationEvent event = new GenerationEvent(minPos, size, generationGroup, target, runTimeRatio);
|
||||
event.future = CompletableFuture.supplyAsync(() ->
|
||||
{
|
||||
long runStartTime = System.nanoTime();
|
||||
event.timeoutTime = runStartTime;
|
||||
event.inQueueTime = runStartTime - event.inQueueTime;
|
||||
event.timer = new EventTimer("setup");
|
||||
BatchGenerationEnvironment.isDistantGeneratorThread.set(true);
|
||||
try {
|
||||
return generationGroup.generateLodFromList(event);
|
||||
} finally {
|
||||
BatchGenerationEnvironment.isDistantGeneratorThread.remove();
|
||||
if (!Thread.interrupted() && runTimeRatio < 1.0) {
|
||||
long endTime = System.nanoTime();
|
||||
try {
|
||||
long deltaMs = TimeUnit.NANOSECONDS.toMillis(endTime - runStartTime);
|
||||
Thread.sleep((long) (deltaMs/runTimeRatio - deltaMs));
|
||||
} catch (InterruptedException ignored) {}
|
||||
}
|
||||
}
|
||||
}, generationGroup.executors);
|
||||
return event;
|
||||
}
|
||||
|
||||
public boolean isComplete()
|
||||
{
|
||||
return future.isDone();
|
||||
}
|
||||
|
||||
|
||||
public boolean hasTimeout(int duration, TimeUnit unit)
|
||||
{
|
||||
long currentTime = System.nanoTime();
|
||||
long delta = currentTime - creationNanotime;
|
||||
long delta = currentTime - timeoutTime;
|
||||
return (delta > TimeUnit.NANOSECONDS.convert(duration, unit));
|
||||
}
|
||||
|
||||
|
||||
public boolean terminate()
|
||||
{
|
||||
LOGGER.info("======================DUMPING ALL THREADS FOR WORLD GEN=======================");
|
||||
@@ -108,36 +114,30 @@ public final class GenerationEvent
|
||||
return future.isCancelled();
|
||||
}
|
||||
|
||||
public void join()
|
||||
public boolean tooClose(int minX, int minZ, int w)
|
||||
{
|
||||
try
|
||||
{
|
||||
future.get();
|
||||
}
|
||||
catch (InterruptedException | ExecutionException e)
|
||||
{
|
||||
throw new RuntimeException(e.getCause()==null? e : e.getCause());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean tooClose(int cx, int cz, int cr)
|
||||
{
|
||||
int distX = Math.abs(cx - pos.x);
|
||||
int distZ = Math.abs(cz - pos.z);
|
||||
int minRange = cr + range + 1; // Need one to account for the center
|
||||
minRange += 1 + 1; // Account for required empty chunks
|
||||
return distX < minRange && distZ < minRange;
|
||||
int aMinX = minPos.x;
|
||||
int aMinZ = minPos.z;
|
||||
int aSize = size;
|
||||
// Account for required empty chunks in the border
|
||||
aSize += 1;
|
||||
w+= 1;
|
||||
// Do a AABB to AABB intersection test
|
||||
return (aMinX + aSize >= minX &&
|
||||
aMinX <= minX + w &&
|
||||
aMinZ + aSize >= minZ &&
|
||||
aMinZ <= minZ + w);
|
||||
}
|
||||
|
||||
public void refreshTimeout()
|
||||
{
|
||||
creationNanotime = System.nanoTime();
|
||||
timeoutTime = System.nanoTime();
|
||||
LodUtil.checkInterruptsUnchecked();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return id + ":" + range + "@" + pos + "(" + target + ")";
|
||||
return id + ":" + size + "@" + minPos + "(" + target + ")";
|
||||
}
|
||||
}
|
||||
@@ -48,6 +48,6 @@ public class Rolling
|
||||
|
||||
public double getAverage()
|
||||
{
|
||||
return total / size;
|
||||
return size==0 ? 0 : total / size;
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -87,7 +87,8 @@ public final class StepStructureStart {
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
// There's a rare issue with StructStart where it throws ArrayIndexOutOfBounds
|
||||
// This means the structFeat is corrupted (For some reason) and I need to reset it.
|
||||
// TODO: Figure out in the future why this happens even though I am using new structFeat
|
||||
// TODO: Figure out in the future why this happens even though I am using new structFeat - OLD
|
||||
// TODO: Is this still a problem?
|
||||
throw new StepStructureStart.StructStartCorruptedException(e);
|
||||
}
|
||||
#endif
|
||||
|
||||
+1
-1
Submodule core updated: 5f486b6258...973be40324
Reference in New Issue
Block a user