Added experimental world generator. (Features mode only for now)
Turn on the AllowUnstableFeatureGeneration button to enable it. It is a temp setting and will be renamed later. There will be many issues with the generator, but at least it for now works... To be fixed tomorrow.
This commit is contained in:
@@ -25,9 +25,11 @@ import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractExperimentalWorldGeneratorWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractWorldGeneratorWrapper;
|
||||
import com.seibel.lod.common.wrappers.block.BlockPosWrapper;
|
||||
import com.seibel.lod.common.wrappers.chunk.ChunkPosWrapper;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.ExperimentalGenerator;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.WorldGeneratorWrapper;
|
||||
|
||||
/**
|
||||
@@ -96,4 +98,9 @@ public class WrapperFactory implements IWrapperFactory
|
||||
{
|
||||
return new WorldGeneratorWrapper(newLodBuilder, newLodDimension, worldWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractExperimentalWorldGeneratorWrapper createExperimentalWorldGenerator(LodBuilder newLodBuilder, LodDimension newLodDimension, IWorldWrapper worldWrapper) {
|
||||
return new ExperimentalGenerator(newLodBuilder, newLodDimension, worldWrapper);
|
||||
}
|
||||
}
|
||||
|
||||
+174
@@ -0,0 +1,174 @@
|
||||
package com.seibel.lod.common.wrappers.worldGeneration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import com.seibel.lod.common.wrappers.world.WorldWrapper;
|
||||
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;
|
||||
import com.seibel.lod.core.objects.PosToGenerateContainer;
|
||||
import com.seibel.lod.core.objects.lod.LodDimension;
|
||||
import com.seibel.lod.core.util.LevelPosUtil;
|
||||
import com.seibel.lod.core.util.SingletonHandler;
|
||||
import com.seibel.lod.core.wrapperInterfaces.IVersionConstants;
|
||||
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractExperimentalWorldGeneratorWrapper;
|
||||
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
|
||||
public class ExperimentalGenerator extends AbstractExperimentalWorldGeneratorWrapper {
|
||||
private static final IMinecraftWrapper MC = SingletonHandler.get(IMinecraftWrapper.class);
|
||||
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
|
||||
private static final IWrapperFactory WRAPPER_FACTORY = SingletonHandler.get(IWrapperFactory.class);
|
||||
private static final IVersionConstants VERSION_CONSTANTS = SingletonHandler.get(IVersionConstants.class);
|
||||
public WorldGenerationStep generationGroup;
|
||||
public LodDimension targetLodDim;
|
||||
private boolean generatorThreadRunning = false;
|
||||
|
||||
public ExperimentalGenerator(LodBuilder newLodBuilder, LodDimension newLodDimension, IWorldWrapper worldWrapper) {
|
||||
super(newLodBuilder, newLodDimension, worldWrapper);
|
||||
System.out.println("================ExperimentalGenerator_INITING=============");
|
||||
generationGroup = new WorldGenerationStep(((WorldWrapper) worldWrapper).getServerWorld(), newLodBuilder, newLodDimension);
|
||||
}
|
||||
|
||||
private static boolean isFarEnough(int genRange, int cax, int cay, int cbx, int cby) {
|
||||
int dist = Math.min(Math.abs(cax-cbx), Math.abs(cay-cby));
|
||||
// return true;
|
||||
return dist > genRange*2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queueGenerationRequests(LodDimension lodDim, LodBuilder lodBuilder) {
|
||||
ExecutorService executor = generationGroup.executors;
|
||||
DistanceGenerationMode mode = CONFIG.client().worldGenerator().getDistanceGenerationMode();
|
||||
|
||||
if (mode != DistanceGenerationMode.NONE
|
||||
&& !generatorThreadRunning
|
||||
&& MC.hasSinglePlayerServer())
|
||||
{
|
||||
generatorThreadRunning = true;
|
||||
|
||||
Runnable runner = () -> {
|
||||
System.out.println("================ExperimentalGenerator_Run=============");
|
||||
try
|
||||
{
|
||||
int maxSamples = 512;
|
||||
int genRange = 8;
|
||||
int points = 8;
|
||||
// round the player's block position down to the nearest chunk BlockPos
|
||||
int playerPosX = MC.getPlayerBlockPos().getX();
|
||||
int playerPosZ = MC.getPlayerBlockPos().getZ();
|
||||
|
||||
//=======================================//
|
||||
// fill in positionsWaitingToBeGenerated //
|
||||
//=======================================//
|
||||
|
||||
ArrayList<ChunkPos> genPos = new ArrayList<ChunkPos>(points);
|
||||
|
||||
PosToGenerateContainer posToGenerate = lodDim.getPosToGenerate(
|
||||
maxSamples, playerPosX, playerPosZ);
|
||||
|
||||
byte detailLevel;
|
||||
int posX;
|
||||
int posZ;
|
||||
int nearIndex = 0;
|
||||
int farIndex = 0;
|
||||
|
||||
for (int i = 0; i < posToGenerate.getNumberOfPos(); i++)
|
||||
{
|
||||
|
||||
// add the near positions
|
||||
if (nearIndex < posToGenerate.getNumberOfNearPos() && posToGenerate.getNthDetail(nearIndex, true) != 0)
|
||||
{
|
||||
detailLevel = (byte) (posToGenerate.getNthDetail(nearIndex, true) - 1);
|
||||
posX = posToGenerate.getNthPosX(nearIndex, true);
|
||||
posZ = posToGenerate.getNthPosZ(nearIndex, true);
|
||||
nearIndex++;
|
||||
ChunkPos chunkPos = new ChunkPos(LevelPosUtil.getChunkPos(detailLevel, posX), LevelPosUtil.getChunkPos(detailLevel, posZ));
|
||||
|
||||
boolean tooClose = false;
|
||||
for (ChunkPos pos : genPos) {
|
||||
if (!isFarEnough(genRange, pos.x, pos.z, chunkPos.x, chunkPos.z)) {
|
||||
tooClose = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tooClose) continue;
|
||||
genPos.add(chunkPos);
|
||||
if (genPos.size() >= points) break;
|
||||
}
|
||||
|
||||
// add the far positions
|
||||
if (farIndex < posToGenerate.getNumberOfFarPos() && posToGenerate.getNthDetail(farIndex, false) != 0)
|
||||
{
|
||||
detailLevel = (byte) (posToGenerate.getNthDetail(farIndex, false) - 1);
|
||||
posX = posToGenerate.getNthPosX(farIndex, false);
|
||||
posZ = posToGenerate.getNthPosZ(farIndex, false);
|
||||
farIndex++;
|
||||
|
||||
ChunkPos chunkPos = new ChunkPos(LevelPosUtil.getChunkPos(detailLevel, posX), LevelPosUtil.getChunkPos(detailLevel, posZ));
|
||||
|
||||
boolean tooClose = false;
|
||||
for (ChunkPos pos : genPos) {
|
||||
if (!isFarEnough(genRange, pos.x, pos.z, chunkPos.x, chunkPos.z)) {
|
||||
tooClose = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tooClose) continue;
|
||||
genPos.add(chunkPos);
|
||||
if (genPos.size() >= points) break;
|
||||
}
|
||||
}
|
||||
System.out.println("WorldGenerator: "+genPos.size()+" number of positions queried.");
|
||||
|
||||
ArrayList<Future<?>> futures = new ArrayList<Future<?>>();
|
||||
|
||||
for (ChunkPos pos : genPos) {
|
||||
futures.add(executor.submit(() -> {
|
||||
generationGroup.generateLodFromList(pos, genRange, Steps.Features);
|
||||
}));
|
||||
}
|
||||
|
||||
for (Future<?> f : futures) {
|
||||
try {
|
||||
f.get(30, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (ExecutionException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (TimeoutException e) {
|
||||
f.cancel(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
// this shouldn't ever happen, but just in case
|
||||
e.printStackTrace();
|
||||
}
|
||||
finally
|
||||
{
|
||||
generatorThreadRunning = false;
|
||||
}
|
||||
};
|
||||
executor.execute(runner);
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
generationGroup.executors.shutdownNow();
|
||||
}
|
||||
|
||||
}
|
||||
+688
@@ -0,0 +1,688 @@
|
||||
package com.seibel.lod.common.wrappers.worldGeneration;
|
||||
|
||||
import com.seibel.lod.core.builders.lodBuilding.LodBuilder;
|
||||
import com.seibel.lod.core.builders.lodBuilding.LodBuilderConfig;
|
||||
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
|
||||
import com.seibel.lod.core.objects.lod.LodDimension;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
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 net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.WorldGenRegion;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.chunk.*;
|
||||
import net.minecraft.server.level.ThreadedLevelLightEngine;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.world.level.levelgen.GenerationStep;
|
||||
import net.minecraft.world.level.levelgen.Heightmap;
|
||||
import net.minecraft.world.level.levelgen.WorldGenSettings;
|
||||
import net.minecraft.world.level.levelgen.blending.Blender;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
|
||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||
|
||||
public class WorldGenerationStep {
|
||||
ServerLevel level;
|
||||
ChunkGenerator generator;
|
||||
StructureManager structures;
|
||||
ThreadedLevelLightEngine lightEngine;
|
||||
LodBuilder lodBuilder;
|
||||
LodDimension lodDim;
|
||||
Registry<Biome> biomes;
|
||||
public ExecutorService executors = Executors.newFixedThreadPool(8, new ThreadFactoryBuilder().setNameFormat("Gen-Worker-Thread-%d").build());
|
||||
|
||||
public WorldGenerationStep(ServerLevel level, LodBuilder lodBuilder, LodDimension lodDim) {
|
||||
System.out.println("================WORLD_GEN_STEP_INITING=============");
|
||||
this.level = level;
|
||||
this.lodBuilder = lodBuilder;
|
||||
this.lodDim = lodDim;
|
||||
lightEngine = (ThreadedLevelLightEngine) level.getLightEngine();
|
||||
biomes = level.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY);
|
||||
generator = level.getChunkSource().getGenerator();
|
||||
structures = level.getStructureManager();
|
||||
StepStructureStart.onLevelLoad(level.getServer().getWorldData().worldGenSettings());
|
||||
StepBiomes.onLevelLoad(level.registryAccess());
|
||||
// Note: This will be problematic...
|
||||
StepLight.onLevelLoad(lightEngine);
|
||||
|
||||
}
|
||||
|
||||
public static final class GridList<T> extends ArrayList<T> implements List<T> {
|
||||
|
||||
private static final long serialVersionUID = 1585978374811888116L;
|
||||
public final int gridCentreToEdge;
|
||||
public final int gridSize;
|
||||
|
||||
public GridList(int gridCentreToEdge) {
|
||||
super((gridCentreToEdge * 2 + 1) * (gridCentreToEdge * 2 + 1));
|
||||
gridSize = gridCentreToEdge * 2 + 1;
|
||||
this.gridCentreToEdge = gridCentreToEdge;
|
||||
}
|
||||
|
||||
public final int offsetOf(int index, int x, int y) {
|
||||
return index + x + y * gridSize;
|
||||
}
|
||||
|
||||
public GridList<T> subGrid(int centreIndex, int gridCentreToEdge) {
|
||||
GridList<T> subGrid = new GridList<T>(gridCentreToEdge);
|
||||
for (int oy = -gridCentreToEdge; oy <= gridCentreToEdge; oy++) {
|
||||
int begin = offsetOf(centreIndex, -gridCentreToEdge, oy);
|
||||
int end = offsetOf(centreIndex, gridCentreToEdge, oy);
|
||||
subGrid.addAll(this.subList(begin, end+1));
|
||||
}
|
||||
return subGrid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GridList "+gridSize+"*"+gridSize+"["+size()+"]";
|
||||
}
|
||||
}
|
||||
|
||||
public static class ChunkSynconizer {
|
||||
|
||||
private ReentrantLock uniqueOwnerLock = new ReentrantLock();
|
||||
ChunkAccess chunk;
|
||||
Steps completedStep = Steps.Empty;
|
||||
|
||||
public ChunkSynconizer(ChunkPos pos, ServerLevel level, Registry<Biome> biomes) {
|
||||
chunk = new ProtoChunk(pos, UpgradeData.EMPTY, level, biomes, null);
|
||||
}
|
||||
|
||||
public boolean tryClaimOwnerLock() {
|
||||
return uniqueOwnerLock.tryLock();
|
||||
}
|
||||
|
||||
public void releaseOwnerLock() {
|
||||
uniqueOwnerLock.unlock();
|
||||
}
|
||||
|
||||
public boolean hasCompletedStep(Steps step) {
|
||||
return step.compareTo(completedStep) <= 0;
|
||||
}
|
||||
|
||||
public void set(ChunkAccess newChunk, Steps newStep) {
|
||||
chunk = newChunk;
|
||||
completedStep = newStep;
|
||||
}
|
||||
|
||||
public void set(Steps newStep) {
|
||||
completedStep = newStep;
|
||||
}
|
||||
}
|
||||
|
||||
ConcurrentHashMap<Long, ChunkSynconizer> chunks = new ConcurrentHashMap<Long, ChunkSynconizer>();
|
||||
// No longer using Long2ObjectLinkedOpenHashMap as I doubt it is multithread
|
||||
// safe.
|
||||
|
||||
private static final long toLongPos(int cx, int cy) {
|
||||
return ChunkPos.asLong(cx, cy);
|
||||
}
|
||||
|
||||
private final ChunkSynconizer getChunkSynconizer(long pos) {
|
||||
ChunkSynconizer chunk = chunks.get(pos);
|
||||
if (chunk != null)
|
||||
return chunk;
|
||||
chunk = new ChunkSynconizer(new ChunkPos(pos), level, biomes);
|
||||
ChunkSynconizer oldVal = chunks.putIfAbsent(pos, chunk);
|
||||
if (oldVal != null)
|
||||
return oldVal;
|
||||
return chunk;
|
||||
}
|
||||
|
||||
public void generateLodFromList(ChunkPos pos, int range, Steps step) {
|
||||
System.out.println("generateLodFromList("+pos.toString()+", "+range+", "+step+")");
|
||||
GridList<ChunkSynconizer> referencedChunks;
|
||||
DistanceGenerationMode generationMode;
|
||||
switch (step) {
|
||||
case Empty:
|
||||
return;
|
||||
case StructureStart:
|
||||
referencedChunks = generateStructureStart(pos, range);
|
||||
generationMode = DistanceGenerationMode.NONE;
|
||||
break;
|
||||
case StructureReference:
|
||||
referencedChunks = generateStructureReference(pos, range);
|
||||
generationMode = DistanceGenerationMode.NONE;
|
||||
break;
|
||||
case Biomes:
|
||||
referencedChunks = generateBiomes(pos, range);
|
||||
generationMode = DistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT;
|
||||
break;
|
||||
case Noise:
|
||||
referencedChunks = generateNoise(pos, range);
|
||||
generationMode = DistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT;
|
||||
break;
|
||||
case Surface:
|
||||
referencedChunks = generateSurface(pos, range);
|
||||
generationMode = DistanceGenerationMode.SURFACE;
|
||||
break;
|
||||
case Carvers:
|
||||
referencedChunks = generateCarvers(pos, range);
|
||||
generationMode = DistanceGenerationMode.SURFACE;
|
||||
break;
|
||||
case Features:
|
||||
referencedChunks = generateFeatures(pos, range);
|
||||
generationMode = DistanceGenerationMode.FEATURES;
|
||||
break;
|
||||
case Light:
|
||||
return;
|
||||
case LiquidCarvers:
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
int centreIndex = referencedChunks.size() / 2;
|
||||
|
||||
for (int ox = -range; ox <= range; ox++) {
|
||||
for (int oy = -range; oy <= range; oy++) {
|
||||
int targetIndex = referencedChunks.offsetOf(centreIndex, ox, oy);
|
||||
ChunkSynconizer target = referencedChunks.get(targetIndex);
|
||||
lodBuilder.generateLodNodeFromChunk(lodDim, new ChunkWrapper(target.chunk), new LodBuilderConfig(generationMode));
|
||||
}
|
||||
}
|
||||
System.out.println("EXIT: generateLodFromList("+pos.toString()+", "+range+", "+step+")");
|
||||
}
|
||||
|
||||
public GridList<ChunkSynconizer> generateStructureStart(ChunkPos pos, int range) {
|
||||
System.out.println("generateStructureStart("+pos.toString()+", "+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));
|
||||
chunks.add(target);
|
||||
if (!target.hasCompletedStep(Steps.StructureStart)) {
|
||||
|
||||
boolean owned = target.tryClaimOwnerLock();
|
||||
if (owned) {
|
||||
try {
|
||||
ChunkAccess access = target.chunk;
|
||||
target.set(StepStructureStart.generate(level, generator, structures, access),
|
||||
Steps.StructureStart);
|
||||
} finally {
|
||||
target.releaseOwnerLock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
//System.out.println("EXIT: generateStructureStart("+pos.toString()+", "+range+") -> "+chunks);
|
||||
return chunks;
|
||||
}
|
||||
|
||||
public GridList<ChunkSynconizer> generateStructureReference(ChunkPos pos, int range) {
|
||||
int prestepRange = range + StepStructureReference.RANGE;
|
||||
GridList<ChunkSynconizer> referencedChunks = generateStructureStart(pos, prestepRange);
|
||||
System.out.println("generateStructureReference(" + pos.toString() + ", " + range + ")");
|
||||
int centreIndex = referencedChunks.size() / 2;
|
||||
|
||||
for (int ox = -range; ox <= range; ox++) {
|
||||
for (int oy = -range; oy <= range; oy++) {
|
||||
int targetIndex = referencedChunks.offsetOf(centreIndex, ox, oy);
|
||||
ChunkSynconizer target = referencedChunks.get(targetIndex);
|
||||
if (!target.hasCompletedStep(Steps.StructureReference)) {
|
||||
boolean owned = target.tryClaimOwnerLock();
|
||||
if (owned) {
|
||||
try {
|
||||
GridList<ChunkSynconizer> reference = referencedChunks.subGrid(targetIndex,
|
||||
StepStructureReference.RANGE);
|
||||
ArrayList<ChunkAccess> referenceAccess = new ArrayList<ChunkAccess>(reference.size());
|
||||
for (ChunkSynconizer ref : reference) {
|
||||
referenceAccess.add(ref.chunk);
|
||||
}
|
||||
StepStructureReference.generate(level, generator, referenceAccess, target.chunk);
|
||||
target.set(Steps.StructureReference);
|
||||
} finally {
|
||||
target.releaseOwnerLock();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//System.out.println(
|
||||
// "EXIT: generateStructureReference(" + pos.toString() + ", " + range + ") -> " + referencedChunks);
|
||||
return referencedChunks;
|
||||
}
|
||||
|
||||
public GridList<ChunkSynconizer> generateBiomes(ChunkPos pos, int range) {
|
||||
int prestepRange = range + 1;
|
||||
GridList<ChunkSynconizer> referencedChunks = generateStructureReference(pos, prestepRange);
|
||||
System.out.println("generateBiomes("+pos.toString()+", "+range+")");
|
||||
int centreIndex = referencedChunks.size() / 2;
|
||||
|
||||
for (int ox = -range; ox <= range; ox++) {
|
||||
for (int oy = -range; oy <= range; oy++) {
|
||||
int targetIndex = referencedChunks.offsetOf(centreIndex, ox, oy);
|
||||
ChunkSynconizer target = referencedChunks.get(targetIndex);
|
||||
if (!target.hasCompletedStep(Steps.Biomes)) {
|
||||
boolean owned = target.tryClaimOwnerLock();
|
||||
if (owned) {
|
||||
try {
|
||||
GridList<ChunkSynconizer> reference = referencedChunks.subGrid(targetIndex,
|
||||
StepBiomes.RANGE);
|
||||
ArrayList<ChunkAccess> referenceAccess = new ArrayList<ChunkAccess>(reference.size());
|
||||
for (ChunkSynconizer ref : reference) {
|
||||
referenceAccess.add(ref.chunk);
|
||||
}
|
||||
target.set(StepBiomes.generate(level, generator, referenceAccess, target.chunk, executors), Steps.Biomes);
|
||||
} finally {
|
||||
target.releaseOwnerLock();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//System.out.println("EXIT: generateBiomes("+pos.toString()+", "+range+") -> "+referencedChunks);
|
||||
return referencedChunks;
|
||||
}
|
||||
|
||||
public GridList<ChunkSynconizer> generateNoise(ChunkPos pos, int range) {
|
||||
// System.out.println("generateNoise("+pos.toString()+", "+range+")");
|
||||
int prestepRange = range + 1;
|
||||
GridList<ChunkSynconizer> referencedChunks = generateBiomes(pos, prestepRange);
|
||||
int centreIndex = referencedChunks.size() / 2;
|
||||
|
||||
for (int ox = -range; ox <= range; ox++) {
|
||||
for (int oy = -range; oy <= range; oy++) {
|
||||
int targetIndex = referencedChunks.offsetOf(centreIndex, ox, oy);
|
||||
ChunkSynconizer target = referencedChunks.get(targetIndex);
|
||||
if (!target.hasCompletedStep(Steps.Noise)) {
|
||||
boolean owned = target.tryClaimOwnerLock();
|
||||
if (owned) {
|
||||
try {
|
||||
GridList<ChunkSynconizer> reference = referencedChunks.subGrid(targetIndex,
|
||||
StepNoise.RANGE);
|
||||
ArrayList<ChunkAccess> referenceAccess = new ArrayList<ChunkAccess>(reference.size());
|
||||
for (ChunkSynconizer ref : reference) {
|
||||
referenceAccess.add(ref.chunk);
|
||||
}
|
||||
target.set(StepNoise.generate(level, generator, referenceAccess, target.chunk, executors),
|
||||
Steps.Noise);
|
||||
} finally {
|
||||
target.releaseOwnerLock();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//System.out.println("EXIT: generateNoise(" + pos.toString() + ", " + range + ") -> " + referencedChunks);
|
||||
return referencedChunks;
|
||||
}
|
||||
|
||||
public GridList<ChunkSynconizer> generateSurface(ChunkPos pos, int range) {
|
||||
int prestepRange = range + 1;
|
||||
GridList<ChunkSynconizer> referencedChunks = generateNoise(pos, prestepRange);
|
||||
int centreIndex = referencedChunks.size() / 2;
|
||||
|
||||
for (int ox = -range; ox <= range; ox++) {
|
||||
for (int oy = -range; oy <= range; oy++) {
|
||||
int targetIndex = referencedChunks.offsetOf(centreIndex, ox, oy);
|
||||
ChunkSynconizer target = referencedChunks.get(targetIndex);
|
||||
if (!target.hasCompletedStep(Steps.Surface)) {
|
||||
boolean owned = target.tryClaimOwnerLock();
|
||||
if (owned) {
|
||||
try {
|
||||
GridList<ChunkSynconizer> reference = referencedChunks.subGrid(targetIndex,
|
||||
StepSurface.RANGE);
|
||||
ArrayList<ChunkAccess> referenceAccess = new ArrayList<ChunkAccess>(reference.size());
|
||||
for (ChunkSynconizer ref : reference) {
|
||||
referenceAccess.add(ref.chunk);
|
||||
}
|
||||
|
||||
target.set(StepSurface.generate(level, generator, referenceAccess, target.chunk),
|
||||
Steps.Surface);
|
||||
} finally {
|
||||
target.releaseOwnerLock();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//System.out.println("EXIT: generateNoise(" + pos.toString() + ", " + range + ") -> " + referencedChunks);
|
||||
return referencedChunks;
|
||||
}
|
||||
|
||||
|
||||
public GridList<ChunkSynconizer> generateCarvers(ChunkPos pos, int range) {
|
||||
int prestepRange = range + 1;
|
||||
GridList<ChunkSynconizer> referencedChunks = generateSurface(pos, prestepRange);
|
||||
int centreIndex = referencedChunks.size() / 2;
|
||||
|
||||
for (int ox = -range; ox <= range; ox++) {
|
||||
for (int oy = -range; oy <= range; oy++) {
|
||||
int targetIndex = referencedChunks.offsetOf(centreIndex, ox, oy);
|
||||
ChunkSynconizer target = referencedChunks.get(targetIndex);
|
||||
if (!target.hasCompletedStep(Steps.Carvers)) {
|
||||
boolean owned = target.tryClaimOwnerLock();
|
||||
if (owned) {
|
||||
try {
|
||||
GridList<ChunkSynconizer> reference = referencedChunks.subGrid(targetIndex,
|
||||
StepCarvers.RANGE);
|
||||
ArrayList<ChunkAccess> referenceAccess = new ArrayList<ChunkAccess>(reference.size());
|
||||
for (ChunkSynconizer ref : reference) {
|
||||
referenceAccess.add(ref.chunk);
|
||||
}
|
||||
target.set(StepCarvers.generate(level, generator, referenceAccess, target.chunk),
|
||||
Steps.Carvers);
|
||||
} finally {
|
||||
target.releaseOwnerLock();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//System.out.println("EXIT: generateNoise(" + pos.toString() + ", " + range + ") -> " + referencedChunks);
|
||||
return referencedChunks;
|
||||
}
|
||||
|
||||
|
||||
public GridList<ChunkSynconizer> generateFeatures(ChunkPos pos, int range) {
|
||||
int prestepRange = range + 1;
|
||||
GridList<ChunkSynconizer> referencedChunks = generateCarvers(pos, prestepRange);
|
||||
int centreIndex = referencedChunks.size() / 2;
|
||||
|
||||
for (int ox = -range; ox <= range; ox++) {
|
||||
for (int oy = -range; oy <= range; oy++) {
|
||||
int targetIndex = referencedChunks.offsetOf(centreIndex, ox, oy);
|
||||
ChunkSynconizer target = referencedChunks.get(targetIndex);
|
||||
if (!target.hasCompletedStep(Steps.Features)) {
|
||||
boolean owned = target.tryClaimOwnerLock();
|
||||
if (owned) {
|
||||
try {
|
||||
GridList<ChunkSynconizer> reference = referencedChunks.subGrid(targetIndex,
|
||||
StepFeatures.RANGE);
|
||||
ArrayList<ChunkAccess> referenceAccess = new ArrayList<ChunkAccess>(reference.size());
|
||||
for (ChunkSynconizer ref : reference) {
|
||||
referenceAccess.add(ref.chunk);
|
||||
}
|
||||
target.set(StepFeatures.generate(level, generator, lightEngine, referenceAccess, target.chunk),
|
||||
Steps.Features);
|
||||
} finally {
|
||||
target.releaseOwnerLock();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//System.out.println("EXIT: generateNoise(" + pos.toString() + ", " + range + ") -> " + referencedChunks);
|
||||
return referencedChunks;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
enum Steps {
|
||||
Empty, StructureStart, StructureReference, Biomes, Noise, Surface, Carvers, LiquidCarvers, Features, Light,
|
||||
}
|
||||
|
||||
public static class StepStructureStart {
|
||||
public static final ChunkStatus STATUS = ChunkStatus.STRUCTURE_STARTS;
|
||||
public static final int RANGE = STATUS.getRange();
|
||||
public static final EnumSet<Heightmap.Types> HEIGHTMAP_TYPES = STATUS.heightmapsAfter();
|
||||
static boolean doGenerateFeatures = true;
|
||||
|
||||
public final static void onLevelLoad(WorldGenSettings genSettings) {
|
||||
doGenerateFeatures = genSettings.generateFeatures();
|
||||
}
|
||||
|
||||
public final static ChunkAccess generate(ServerLevel level, ChunkGenerator generator,
|
||||
StructureManager structures, ChunkAccess chunk) {
|
||||
|
||||
if (doGenerateFeatures) {
|
||||
// Should be thread safe
|
||||
generator.createStructures(level.registryAccess(), level.structureFeatureManager(), chunk, structures,
|
||||
level.getSeed());
|
||||
}
|
||||
((ProtoChunk) chunk).setStatus(STATUS);
|
||||
level.onStructureStartsAvailable(chunk);
|
||||
return chunk;
|
||||
}
|
||||
|
||||
static ChunkAccess load(ServerLevel level, ChunkAccess chunk) {
|
||||
((ProtoChunk) chunk).setStatus(STATUS);
|
||||
level.onStructureStartsAvailable(chunk);
|
||||
return chunk;
|
||||
}
|
||||
}
|
||||
|
||||
public static class StepStructureReference {
|
||||
public static final ChunkStatus STATUS = ChunkStatus.STRUCTURE_REFERENCES;
|
||||
public static final int RANGE = STATUS.getRange();
|
||||
public static final EnumSet<Heightmap.Types> HEIGHTMAP_TYPES = STATUS.heightmapsAfter();
|
||||
|
||||
public static final void generate(ServerLevel level, ChunkGenerator generator, List<ChunkAccess> chunkList,
|
||||
ChunkAccess chunk) {
|
||||
WorldGenRegion worldGenRegion = new WorldGenRegion(level, chunkList, STATUS, -1);
|
||||
// Note: Not certain StructureFeatureManager.forWorldGenRegion(...) is thread
|
||||
// safe
|
||||
generator.createReferences((WorldGenLevel) worldGenRegion,
|
||||
level.structureFeatureManager().forWorldGenRegion(worldGenRegion), chunk);
|
||||
((ProtoChunk) chunk).setStatus(STATUS);
|
||||
}
|
||||
|
||||
static ChunkAccess load(ChunkAccess chunk) {
|
||||
((ProtoChunk) chunk).setStatus(STATUS);
|
||||
return chunk;
|
||||
}
|
||||
}
|
||||
|
||||
public static class StepBiomes {
|
||||
public static final ChunkStatus STATUS = ChunkStatus.BIOMES;
|
||||
public static final int RANGE = STATUS.getRange();
|
||||
public static final EnumSet<Heightmap.Types> HEIGHTMAP_TYPES = STATUS.heightmapsAfter();
|
||||
public static Registry<Biome> biomeRegistry;
|
||||
|
||||
public final static void onLevelLoad(RegistryAccess registry) {
|
||||
biomeRegistry = registry.registryOrThrow(Registry.BIOME_REGISTRY);
|
||||
}
|
||||
|
||||
public static final ChunkAccess generate(ServerLevel level, ChunkGenerator generator,
|
||||
List<ChunkAccess> chunkList, ChunkAccess chunk, Executor worker) {
|
||||
WorldGenRegion worldGenRegion = new WorldGenRegion(level, chunkList, STATUS, -1);
|
||||
chunk = generator.createBiomes(biomeRegistry, worker, Blender.of(worldGenRegion),
|
||||
level.structureFeatureManager().forWorldGenRegion(worldGenRegion), chunk).join();
|
||||
((ProtoChunk) chunk).setStatus(STATUS);
|
||||
return chunk;
|
||||
}
|
||||
|
||||
static ChunkAccess load(ChunkAccess chunk) {
|
||||
((ProtoChunk) chunk).setStatus(STATUS);
|
||||
return chunk;
|
||||
}
|
||||
}
|
||||
|
||||
public static class StepNoise {
|
||||
public static final ChunkStatus STATUS = ChunkStatus.NOISE;
|
||||
public static final int RANGE = STATUS.getRange();
|
||||
public static final EnumSet<Heightmap.Types> HEIGHTMAP_TYPES = STATUS.heightmapsAfter();
|
||||
|
||||
public static final ChunkAccess generate(ServerLevel level, ChunkGenerator generator,
|
||||
List<ChunkAccess> chunkList, ChunkAccess chunk, Executor worker) {
|
||||
WorldGenRegion worldGenRegion = new WorldGenRegion(level, chunkList, STATUS, 0);
|
||||
chunk = generator.fillFromNoise(worker, Blender.of(worldGenRegion),
|
||||
level.structureFeatureManager().forWorldGenRegion(worldGenRegion), chunk).join();
|
||||
((ProtoChunk) chunk).setStatus(STATUS);
|
||||
return chunk;
|
||||
}
|
||||
|
||||
static ChunkAccess load(ChunkAccess chunk) {
|
||||
((ProtoChunk) chunk).setStatus(STATUS);
|
||||
return chunk;
|
||||
}
|
||||
}
|
||||
|
||||
public static class StepSurface {
|
||||
public static final ChunkStatus STATUS = ChunkStatus.SURFACE;
|
||||
public static final int RANGE = STATUS.getRange();
|
||||
public static final EnumSet<Heightmap.Types> HEIGHTMAP_TYPES = STATUS.heightmapsAfter();
|
||||
|
||||
public static final ChunkAccess generate(ServerLevel level, ChunkGenerator generator,
|
||||
List<ChunkAccess> chunkList, ChunkAccess chunk) {
|
||||
WorldGenRegion worldGenRegion = new WorldGenRegion(level, chunkList, STATUS, 0);
|
||||
generator.buildSurface(worldGenRegion, level.structureFeatureManager().forWorldGenRegion(worldGenRegion),
|
||||
chunk);
|
||||
((ProtoChunk) chunk).setStatus(STATUS);
|
||||
return chunk;
|
||||
}
|
||||
|
||||
static ChunkAccess load(ChunkAccess chunk) {
|
||||
((ProtoChunk) chunk).setStatus(STATUS);
|
||||
return chunk;
|
||||
}
|
||||
}
|
||||
|
||||
public static class StepCarvers {
|
||||
public static final ChunkStatus STATUS = ChunkStatus.CARVERS;
|
||||
public static final int RANGE = STATUS.getRange();
|
||||
public static final EnumSet<Heightmap.Types> HEIGHTMAP_TYPES = STATUS.heightmapsAfter();
|
||||
|
||||
public static final ChunkAccess generate(ServerLevel level, ChunkGenerator generator,
|
||||
List<ChunkAccess> chunkList, ChunkAccess chunk) {
|
||||
WorldGenRegion worldGenRegion = new WorldGenRegion(level, chunkList, STATUS, 0);
|
||||
Blender.addAroundOldChunksCarvingMaskFilter((WorldGenLevel) worldGenRegion, (ProtoChunk) chunk);
|
||||
generator.applyCarvers(worldGenRegion, level.getSeed(), level.getBiomeManager(),
|
||||
level.structureFeatureManager().forWorldGenRegion(worldGenRegion), chunk,
|
||||
GenerationStep.Carving.AIR);
|
||||
((ProtoChunk) chunk).setStatus(STATUS);
|
||||
return chunk;
|
||||
}
|
||||
|
||||
static ChunkAccess load(ChunkAccess chunk) {
|
||||
((ProtoChunk) chunk).setStatus(STATUS);
|
||||
return chunk;
|
||||
}
|
||||
}
|
||||
|
||||
public static class StepLiquidCarvers {
|
||||
public static final ChunkStatus STATUS = ChunkStatus.LIQUID_CARVERS;
|
||||
public static final int RANGE = STATUS.getRange();
|
||||
public static final EnumSet<Heightmap.Types> HEIGHTMAP_TYPES = STATUS.heightmapsAfter();
|
||||
|
||||
public static final ChunkAccess generate(ServerLevel level, ChunkGenerator generator,
|
||||
List<ChunkAccess> chunkList, ChunkAccess chunk, Executor worker) {
|
||||
// FIXME: I think the decompiler failed on this one. Find the actual body and
|
||||
// put it here.
|
||||
((ProtoChunk) chunk).setStatus(STATUS);
|
||||
return chunk;
|
||||
}
|
||||
|
||||
static ChunkAccess load(ChunkAccess chunk) {
|
||||
((ProtoChunk) chunk).setStatus(STATUS);
|
||||
return chunk;
|
||||
}
|
||||
}
|
||||
|
||||
public static class StepFeatures {
|
||||
public static final ChunkStatus STATUS = ChunkStatus.FEATURES;
|
||||
public static final int RANGE = STATUS.getRange();
|
||||
public static final EnumSet<Heightmap.Types> HEIGHTMAP_TYPES = STATUS.heightmapsAfter();
|
||||
|
||||
public static final ChunkAccess generate(ServerLevel level, ChunkGenerator generator,
|
||||
ThreadedLevelLightEngine lightEngine, List<ChunkAccess> chunkList, ChunkAccess chunk) {
|
||||
ProtoChunk protoChunk = (ProtoChunk) chunk;
|
||||
protoChunk.setLightEngine((LevelLightEngine) lightEngine);
|
||||
|
||||
Heightmap.primeHeightmaps(chunk,
|
||||
EnumSet.of(Heightmap.Types.MOTION_BLOCKING, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES,
|
||||
Heightmap.Types.OCEAN_FLOOR, Heightmap.Types.WORLD_SURFACE));
|
||||
|
||||
// This could be problematic. May need to lock the 8 surrounding chunks then.
|
||||
WorldGenRegion worldGenRegion = new WorldGenRegion(level, chunkList, STATUS, 1);
|
||||
|
||||
generator.applyBiomeDecoration((WorldGenLevel) worldGenRegion, chunk,
|
||||
level.structureFeatureManager().forWorldGenRegion(worldGenRegion));
|
||||
Blender.generateBorderTicks(worldGenRegion, chunk);
|
||||
|
||||
protoChunk.setStatus(STATUS);
|
||||
return chunk;
|
||||
}
|
||||
|
||||
static ChunkAccess load(ChunkAccess chunk) {
|
||||
((ProtoChunk) chunk).setStatus(STATUS);
|
||||
return chunk;
|
||||
}
|
||||
}
|
||||
|
||||
public static class StepLight {
|
||||
public static final ChunkStatus STATUS = ChunkStatus.LIGHT;
|
||||
public static final int RANGE = STATUS.getRange();
|
||||
public static final EnumSet<Heightmap.Types> HEIGHTMAP_TYPES = STATUS.heightmapsAfter();
|
||||
private static ThreadedLevelLightEngine lightEngine;
|
||||
|
||||
public final static void onLevelLoad(ThreadedLevelLightEngine engine) {
|
||||
lightEngine = engine;
|
||||
}
|
||||
|
||||
public static final ChunkAccess generate(ChunkAccess chunk) {
|
||||
((ProtoChunk) chunk).setStatus(STATUS);
|
||||
return lightEngine.lightChunk(chunk, chunk.isLightCorrect()).join();
|
||||
}
|
||||
|
||||
public static final ChunkAccess load(ChunkAccess chunk) {
|
||||
((ProtoChunk) chunk).setStatus(STATUS);
|
||||
return lightEngine.lightChunk(chunk, chunk.isLightCorrect()).join();
|
||||
}
|
||||
}
|
||||
|
||||
// The following may not be needed
|
||||
/*
|
||||
* public static class Spawn implements SimpleGen {
|
||||
*
|
||||
* @Override public EnumSet<Types> getHeightmapTypes() { return POST_FEATURES; }
|
||||
*
|
||||
* @Override public int getDependencyRange() { return 0; }
|
||||
*
|
||||
* @Override public final void doSimpleWork(ChunkStatus targetStatus,
|
||||
* ServerLevel level, ChunkGenerator generator, List<ChunkAccess> chunkList,
|
||||
* ChunkAccess chunk) { if (!chunk.isUpgrading())
|
||||
* generator.spawnOriginalMobs(new WorldGenRegion(level, chunkList,
|
||||
* targetStatus, -1)); } } public static class Heightmaps implements SimpleGen {
|
||||
*
|
||||
* @Override public EnumSet<Types> getHeightmapTypes() { return POST_FEATURES; }
|
||||
*
|
||||
* @Override public int getDependencyRange() { return 0; }
|
||||
*
|
||||
* @Override public final void doSimpleWork(ChunkStatus targetStatus,
|
||||
* ServerLevel level, ChunkGenerator generator, List<ChunkAccess> chunkList,
|
||||
* ChunkAccess chunk) { // Apearently nothing again??? Decompiler Error? } }
|
||||
*
|
||||
* public static class Full implements Gen {
|
||||
*
|
||||
* @Override public EnumSet<Types> getHeightmapTypes() { return POST_FEATURES; }
|
||||
*
|
||||
* @Override public int getDependencyRange() { return 0; }
|
||||
*
|
||||
* @Override public final ChunkAccess doWork(ChunkStatus targetStatus, Executor
|
||||
* worker, ServerLevel level, ChunkGenerator generator, StructureManager
|
||||
* structures, ThreadedLevelLightEngine lightEngine, Mutator function,
|
||||
* List<ChunkAccess> chunkList, ChunkAccess chunk, boolean alwaysRegenerate) {
|
||||
* return function.call(chunk); }
|
||||
*
|
||||
* @Override public final ChunkAccess load(ChunkStatus targetStatus, ServerLevel
|
||||
* level, StructureManager structures, ThreadedLevelLightEngine lightEngine,
|
||||
* Mutator function, ChunkAccess chunk) { return function.call(chunk); } }
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
}
|
||||
+45
-1
@@ -4,14 +4,58 @@ import com.seibel.lod.core.builders.lodBuilding.LodBuilder;
|
||||
import com.seibel.lod.core.builders.lodBuilding.LodBuilderConfig;
|
||||
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
|
||||
import com.seibel.lod.core.objects.lod.LodDimension;
|
||||
import com.seibel.lod.core.util.LodThreadFactory;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractWorldGeneratorWrapper;
|
||||
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.concurrent.atomic.AtomicReferenceArray;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.IntFunction;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.mojang.datafixers.util.Either;
|
||||
import com.seibel.lod.common.wrappers.chunk.ChunkWrapper;
|
||||
import com.seibel.lod.common.wrappers.world.WorldWrapper;
|
||||
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.WorldGenRegion;
|
||||
import net.minecraft.server.level.ChunkHolder.ChunkLoadingFailure;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.LevelHeightAccessor;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.chunk.*;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus.ChunkType;
|
||||
import net.minecraft.server.level.ThreadedLevelLightEngine;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.core.Registry;
|
||||
/* */ import net.minecraft.server.level.ChunkHolder;
|
||||
/* */ import net.minecraft.server.level.ServerLevel;
|
||||
/* */ import net.minecraft.server.level.ThreadedLevelLightEngine;
|
||||
/* */ import net.minecraft.server.level.WorldGenRegion;
|
||||
/* */ import net.minecraft.util.profiling.jfr.JvmProfiler;
|
||||
/* */ import net.minecraft.util.profiling.jfr.callback.ProfiledDuration;
|
||||
/* */ import net.minecraft.world.level.WorldGenLevel;
|
||||
/* */ import net.minecraft.world.level.levelgen.BelowZeroRetrogen;
|
||||
/* */ import net.minecraft.world.level.levelgen.GenerationStep;
|
||||
/* */ import net.minecraft.world.level.levelgen.Heightmap;
|
||||
import net.minecraft.world.level.levelgen.Heightmap.Types;
|
||||
/* */ import net.minecraft.world.level.levelgen.blending.Blender;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
|
||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||
|
||||
/**
|
||||
* @author James Seibel
|
||||
@@ -136,4 +180,4 @@ public class WorldGeneratorWrapper extends AbstractWorldGeneratorWrapper
|
||||
|
||||
Otherwise, if snow/trees aren't necessary SURFACE is the next fastest (although not by much)
|
||||
*/
|
||||
}
|
||||
}
|
||||
+1
-1
Submodule core updated: 4229ed75ae...8577363438
+1704
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user