Prep the IChunkGenerator/BatchGenerator for using the API

This commit is contained in:
James Seibel
2022-12-03 19:45:44 -06:00
parent 6fd47f360c
commit 24260a057a
4 changed files with 70 additions and 47 deletions
@@ -29,7 +29,6 @@ import com.seibel.lod.core.util.BitShiftUtil;
import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractBatchGenerationEnvionmentWrapper;
import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractBatchGenerationEnvionmentWrapper.Steps;
import org.apache.logging.log4j.Logger;
@@ -44,26 +43,49 @@ import java.util.function.Consumer;
*/
public class BatchGenerator implements IChunkGenerator
{
public static final boolean ENABLE_GENERATOR_STATS_LOGGING = false;
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
private static final IWrapperFactory FACTORY = SingletonInjector.INSTANCE.get(IWrapperFactory.class);
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
public AbstractBatchGenerationEnvionmentWrapper generationGroup;
public IDhLevel targetLodLevel;
public static final int generationGroupSize = 4;
private static final Logger LOGGER = DhLoggerBuilder.getLogger(MethodHandles.lookup().lookupClass().getSimpleName());
public IDhLevel targetDhLevel;
public BatchGenerator(IDhLevel targetLodLevel)
public BatchGenerator(IDhLevel targetDhLevel)
{
this.targetLodLevel = targetLodLevel;
this.generationGroup = FACTORY.createBatchGenerator(targetLodLevel);
this.targetDhLevel = targetDhLevel;
this.generationGroup = FACTORY.createBatchGenerator(targetDhLevel);
LOGGER.info("Batch Chunk Generator initialized");
}
//======================//
// generator parameters //
//======================//
@Override
public byte getMinDataDetailLevel() { return LodUtil.BLOCK_DETAIL_LEVEL; }
@Override
public byte getMaxDataDetailLevel() { return LodUtil.BLOCK_DETAIL_LEVEL; }
@Override
public byte getMinGenerationGranularity() { return LodUtil.CHUNK_DETAIL_LEVEL; }
@Override
public byte getMaxGenerationGranularity() { return LodUtil.CHUNK_DETAIL_LEVEL + 2; }
//===================//
// generator methods //
//===================//
@Override
public void close() { this.stop(true); }
public void stop(boolean blocking)
{
LOGGER.info("Batch Chunk Generator shutting down...");
@@ -87,7 +109,7 @@ public class BatchGenerator implements IChunkGenerator
targetStep = Steps.Empty; // NOTE: Only load in existing chunks. No new chunk generation
break;
case BIOME_ONLY:
targetStep = Steps.Biomes; // NOTE: No block. Require fake height in LodBuilder
targetStep = Steps.Biomes; // NOTE: No blocks. Require fake height in LodBuilder
break;
case BIOME_ONLY_SIMULATE_HEIGHT:
targetStep = Steps.Noise; // NOTE: Stone only. Require fake surface
@@ -100,11 +122,10 @@ public class BatchGenerator implements IChunkGenerator
targetStep = Steps.Features;
break;
}
;
int chunkXMin = chunkPosMin.x;
int chunkZMin = chunkPosMin.z;
int genChunkSize = BitShiftUtil.powerOfTwo(granularity - 4); // minus 4 for chunk size is equal to dividing by 16
int genChunkSize = BitShiftUtil.powerOfTwo(granularity - 4); // minus 4 is equal to dividing by 16 to convert to chunk scale
double runTimeRatio = Config.Client.Advanced.Threading.numberOfWorldGenerationThreads.get() > 1 ?
1.0 :
Config.Client.Advanced.Threading.numberOfWorldGenerationThreads.get();
@@ -112,23 +133,6 @@ public class BatchGenerator implements IChunkGenerator
}
@Override
public byte getMinDataDetailLevel() { return LodUtil.BLOCK_DETAIL_LEVEL; }
@Override
public byte getMaxDataDetailLevel() { return LodUtil.BLOCK_DETAIL_LEVEL; }
@Override
public int getPriority() { return LodUtil.BLOCK_DETAIL_LEVEL; }
@Override
public byte getMinGenerationGranularity() { return LodUtil.CHUNK_DETAIL_LEVEL; }
@Override
public byte getMaxGenerationGranularity() { return LodUtil.CHUNK_DETAIL_LEVEL + 2; }
@Override
public void close() { this.stop(true); }
public void update() { this.generationGroup.updateAllFutures(); }
public void preGeneratorTaskStart() { this.generationGroup.updateAllFutures(); }
}
@@ -22,18 +22,16 @@ public interface IChunkGenerator extends Closeable
/**
* What is the detail/resolution of the data? (This will offset the generation granularity)
* (minimum detail is 0, maximum detail is 255) (though that high isn't really... realistic)
* (0 = 1x1 block per data, 1 = 2x2 block per data, 2 = 4x4 block per data... etc.)
* (0 = 1x1 block per data, 1 = 2x2 block per data, 2 = 4x4 block per data, etc. This measured in the same units as LOD Detail Level.)
* TODO: System currently only supports 1x1 block per data.
*/
byte getMinDataDetailLevel();
byte getMaxDataDetailLevel();
int getPriority();
/**
* What is the min batch size of a single generation call?
* (minimum return value is 4 since that's the MC chunk size)
* (4 -> 16x16 data per call, 5 -> 32x32 data per call, 6 -> 64x64 data per call... etc.)
* (4 -> 16x16 data per call, 5 -> 32x32 data per call, 6 -> 64x64 data per call, etc. This measured in the same units as LOD Detail Level.)
*/
byte getMinGenerationGranularity();
@@ -41,7 +39,7 @@ public interface IChunkGenerator extends Closeable
* What is the max batch size of a single generation call?
* The system will try to group tasks to the max batch size if possible
* (minimum return value is 4 since that's the MC chunk size)
* (4 -> 16x16 data per call, 5 -> 32x32 data per call, 6 -> 64x64 data per call... etc.)
* (4 -> 16x16 data per call, 5 -> 32x32 data per call, 6 -> 64x64 data per call, etc. This measured in the same units as LOD Detail Level.)
*/
byte getMaxGenerationGranularity();
@@ -62,7 +60,7 @@ public interface IChunkGenerator extends Closeable
/**
* Start a generation event
* (Note that the chunkPos is always aligned to the granularity)
* (For example, if the granularity is 4, data detail is 0, the chunkPos will be aligned to 16x16 blocks)
* (For example, if the granularity is 4 (chunk sized) with a data detail level of 0 (block sized), the chunkPos will be aligned to 16x16 blocks)
*/
default CompletableFuture<Void> generate(DhChunkPos chunkPosMin,
byte granularity, byte targetDataDetail,
@@ -75,4 +73,25 @@ public interface IChunkGenerator extends Closeable
}
//===============//
// event methods //
//===============//
/**
* Called before a new generator task is started. <br>
* This can be used to run cleanup on existing tasks before new tasks are started.
*/
void preGeneratorTaskStart();
//===========//
// overrides //
//===========//
// This is overridden to remove the "throws IOException"
// that is present in the default Closeable.close() method
@Override
void close();
}
@@ -410,8 +410,7 @@ public class WorldGenerationQueue implements Closeable
DhChunkPos chunkPosMin = new DhChunkPos(pos.getCorner());
LOGGER.info("Generating section {} with granularity {} at {}", pos, granularity, chunkPosMin);
task.genFuture = this.generator.generate(
chunkPosMin, granularity, dataDetail, task.group::accept);
task.genFuture = this.generator.generate(chunkPosMin, granularity, dataDetail, task.group::accept);
task.genFuture.whenComplete((v, ex) -> {
if (ex != null)
{
@@ -5,6 +5,7 @@ import com.seibel.lod.core.datatype.full.ChunkSizedData;
import com.seibel.lod.core.datatype.full.FullDataSource;
import com.seibel.lod.core.datatype.transform.ChunkToLodBuilder;
import com.seibel.lod.core.file.datafile.IDataSourceProvider;
import com.seibel.lod.core.generation.IChunkGenerator;
import com.seibel.lod.core.generation.WorldGenerationQueue;
import com.seibel.lod.core.pos.DhLodPos;
import com.seibel.lod.core.pos.DhSectionPos;
@@ -316,7 +317,7 @@ public class DhClientServerLevel implements IDhClientLevel, IDhServerLevel
if (wgs != null)
{
wgs.batchGenerator.update();
wgs.chunkGenerator.preGeneratorTaskStart();
wgs.worldGenerationQueue.pollAndStartClosest(new DhBlockPos2D(MC_CLIENT.getPlayerBlockPos()));
}
}
@@ -334,7 +335,7 @@ public class DhClientServerLevel implements IDhClientLevel, IDhServerLevel
// helper classes //
//================//
class RenderState
private class RenderState
{
final IClientLevelWrapper clientLevel;
final LodQuadTree tree;
@@ -362,15 +363,15 @@ public class DhClientServerLevel implements IDhClientLevel, IDhServerLevel
}
}
class WorldGenState
private class WorldGenState
{
final BatchGenerator batchGenerator;
final WorldGenerationQueue worldGenerationQueue;
public final IChunkGenerator chunkGenerator;
public final WorldGenerationQueue worldGenerationQueue;
WorldGenState()
{
this.batchGenerator = new BatchGenerator(DhClientServerLevel.this);
this.worldGenerationQueue = new WorldGenerationQueue(this.batchGenerator);
this.chunkGenerator = new BatchGenerator(DhClientServerLevel.this);
this.worldGenerationQueue = new WorldGenerationQueue(this.chunkGenerator);
dataFileHandler.setGenerationQueue(this.worldGenerationQueue);
}
@@ -382,7 +383,7 @@ public class DhClientServerLevel implements IDhClientLevel, IDhServerLevel
{
LOGGER.error("Error closing generation queue", ex);
return null;
}).thenRun(this.batchGenerator::close)
}).thenRun(this.chunkGenerator::close)
.exceptionally(ex ->
{
LOGGER.error("Error closing world gen", ex);