Work on world generator integration to a1.7 rework
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
package com.seibel.lod.core.a7;
|
||||
|
||||
import com.seibel.lod.core.a7.datatype.PlaceHolderRenderSource;
|
||||
|
||||
public interface PlaceHolderQueue {
|
||||
void track(PlaceHolderRenderSource source); // Note: Implementation should only track a weak reference to the source.
|
||||
}
|
||||
@@ -16,6 +16,8 @@ import java.io.OutputStream;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public interface LodRenderSource {
|
||||
DhSectionPos getSectionPos();
|
||||
|
||||
void enableRender(IClientLevel level, LodQuadTree quadTree);
|
||||
void disableRender();
|
||||
boolean isRenderReady();
|
||||
@@ -35,4 +37,9 @@ public interface LodRenderSource {
|
||||
void update(ChunkSizedData chunkData);
|
||||
|
||||
byte getRenderVersion();
|
||||
|
||||
/**
|
||||
* Whether this object is still valid. If not, a new one should be created.
|
||||
*/
|
||||
boolean isValid();
|
||||
}
|
||||
|
||||
+25
-14
@@ -2,57 +2,68 @@ package com.seibel.lod.core.a7.datatype;
|
||||
|
||||
import com.seibel.lod.core.a7.datatype.full.ChunkSizedData;
|
||||
import com.seibel.lod.core.a7.level.IClientLevel;
|
||||
import com.seibel.lod.core.a7.pos.DhSectionPos;
|
||||
import com.seibel.lod.core.a7.render.LodQuadTree;
|
||||
import com.seibel.lod.core.a7.render.RenderBuffer;
|
||||
import com.seibel.lod.core.a7.save.io.render.RenderMetaFile;
|
||||
import com.seibel.lod.core.objects.DHChunkPos;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class EmptyRenderSource implements LodRenderSource {
|
||||
public static final EmptyRenderSource INSTANCE = new EmptyRenderSource();
|
||||
public class PlaceHolderRenderSource implements LodRenderSource {
|
||||
final DhSectionPos pos;
|
||||
boolean isValid = true;
|
||||
public PlaceHolderRenderSource(DhSectionPos pos) {
|
||||
this.pos = pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DhSectionPos getSectionPos() {
|
||||
return pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableRender(IClientLevel level, LodQuadTree quadTree) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disableRender() {
|
||||
}
|
||||
public void disableRender() {}
|
||||
|
||||
@Override
|
||||
public boolean isRenderReady() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
public void dispose() {}
|
||||
@Override
|
||||
public byte getDetailOffset() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean trySwapRenderBuffer(LodQuadTree quadTree, AtomicReference<RenderBuffer> referenceSlot) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveRender(IClientLevel level, RenderMetaFile file, OutputStream dataStream) throws IOException {
|
||||
throw new UnsupportedOperationException("EmptyRenderSource should NEVER be saved!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(ChunkSizedData chunkData) {
|
||||
}
|
||||
public void update(ChunkSizedData chunkData) {}
|
||||
|
||||
@Override
|
||||
public byte getRenderVersion() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void markInvalid() {
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return isValid;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -322,4 +322,9 @@ public class ColumnRenderSource implements LodRenderSource, IColumnDatatype {
|
||||
public byte getRenderVersion() {
|
||||
return LATEST_VERSION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return true; // For now, this is always valid.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
package com.seibel.lod.core.a7.generation;
|
||||
|
||||
import com.seibel.lod.core.a7.PlaceHolderQueue;
|
||||
import com.seibel.lod.core.a7.datatype.PlaceHolderRenderSource;
|
||||
import com.seibel.lod.core.a7.datatype.full.ChunkSizedData;
|
||||
import com.seibel.lod.core.a7.datatype.full.FullDataSource;
|
||||
import com.seibel.lod.core.a7.pos.DhBlockPos2D;
|
||||
import com.seibel.lod.core.a7.pos.DhLodPos;
|
||||
import com.seibel.lod.core.a7.pos.DhSectionPos;
|
||||
import com.seibel.lod.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.lod.core.objects.DHChunkPos;
|
||||
import com.seibel.lod.core.util.gridList.ArrayGridList;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
public class GenerationQueue implements PlaceHolderQueue {
|
||||
private final Logger logger = DhLoggerBuilder.getLogger();
|
||||
DhBlockPos2D lastPlayerPos = new DhBlockPos2D(0, 0);
|
||||
final HashMap<DhSectionPos, WeakReference<PlaceHolderRenderSource>> trackers = new HashMap<>();
|
||||
IGenerator generator = null;
|
||||
final BiConsumer<DhSectionPos, ChunkSizedData> writeConsumer;
|
||||
|
||||
public GenerationQueue(BiConsumer<DhSectionPos, ChunkSizedData> writeConsumer) {
|
||||
this.writeConsumer = writeConsumer;
|
||||
}
|
||||
|
||||
public void track(PlaceHolderRenderSource source) {
|
||||
trackers.put(source.getSectionPos(), new WeakReference<>(source));
|
||||
}
|
||||
|
||||
private void update() {
|
||||
LinkedList<DhSectionPos> toRemove = new LinkedList<>();
|
||||
for (DhSectionPos pos : trackers.keySet()) {
|
||||
WeakReference<PlaceHolderRenderSource> ref = trackers.get(pos);
|
||||
if (ref.get() == null) {
|
||||
toRemove.add(pos);
|
||||
}
|
||||
}
|
||||
for (DhSectionPos pos : toRemove) {
|
||||
trackers.remove(pos);
|
||||
}
|
||||
}
|
||||
|
||||
//FIXME: Do optimizations on polling closest to player. (Currently its a O(n) search!)
|
||||
//FIXME: Do not return sections that is already being generated.
|
||||
private DhSectionPos pollClosest(DhBlockPos2D playerPos) {
|
||||
update();
|
||||
DhSectionPos closest = null;
|
||||
long closestDist = Long.MAX_VALUE;
|
||||
for (DhSectionPos pos : trackers.keySet()) {
|
||||
long distSqr = pos.getCenter().getCenter().distSquared(playerPos);
|
||||
if (distSqr < closestDist) {
|
||||
closest = pos;
|
||||
closestDist = distSqr;
|
||||
}
|
||||
}
|
||||
return closest;
|
||||
}
|
||||
|
||||
public void setGenerator(IGenerator generator) {
|
||||
this.generator = generator;
|
||||
}
|
||||
|
||||
private void write(DhSectionPos pos, ChunkSizedData data) {
|
||||
writeConsumer.accept(pos, data);
|
||||
WeakReference<PlaceHolderRenderSource> ref = trackers.get(pos);
|
||||
if (ref == null) return; // No placeholder there, so no need to trigger a refresh on it.
|
||||
PlaceHolderRenderSource source = ref.get();
|
||||
if (source == null) return; // Same as above.
|
||||
source.markInvalid(); // Mark the placeholder as invalid, so it will be refreshed on next lodTree update.
|
||||
}
|
||||
|
||||
public void doGeneration() {
|
||||
if (generator == null) return;
|
||||
|
||||
DhSectionPos pos = pollClosest(lastPlayerPos);
|
||||
if (pos == null) return;
|
||||
|
||||
byte dataDetail = generator.getDataDetail();
|
||||
byte minGenGranularity = generator.getMinGenerationGranularity();
|
||||
byte maxGenGranularity = generator.getMaxGenerationGranularity();
|
||||
if (minGenGranularity < 4 || maxGenGranularity < 4) {
|
||||
throw new IllegalStateException("Generation granularity must be at least 4!");
|
||||
}
|
||||
|
||||
byte minUnitDetail = (byte) (dataDetail + minGenGranularity);
|
||||
byte maxUnitDetail = (byte) (dataDetail + maxGenGranularity);
|
||||
|
||||
byte granularity;
|
||||
int count;
|
||||
DHChunkPos chunkPosMin;
|
||||
if (pos.sectionDetail < minUnitDetail) {
|
||||
granularity = minGenGranularity;
|
||||
count = 1;
|
||||
chunkPosMin = new DHChunkPos(pos.getSectionBBoxPos().convertUpwardsTo(minUnitDetail).getCorner());
|
||||
} else if (pos.sectionDetail > maxUnitDetail) {
|
||||
granularity = maxGenGranularity;
|
||||
count = 1 << (pos.sectionDetail - maxUnitDetail);
|
||||
chunkPosMin = new DHChunkPos(pos.getCorner().getCorner());
|
||||
} else {
|
||||
granularity = (byte) (pos.sectionDetail - dataDetail);
|
||||
count = 1;
|
||||
chunkPosMin = new DHChunkPos(pos.getCorner().getCorner());
|
||||
}
|
||||
assert granularity >= minGenGranularity && granularity <= maxGenGranularity;
|
||||
assert count > 0;
|
||||
assert granularity >= 4; // Thanks compiler. Guess having a 'always true' warning means I did it right.
|
||||
|
||||
CompletableFuture<ArrayGridList<ChunkSizedData>> dataFuture = generator.generate(chunkPosMin, granularity);
|
||||
|
||||
dataFuture.whenComplete((data, ex) -> {
|
||||
if (ex != null) {
|
||||
logger.error("Error generating data for section " + pos + ": " + ex);
|
||||
return;
|
||||
}
|
||||
assert data != null;
|
||||
if (data.gridSize != count) {
|
||||
logger.error("Generated data grid size (" + data.gridSize
|
||||
+ ") does not match expected size (" + count + ") for section " + pos);
|
||||
return;
|
||||
}
|
||||
final byte sectionDetail = (byte) (dataDetail + FullDataSource.SECTION_SIZE_OFFSET);
|
||||
data.forEachPos((x,z) -> {
|
||||
ChunkSizedData chunkData = data.get(x,z);
|
||||
DhLodPos chunkDataPos = new DhLodPos((byte) (dataDetail + 4), x, z).convertUpwardsTo(sectionDetail);
|
||||
DhSectionPos sectionPos = new DhSectionPos(chunkDataPos.detail, chunkDataPos.x, chunkDataPos.z);
|
||||
write(sectionPos, chunkData);
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.seibel.lod.core.a7.generation;
|
||||
|
||||
import com.seibel.lod.core.a7.datatype.full.ChunkSizedData;
|
||||
import com.seibel.lod.core.a7.datatype.transform.LodDataBuilder;
|
||||
import com.seibel.lod.core.objects.DHChunkPos;
|
||||
import com.seibel.lod.core.util.gridList.ArrayGridList;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public interface IChunkGenerator extends IGenerator {
|
||||
CompletableFuture<ArrayGridList<IChunkWrapper>> generateChunks(DHChunkPos chunkPosMin, byte granularity);
|
||||
|
||||
@Override
|
||||
default CompletableFuture<ArrayGridList<ChunkSizedData>> generate(DHChunkPos chunkPosMin, byte granularity) {
|
||||
return generateChunks(chunkPosMin, granularity).thenApply(chunks -> {
|
||||
ArrayGridList<ChunkSizedData> chunkData = new ArrayGridList<>(chunks.gridSize);
|
||||
chunks.forEachPos((x, y) -> chunkData.set(x, y, LodDataBuilder.createChunkData(chunks.get(x, y))));
|
||||
return chunkData;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.seibel.lod.core.a7.generation;
|
||||
|
||||
import com.seibel.lod.core.a7.datatype.full.ChunkSizedData;
|
||||
import com.seibel.lod.core.objects.DHChunkPos;
|
||||
import com.seibel.lod.core.util.gridList.ArrayGridList;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public interface IGenerator extends AutoCloseable {
|
||||
// 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.)
|
||||
// TODO: System currently only supports 1x1 block per data.
|
||||
byte getDataDetail();
|
||||
// What is the min batch size of a single generation?
|
||||
// (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.)
|
||||
byte getMinGenerationGranularity();
|
||||
// What is the max batch size of a single generation?
|
||||
// (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.)
|
||||
byte getMaxGenerationGranularity();
|
||||
|
||||
// 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)
|
||||
CompletableFuture<ArrayGridList<ChunkSizedData>> generate(DHChunkPos chunkPosMin, byte granularity);
|
||||
|
||||
// Return whether the generator is currently busy and cannot accept new generation requests.
|
||||
boolean isBusy();
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.seibel.lod.core.a7.level;
|
||||
|
||||
import com.seibel.lod.core.a7.generation.GenerationQueue;
|
||||
import com.seibel.lod.core.a7.render.LodQuadTree;
|
||||
import com.seibel.lod.core.a7.util.FileScanner;
|
||||
import com.seibel.lod.core.a7.save.io.file.LocalDataFileHandler;
|
||||
@@ -26,6 +27,7 @@ public class DhClientServerLevel implements IClientLevel, IServerLevel {
|
||||
private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||
public final LocalSaveStructure save;
|
||||
public final LocalDataFileHandler dataFileHandler;
|
||||
public GenerationQueue generationQueue = null;
|
||||
public RenderFileHandler renderFileHandler = null;
|
||||
public RenderBufferHandler renderBufferHandler = null; //TODO: Should this be owned by renderer?
|
||||
public final ILevelWrapper level;
|
||||
@@ -54,7 +56,9 @@ public class DhClientServerLevel implements IClientLevel, IServerLevel {
|
||||
LOGGER.warn("Tried to call startRenderer() on the clientServerLevel {} when renderer is already setup!", level);
|
||||
return;
|
||||
}
|
||||
renderFileHandler = new RenderFileHandler(dataFileHandler, this, save.getRenderCacheFolder(level));
|
||||
|
||||
generationQueue = new GenerationQueue((a,b) -> renderFileHandler.write(a,b)); // FIXME: Ops. A need B and B need A... Does this work?
|
||||
renderFileHandler = new RenderFileHandler(dataFileHandler, this, save.getRenderCacheFolder(level), generationQueue);
|
||||
tree = new LodQuadTree(this, Config.Client.Graphics.Quality.lodChunkRenderDistance.get()*16,
|
||||
MC_CLIENT.getPlayerBlockPos().x, MC_CLIENT.getPlayerBlockPos().z, renderFileHandler);
|
||||
renderBufferHandler = new RenderBufferHandler(tree);
|
||||
@@ -84,6 +88,7 @@ public class DhClientServerLevel implements IClientLevel, IServerLevel {
|
||||
renderFileHandler.flushAndSave(); //Ignore the completion feature so that this action is async
|
||||
renderFileHandler.close();
|
||||
renderFileHandler = null;
|
||||
generationQueue = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -5,5 +5,4 @@ import com.seibel.lod.core.a7.datatype.full.ChunkSizedData;
|
||||
public interface IServerLevel extends ILevel {
|
||||
void serverTick();
|
||||
void doWorldGen();
|
||||
void submitChunkData(ChunkSizedData data);
|
||||
}
|
||||
|
||||
@@ -363,6 +363,8 @@ public class LodQuadTree {
|
||||
} else {
|
||||
if (!section.isLoaded() && !section.isLoading()) {
|
||||
section.load(renderSourceProvider);
|
||||
} else if (section.isOutdated()) {
|
||||
section.reload(renderSourceProvider);
|
||||
}
|
||||
if (section.childCount == 4) section.enableRender(level, this);
|
||||
if (section.childCount == 0) section.disableRender();
|
||||
|
||||
@@ -47,6 +47,13 @@ public class LodRenderSection {
|
||||
if (loadFuture != null || lodRenderSource != null) throw new IllegalStateException("Reloading is not supported!");
|
||||
loadFuture = renderDataProvider.read(pos);
|
||||
}
|
||||
public void reload(IRenderSourceProvider renderDataProvider) {
|
||||
if (loadFuture != null) throw new IllegalStateException("This section is already loading!");
|
||||
if (lodRenderSource == null) throw new IllegalStateException("This section is not loaded!");
|
||||
lodRenderSource.dispose();
|
||||
lodRenderSource = null;
|
||||
loadFuture = renderDataProvider.read(pos);
|
||||
}
|
||||
|
||||
public void tick(LodQuadTree quadTree) {
|
||||
if (loadFuture != null && loadFuture.isDone()) {
|
||||
@@ -78,6 +85,10 @@ public class LodRenderSection {
|
||||
return loadFuture != null;
|
||||
}
|
||||
|
||||
public boolean isOutdated() {
|
||||
return lodRenderSource != null && !lodRenderSource.isValid();
|
||||
}
|
||||
|
||||
public LodRenderSource getRenderContainer() {
|
||||
return lodRenderSource;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.seibel.lod.core.a7.render;
|
||||
|
||||
import com.seibel.lod.core.a7.datatype.LodRenderSource;
|
||||
import com.seibel.lod.core.a7.datatype.full.ChunkSizedData;
|
||||
import com.seibel.lod.core.objects.Pos2D;
|
||||
import com.seibel.lod.core.a7.pos.DhSectionPos;
|
||||
import com.seibel.lod.core.render.LodRenderProgram;
|
||||
|
||||
@@ -1,23 +1,16 @@
|
||||
package com.seibel.lod.core.a7.save.io.render;
|
||||
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.seibel.lod.core.a7.datatype.EmptyRenderSource;
|
||||
import com.seibel.lod.core.a7.datatype.LodDataSource;
|
||||
import com.seibel.lod.core.a7.PlaceHolderQueue;
|
||||
import com.seibel.lod.core.a7.datatype.PlaceHolderRenderSource;
|
||||
import com.seibel.lod.core.a7.datatype.LodRenderSource;
|
||||
import com.seibel.lod.core.a7.datatype.RenderSourceLoader;
|
||||
import com.seibel.lod.core.a7.datatype.column.ColumnRenderLoader;
|
||||
import com.seibel.lod.core.a7.datatype.column.ColumnRenderSource;
|
||||
import com.seibel.lod.core.a7.datatype.full.ChunkSizedData;
|
||||
import com.seibel.lod.core.a7.datatype.full.FullFormat;
|
||||
import com.seibel.lod.core.a7.level.IClientLevel;
|
||||
import com.seibel.lod.core.a7.save.io.file.DataMetaFile;
|
||||
import com.seibel.lod.core.a7.save.io.file.IDataSourceProvider;
|
||||
import com.seibel.lod.core.a7.pos.DhSectionPos;
|
||||
import com.seibel.lod.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.lod.core.objects.DHChunkPos;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.lwjgl.system.CallbackI;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -33,11 +26,13 @@ public class RenderFileHandler implements IRenderSourceProvider {
|
||||
final IClientLevel level;
|
||||
final File saveDir;
|
||||
final IDataSourceProvider dataSourceProvider;
|
||||
final PlaceHolderQueue placeHolderQueue;
|
||||
|
||||
public RenderFileHandler(IDataSourceProvider sourceProvider, IClientLevel level, File saveRootDir) {
|
||||
public RenderFileHandler(IDataSourceProvider sourceProvider, IClientLevel level, File saveRootDir, PlaceHolderQueue placeHolderQueue) {
|
||||
this.dataSourceProvider = sourceProvider;
|
||||
this.level = level;
|
||||
this.saveDir = saveRootDir;
|
||||
this.placeHolderQueue = placeHolderQueue;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -118,7 +113,9 @@ public class RenderFileHandler implements IRenderSourceProvider {
|
||||
LOGGER.error("Uncaught error on {}:", pos, e);
|
||||
}
|
||||
if (render != null) return render;
|
||||
return EmptyRenderSource.INSTANCE;
|
||||
PlaceHolderRenderSource placeHolder = new PlaceHolderRenderSource(pos);
|
||||
placeHolderQueue.track(placeHolder);
|
||||
return placeHolder;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -19,24 +19,29 @@
|
||||
|
||||
package com.seibel.lod.core.builders.worldGeneration;
|
||||
|
||||
import com.seibel.lod.core.a7.generation.IChunkGenerator;
|
||||
import com.seibel.lod.core.a7.level.ILevel;
|
||||
import com.seibel.lod.core.config.Config;
|
||||
import com.seibel.lod.core.enums.config.EDistanceGenerationMode;
|
||||
import com.seibel.lod.core.enums.config.EGenerationPriority;
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.lod.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.lod.core.objects.DHChunkPos;
|
||||
import com.seibel.lod.core.objects.PosToGenerateContainer;
|
||||
import com.seibel.lod.core.util.LevelPosUtil;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.util.gridList.ArrayGridList;
|
||||
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;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class BatchGenerator
|
||||
public class BatchGenerator implements IChunkGenerator
|
||||
{
|
||||
public static final boolean ENABLE_GENERATOR_STATS_LOGGING = false;
|
||||
|
||||
@@ -254,4 +259,60 @@ public class BatchGenerator
|
||||
generationGroup.stop(blocking);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBusy() {
|
||||
return generationGroup.getEventCount() > previousThreadCount*1.5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<ArrayGridList<IChunkWrapper>> generateChunks(DHChunkPos chunkPosMin, byte granularity) {
|
||||
EDistanceGenerationMode mode = Config.Client.WorldGenerator.distanceGenerationMode.get();
|
||||
Steps targetStep = null;
|
||||
switch (mode) {
|
||||
case NONE:
|
||||
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
|
||||
break;
|
||||
case BIOME_ONLY_SIMULATE_HEIGHT:
|
||||
targetStep = Steps.Noise; // NOTE: Stone only. Require fake surface
|
||||
break;
|
||||
case SURFACE:
|
||||
targetStep = Steps.Surface; // Carvers or Surface???
|
||||
break;
|
||||
case FEATURES:
|
||||
case FULL:
|
||||
targetStep = Steps.Features;
|
||||
break;
|
||||
};
|
||||
|
||||
|
||||
int chunkXMin = chunkPosMin.x;
|
||||
int chunkZMin = chunkPosMin.z;
|
||||
int genChunkSize = 1 << (granularity - 4); // minus 4 for chunk size as its equal to div by 16
|
||||
double runTimeRatio = Config.Client.Advanced.Threading.numberOfWorldGenerationThreads.get()>1 ? 1.0
|
||||
: Config.Client.Advanced.Threading.numberOfWorldGenerationThreads.get();
|
||||
return generationGroup.generateChunks(chunkXMin, chunkZMin, genChunkSize, targetStep, runTimeRatio);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getDataDetail() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getMinGenerationGranularity() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getMaxGenerationGranularity() {
|
||||
return 16;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
stop(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,10 @@ public class DHChunkPos {
|
||||
this.x = blockPos.x >> 4; // Same as div 16
|
||||
this.z = blockPos.z >> 4; // Same as div 16
|
||||
}
|
||||
public DHChunkPos(DhBlockPos2D blockPos) {
|
||||
this.x = blockPos.x >> 4; // Same as div 16
|
||||
this.z = blockPos.z >> 4; // Same as div 16
|
||||
}
|
||||
|
||||
public DHBlockPos center() {
|
||||
return new DHBlockPos(8 + x << 4, 0, 8 + z << 4);
|
||||
|
||||
+8
@@ -20,6 +20,10 @@
|
||||
package com.seibel.lod.core.wrapperInterfaces.worldGeneration;
|
||||
|
||||
import com.seibel.lod.core.a7.level.ILevel;
|
||||
import com.seibel.lod.core.util.gridList.ArrayGridList;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public abstract class AbstractBatchGenerationEnvionmentWrapper {
|
||||
public enum Steps {
|
||||
@@ -31,11 +35,15 @@ public abstract class AbstractBatchGenerationEnvionmentWrapper {
|
||||
|
||||
public abstract void resizeThreadPool(int newThreadCount);
|
||||
|
||||
@Deprecated
|
||||
public abstract void updateAllFutures();
|
||||
|
||||
public abstract int getEventCount();
|
||||
|
||||
@Deprecated
|
||||
public abstract boolean tryAddPoint(int chunkX, int chunkZ, int genSize, Steps targetStep, boolean genAllDetails, double runTimeRatio);
|
||||
|
||||
public abstract void stop(boolean blocking);
|
||||
|
||||
public abstract CompletableFuture<ArrayGridList<IChunkWrapper>> generateChunks(int minX, int minZ, int genSize, Steps targetStep, double runTimeRatio);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user