Updated generator
This commit is contained in:
@@ -170,8 +170,6 @@ public class Config extends ConfigGui
|
||||
@Category("client.worldGenerator")
|
||||
@Entry
|
||||
public static BlocksToAvoid blocksToAvoid = IWorldGenerator.BLOCKS_TO_AVOID_DEFAULT;
|
||||
|
||||
// public static boolean useExperimentalPreGenLoading = false;
|
||||
}
|
||||
|
||||
public static class Advanced
|
||||
|
||||
@@ -19,12 +19,14 @@
|
||||
|
||||
package com.seibel.lod.common.wrappers;
|
||||
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.ExperimentalGenerator;
|
||||
import com.seibel.lod.core.builders.lodBuilding.LodBuilder;
|
||||
import com.seibel.lod.core.objects.lod.LodDimension;
|
||||
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;
|
||||
@@ -36,32 +38,27 @@ import com.seibel.lod.common.wrappers.worldGeneration.WorldGeneratorWrapper;
|
||||
* @author James Seibel
|
||||
* @version 11-20-2021
|
||||
*/
|
||||
public class WrapperFactory implements IWrapperFactory
|
||||
{
|
||||
public class WrapperFactory implements IWrapperFactory {
|
||||
public static final WrapperFactory INSTANCE = new WrapperFactory();
|
||||
|
||||
|
||||
@Override
|
||||
public AbstractBlockPosWrapper createBlockPos()
|
||||
{
|
||||
public AbstractBlockPosWrapper createBlockPos() {
|
||||
return new BlockPosWrapper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractBlockPosWrapper createBlockPos(int x, int y, int z)
|
||||
{
|
||||
return new BlockPosWrapper(x,y,z);
|
||||
public AbstractBlockPosWrapper createBlockPos(int x, int y, int z) {
|
||||
return new BlockPosWrapper(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractChunkPosWrapper createChunkPos()
|
||||
{
|
||||
public AbstractChunkPosWrapper createChunkPos() {
|
||||
return new ChunkPosWrapper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractChunkPosWrapper createChunkPos(long xAndZPositionCombined)
|
||||
{
|
||||
public AbstractChunkPosWrapper createChunkPos(long xAndZPositionCombined) {
|
||||
int x = (int) (xAndZPositionCombined & Integer.MAX_VALUE);
|
||||
int z = (int) (xAndZPositionCombined >> Long.SIZE / 2) & Integer.MAX_VALUE;
|
||||
|
||||
@@ -69,26 +66,27 @@ public class WrapperFactory implements IWrapperFactory
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractChunkPosWrapper createChunkPos(int x, int z)
|
||||
{
|
||||
public AbstractChunkPosWrapper createChunkPos(int x, int z) {
|
||||
return new ChunkPosWrapper(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractChunkPosWrapper createChunkPos(AbstractChunkPosWrapper newChunkPos)
|
||||
{
|
||||
public AbstractChunkPosWrapper createChunkPos(AbstractChunkPosWrapper newChunkPos) {
|
||||
return new ChunkPosWrapper(newChunkPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractChunkPosWrapper createChunkPos(AbstractBlockPosWrapper blockPos)
|
||||
{
|
||||
public AbstractChunkPosWrapper createChunkPos(AbstractBlockPosWrapper blockPos) {
|
||||
return new ChunkPosWrapper(blockPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractWorldGeneratorWrapper createWorldGenerator(LodBuilder newLodBuilder, LodDimension newLodDimension, IWorldWrapper worldWrapper)
|
||||
{
|
||||
public AbstractWorldGeneratorWrapper createWorldGenerator(LodBuilder newLodBuilder, LodDimension newLodDimension, IWorldWrapper worldWrapper) {
|
||||
return new WorldGeneratorWrapper(newLodBuilder, newLodDimension, worldWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractExperimentalWorldGeneratorWrapper createExperimentalWorldGenerator(LodBuilder newLodBuilder, LodDimension newLodDimension, IWorldWrapper worldWrapper) {
|
||||
return new ExperimentalGenerator(newLodBuilder, newLodDimension, worldWrapper);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-4
@@ -4,6 +4,7 @@ import java.awt.*;
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.mojang.blaze3d.platform.NativeImage;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.seibel.lod.common.wrappers.misc.LightMapWrapper;
|
||||
import com.seibel.lod.core.handlers.IReflectionHandler;
|
||||
import com.seibel.lod.core.handlers.ReflectionHandler;
|
||||
@@ -44,8 +45,6 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||
{
|
||||
public static final MinecraftRenderWrapper INSTANCE = new MinecraftRenderWrapper();
|
||||
|
||||
private static final MinecraftWrapper MC_WRAPPER = MinecraftWrapper.INSTANCE;
|
||||
|
||||
private static final Minecraft MC = Minecraft.getInstance();
|
||||
private static final GameRenderer GAME_RENDERER = MC.gameRenderer;
|
||||
|
||||
@@ -96,8 +95,7 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||
|
||||
@Override
|
||||
public Color getFogColor() {
|
||||
float[] colorValues = new float[4];
|
||||
GL20.glGetFloatv(GL20.GL_FOG_COLOR, colorValues);
|
||||
float[] colorValues = RenderSystem.getShaderFogColor();
|
||||
return new Color(colorValues[0], colorValues[1], colorValues[2], colorValues[3]);
|
||||
}
|
||||
|
||||
|
||||
+175
@@ -0,0 +1,175 @@
|
||||
package com.seibel.lod.common.wrappers.worldGeneration;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.seibel.lod.common.wrappers.world.WorldWrapper;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.WorldGenerationStep.GenerationEvent;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.WorldGenerationStep.Steps;
|
||||
import com.seibel.lod.core.builders.lodBuilding.LodBuilder;
|
||||
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
|
||||
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.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);
|
||||
public WorldGenerationStep generationGroup;
|
||||
public LodDimension targetLodDim;
|
||||
public static final int generationGroupSize = 4;
|
||||
public static final int generationGroupSizeFar = 0;
|
||||
public static int numberOfGenerationPoints = CONFIG.client().advanced().threading().getNumberOfWorldGenerationThreads()*2;
|
||||
|
||||
private int estimatedSampleNeeded = 128;
|
||||
|
||||
private LinkedList<GenerationEvent> events = new LinkedList<GenerationEvent>();
|
||||
|
||||
public ExperimentalGenerator(LodBuilder newLodBuilder, LodDimension newLodDimension, IWorldWrapper worldWrapper) {
|
||||
super(newLodBuilder, newLodDimension, worldWrapper);
|
||||
System.out.println("================ExperimentalGenerator INIT=============");
|
||||
generationGroup = new WorldGenerationStep(((WorldWrapper) worldWrapper).getServerWorld(), newLodBuilder,
|
||||
newLodDimension);
|
||||
}
|
||||
|
||||
private boolean checkIfPositionIsValid(int chunkX, int chunkZ, int range) {
|
||||
for (GenerationEvent event : events) {
|
||||
if (event.tooClose(chunkX, chunkZ, range)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queueGenerationRequests(LodDimension lodDim, LodBuilder lodBuilder) {
|
||||
DistanceGenerationMode mode = CONFIG.client().worldGenerator().getDistanceGenerationMode();
|
||||
numberOfGenerationPoints = CONFIG.client().advanced().threading().getNumberOfWorldGenerationThreads();
|
||||
|
||||
if (mode == DistanceGenerationMode.NONE || !MC.hasSinglePlayerServer())
|
||||
return;
|
||||
|
||||
// Update all current out standing jobs
|
||||
Iterator<GenerationEvent> iter = events.iterator();
|
||||
while (iter.hasNext()) {
|
||||
GenerationEvent event = iter.next();
|
||||
if (event.isCompleted()) {
|
||||
event.join();
|
||||
iter.remove();
|
||||
} else if (event.hasTimeout(5, TimeUnit.SECONDS)) {
|
||||
System.err.println(event.id+": Timed out and terminated!");
|
||||
event.terminate();
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
|
||||
// If we still all jobs running, return.
|
||||
if (events.size() >= numberOfGenerationPoints)
|
||||
return;
|
||||
|
||||
final int targetToGenerate = numberOfGenerationPoints - events.size();
|
||||
int toGenerate = targetToGenerate;
|
||||
int positionGoneThough = 0;
|
||||
|
||||
// round the player's block position down to the nearest chunk BlockPos
|
||||
int playerPosX = MC.getPlayerBlockPos().getX();
|
||||
int playerPosZ = MC.getPlayerBlockPos().getZ();
|
||||
|
||||
// TODO: Make it so that lodDim allows feeding in a function to fast halt if
|
||||
// position generation is completed.
|
||||
PosToGenerateContainer posToGenerate = lodDim.getPosToGenerate(estimatedSampleNeeded, playerPosX, playerPosZ);
|
||||
|
||||
// Find the max number of iterations we need to go though.
|
||||
// We are checking one FarPos, and one NearPos per iterations. This ensure we
|
||||
// aren't just
|
||||
// always picking one or the other.
|
||||
int nearCount = posToGenerate.getNumberOfNearPos();
|
||||
int farCount = posToGenerate.getNumberOfFarPos();
|
||||
int maxIteration = Math.max(nearCount, farCount);
|
||||
|
||||
for (int i = 0; i < maxIteration; i++) {
|
||||
|
||||
// We have nearPos to go though
|
||||
if (i < nearCount && posToGenerate.getNthDetail(i, true) != 0) {
|
||||
positionGoneThough++;
|
||||
// TODO: Add comment here on why theres a '-1'.
|
||||
// Not sure what's happening here. This is copied from previous codes.
|
||||
byte detailLevel = (byte) (posToGenerate.getNthDetail(i, true) - 1);
|
||||
int chunkX = LevelPosUtil.getChunkPos(detailLevel, posToGenerate.getNthPosX(i, true));
|
||||
int chunkZ = LevelPosUtil.getChunkPos(detailLevel, posToGenerate.getNthPosZ(i, true));
|
||||
if (checkIfPositionIsValid(chunkX, chunkZ, generationGroupSize)) {
|
||||
ChunkPos chunkPos = new ChunkPos(chunkX, chunkZ);
|
||||
events.add(new GenerationEvent(chunkPos, generationGroupSize, generationGroup, Steps.Surface));
|
||||
toGenerate--;
|
||||
}
|
||||
}
|
||||
//if (toGenerate <= 0)
|
||||
// break;
|
||||
|
||||
// We have farPos to go though
|
||||
if (i < farCount && posToGenerate.getNthDetail(i, false) != 0) {
|
||||
positionGoneThough++;
|
||||
// TODO: Add comment here on why theres a '-1'.
|
||||
// Not sure what's happening here. This is copied from previous codes.
|
||||
byte detailLevel = (byte) (posToGenerate.getNthDetail(i, false) - 1);
|
||||
int chunkX = LevelPosUtil.getChunkPos(detailLevel, posToGenerate.getNthPosX(i, false));
|
||||
int chunkZ = LevelPosUtil.getChunkPos(detailLevel, posToGenerate.getNthPosZ(i, false));
|
||||
if (checkIfPositionIsValid(chunkX, chunkZ, generationGroupSizeFar)) {
|
||||
ChunkPos chunkPos = new ChunkPos(chunkX, chunkZ);
|
||||
events.add(new GenerationEvent(chunkPos, generationGroupSizeFar, generationGroup, Steps.Surface));
|
||||
toGenerate--;
|
||||
}
|
||||
}
|
||||
if (toGenerate <= 0)
|
||||
break;
|
||||
|
||||
}
|
||||
if (targetToGenerate != toGenerate) {
|
||||
if (toGenerate <= 0) {
|
||||
System.out.println(
|
||||
"WorldGenerator: Sampled " + posToGenerate.getNumberOfPos() + " out of " + estimatedSampleNeeded
|
||||
+ " points, started all targeted " + targetToGenerate + " generations.");
|
||||
} else {
|
||||
System.out.println("WorldGenerator: Sampled " + posToGenerate.getNumberOfPos() + " out of "
|
||||
+ estimatedSampleNeeded + " points, started " + (targetToGenerate - toGenerate)
|
||||
+ " out of targeted " + targetToGenerate + " generations.");
|
||||
}
|
||||
}
|
||||
|
||||
if (toGenerate > 0 && estimatedSampleNeeded <= posToGenerate.getNumberOfPos()) {
|
||||
// We failed to generate enough points from the samples.
|
||||
// Let's increase the estimatedSampleNeeded.
|
||||
estimatedSampleNeeded *= 1.3;
|
||||
// Ensure wee don't go to basically infinity
|
||||
if (estimatedSampleNeeded > 32768)
|
||||
estimatedSampleNeeded = 32768;
|
||||
System.out.println("WorldGenerator: Increasing estimatedSampleNeeeded to " + estimatedSampleNeeded);
|
||||
|
||||
} else if (toGenerate <= 0 && positionGoneThough * 1.5 < posToGenerate.getNumberOfPos()) {
|
||||
// We haven't gone though half of them and it's already enough.
|
||||
// Let's shink the estimatedSampleNeeded.
|
||||
estimatedSampleNeeded /= 1.2;
|
||||
// Ensure we don't go to near zero.
|
||||
if (estimatedSampleNeeded < 4)
|
||||
estimatedSampleNeeded = 4;
|
||||
System.out.println("WorldGenerator: Decreasing estimatedSampleNeeeded to " + estimatedSampleNeeded);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
System.out.println("================ExperimentalGenerator SHUTDOWN=============");
|
||||
generationGroup.executors.shutdownNow();
|
||||
}
|
||||
|
||||
}
|
||||
+902
@@ -0,0 +1,902 @@
|
||||
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.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import com.seibel.lod.common.wrappers.chunk.ChunkWrapper;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.WorldGenerationStep.Steps;
|
||||
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.WorldGenRegion;
|
||||
import net.minecraft.world.entity.ai.village.VillageSiege;
|
||||
import net.minecraft.world.entity.npc.CatSpawner;
|
||||
import net.minecraft.world.entity.npc.WanderingTraderSpawner;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.StructureFeatureManager;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.BiomeManager;
|
||||
import net.minecraft.world.level.chunk.*;
|
||||
import net.minecraft.world.level.dimension.DimensionType;
|
||||
import net.minecraft.world.level.dimension.LevelStem;
|
||||
import net.minecraft.server.level.ThreadedLevelLightEngine;
|
||||
import net.minecraft.core.MappedRegistry;
|
||||
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.NoiseBasedChunkGenerator;
|
||||
import net.minecraft.world.level.levelgen.PatrolSpawner;
|
||||
import net.minecraft.world.level.levelgen.PhantomSpawner;
|
||||
import net.minecraft.world.level.levelgen.WorldGenSettings;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
|
||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||
import net.minecraft.world.level.storage.ServerLevelData;
|
||||
import net.minecraft.world.level.storage.WorldData;
|
||||
|
||||
public class WorldGenerationStep {
|
||||
|
||||
/*
|
||||
public static class ChunkScanner implements ChunkScanAccess {
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> scanChunk(ChunkPos paramChunkPos, StreamTagVisitor paramStreamTagVisitor) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
}*/
|
||||
|
||||
|
||||
public static class GenerationEvent {
|
||||
private static int generationFutureDebugIDs = 0;
|
||||
ChunkPos pos;
|
||||
int range;
|
||||
Future<?> future;
|
||||
long nanotime;
|
||||
int id;
|
||||
Steps target;
|
||||
|
||||
public GenerationEvent(ChunkPos pos, int range, WorldGenerationStep generationGroup, Steps target) {
|
||||
nanotime = System.nanoTime();
|
||||
this.pos = pos;
|
||||
this.range = range;
|
||||
id = generationFutureDebugIDs++;
|
||||
this.target = target;
|
||||
future = generationGroup.executors.submit(() -> {
|
||||
generationGroup.generateLodFromList(this);
|
||||
});
|
||||
}
|
||||
public boolean isCompleted() {
|
||||
return future.isDone();
|
||||
}
|
||||
public boolean hasTimeout(int duration, TimeUnit unit) {
|
||||
long currentTime = System.nanoTime();
|
||||
long delta = currentTime - nanotime;
|
||||
return (delta > TimeUnit.NANOSECONDS.convert(duration, unit));
|
||||
}
|
||||
public void terminate() {
|
||||
future.cancel(true);
|
||||
}
|
||||
public void join() {
|
||||
try {
|
||||
future.get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
public boolean tooClose(int cx, int cz, int cr) {
|
||||
int dist = Math.min(Math.abs(cx - pos.x), Math.abs(cz - pos.z));
|
||||
return dist<range+cr;
|
||||
}
|
||||
public void refreshTimeout() {
|
||||
nanotime = System.nanoTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return id + ":"+ range + "@"+ pos+"("+target+")";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private static <T> T joinAsync(CompletableFuture<T> f) {
|
||||
//while (!f.isDone()) Thread.yield();
|
||||
return f.join();
|
||||
}
|
||||
|
||||
ServerLevel level;
|
||||
ChunkGenerator generator;
|
||||
StructureManager structures;
|
||||
BiomeManager biomeManager;
|
||||
WorldGenSettings worldGenSettings;
|
||||
ThreadedLevelLightEngine lightEngine;
|
||||
LodBuilder lodBuilder;
|
||||
LodDimension lodDim;
|
||||
StructureFeatureManager structureFeatureManager;
|
||||
// StructureCheck structureCheck;
|
||||
Registry<Biome> biomes;
|
||||
RegistryAccess registry;
|
||||
long worldSeed;
|
||||
//public ExecutorService executors = Executors.newWorkStealingPool();
|
||||
public ExecutorService executors = Executors.newCachedThreadPool(new ThreadFactoryBuilder().setNameFormat("Gen-Worker-Thread-%d").build());
|
||||
|
||||
//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;
|
||||
setupStuff();
|
||||
|
||||
StepStructureStart.onLevelLoad(generator, worldGenSettings, registry, structureFeatureManager, structures, worldSeed);
|
||||
StepStructureReference.onLevelLoad(level, generator, structureFeatureManager);
|
||||
StepBiomes.onLevelLoad(level, generator, biomes, structureFeatureManager);
|
||||
StepNoise.onLevelLoad(level, generator, structureFeatureManager);
|
||||
StepSurface.onLevelLoad(level, generator, structureFeatureManager);
|
||||
StepCarvers.onLevelLoad(level, generator, structureFeatureManager, worldSeed, biomeManager);
|
||||
StepFeatures.onLevelLoad(level, generator, structureFeatureManager, lightEngine);
|
||||
StepLight.onLevelLoad(lightEngine);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void setupStuff() {
|
||||
lightEngine = (ThreadedLevelLightEngine) level.getLightEngine();
|
||||
MinecraftServer server = level.getServer();
|
||||
WorldData worldData = server.getWorldData();
|
||||
worldGenSettings = worldData.worldGenSettings();
|
||||
registry = server.registryAccess();
|
||||
biomes = registry.registryOrThrow(Registry.BIOME_REGISTRY);
|
||||
worldSeed = worldGenSettings.seed();
|
||||
long biomeSeed = BiomeManager.obfuscateSeed(worldSeed);
|
||||
// FIXME: broken in 1.17.1
|
||||
// biomeManager = new BiomeManager(level, biomeSeed);
|
||||
structures = server.getStructureManager();
|
||||
// TODO: Get the current level dimension
|
||||
MappedRegistry<LevelStem> mappedRegistry = worldGenSettings.dimensions();
|
||||
LevelStem levelStem = mappedRegistry.get(LevelStem.OVERWORLD);
|
||||
if (levelStem == null) {
|
||||
throw new RuntimeException("There should already be a level.... Right???");
|
||||
} else {
|
||||
generator = levelStem.generator();
|
||||
}
|
||||
structureFeatureManager = new StructureFeatureManager(level, worldGenSettings);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
//System.out.println("========================================\n"+
|
||||
//this.toDetailString() + "\nTOOOOOOOOOOOOO\n"+subGrid.toDetailString()+
|
||||
//"==========================================\n");
|
||||
return subGrid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GridList "+gridSize+"*"+gridSize+"["+size()+"]";
|
||||
}
|
||||
public String toDetailString() {
|
||||
StringBuilder str = new StringBuilder("\n");
|
||||
int i = 0;
|
||||
for (T t : this) {
|
||||
str.append(t.toString());
|
||||
str.append(", ");
|
||||
i++;
|
||||
if (i%gridSize == 0) {
|
||||
str.append("\n");
|
||||
}
|
||||
}
|
||||
return str.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static class ChunkSynconizer {
|
||||
|
||||
private ReentrantLock uniqueOwnerLock = new ReentrantLock();
|
||||
ChunkAccess chunk;
|
||||
Steps completedStep = Steps.Empty;
|
||||
|
||||
public ChunkSynconizer(ChunkPos pos, ServerLevel level) {
|
||||
chunk = new ProtoChunk(pos, UpgradeData.EMPTY, level);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return chunk.getPos().toString();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
ChunkSynconizer oldVal = chunks.putIfAbsent(pos, chunk);
|
||||
if (oldVal != null)
|
||||
return oldVal;
|
||||
return chunk;
|
||||
}
|
||||
|
||||
public void generateLodFromList(GenerationEvent event) {
|
||||
try {
|
||||
System.out.println("Started event: "+event);
|
||||
GridList<ChunkSynconizer> referencedChunks;
|
||||
DistanceGenerationMode generationMode;
|
||||
Runnable lambda = () -> {event.refreshTimeout();};
|
||||
switch (event.target) {
|
||||
case Empty:
|
||||
return;
|
||||
case StructureStart:
|
||||
referencedChunks = generateStructureStart(lambda, event.pos, event.range);
|
||||
generationMode = DistanceGenerationMode.NONE;
|
||||
break;
|
||||
case StructureReference:
|
||||
referencedChunks = generateStructureReference(lambda, event.pos, event.range);
|
||||
generationMode = DistanceGenerationMode.NONE;
|
||||
break;
|
||||
case Biomes:
|
||||
referencedChunks = generateBiomes(lambda, event.pos, event.range);
|
||||
generationMode = DistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT;
|
||||
break;
|
||||
case Noise:
|
||||
referencedChunks = generateNoise(lambda, event.pos, event.range);
|
||||
generationMode = DistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT;
|
||||
break;
|
||||
case Surface:
|
||||
referencedChunks = generateSurface(lambda, event.pos, event.range);
|
||||
generationMode = DistanceGenerationMode.SURFACE;
|
||||
break;
|
||||
case Carvers:
|
||||
referencedChunks = generateCarvers(lambda, event.pos, event.range);
|
||||
generationMode = DistanceGenerationMode.SURFACE;
|
||||
break;
|
||||
case Features:
|
||||
referencedChunks = generateFeatures(lambda, event.pos, event.range);
|
||||
generationMode = DistanceGenerationMode.FEATURES;
|
||||
break;
|
||||
case LiquidCarvers:
|
||||
return;
|
||||
case Light:
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
int centreIndex = referencedChunks.size() / 2;
|
||||
|
||||
for (int ox = -event.range; ox <= event.range; ox++) {
|
||||
for (int oy = -event.range; oy <= event.range; oy++) {
|
||||
int targetIndex = referencedChunks.offsetOf(centreIndex, ox, oy);
|
||||
ChunkSynconizer target = referencedChunks.get(targetIndex);
|
||||
lodBuilder.generateLodNodeFromChunk(lodDim, new ChunkWrapper(target.chunk), new LodBuilderConfig(generationMode));
|
||||
}
|
||||
}
|
||||
lambda.run();
|
||||
for (ChunkSynconizer sync : referencedChunks) {
|
||||
chunks.remove(sync.chunk.getPos().toLong());
|
||||
}
|
||||
System.out.println("Ended event: "+event);
|
||||
} catch (RuntimeException e) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public GridList<ChunkSynconizer> generateStructureStart(Runnable r, ChunkPos pos, int range) {
|
||||
int cx = pos.x;
|
||||
int cy = pos.z;
|
||||
GridList<ChunkSynconizer> chunks = new GridList<ChunkSynconizer>(range);
|
||||
|
||||
for (int oy = -range; oy <= range; oy++) {
|
||||
for (int ox = -range; ox <= range; ox++) {
|
||||
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(access),
|
||||
Steps.StructureStart);
|
||||
} finally {
|
||||
target.releaseOwnerLock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
r.run();
|
||||
return chunks;
|
||||
}
|
||||
|
||||
public GridList<ChunkSynconizer> generateStructureReference(Runnable r, ChunkPos pos, int range) {
|
||||
int prestepRange = range + StepStructureReference.RANGE;
|
||||
GridList<ChunkSynconizer> referencedChunks = generateStructureStart(r, pos, prestepRange);
|
||||
int centreIndex = referencedChunks.size() / 2;
|
||||
|
||||
for (int oy = -range; oy <= range; oy++) {
|
||||
for (int ox = -range; ox <= range; ox++) {
|
||||
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(referenceAccess, target.chunk);
|
||||
target.set(Steps.StructureReference);
|
||||
} finally {
|
||||
target.releaseOwnerLock();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
r.run();
|
||||
return referencedChunks;
|
||||
}
|
||||
|
||||
public GridList<ChunkSynconizer> generateBiomes(Runnable r, ChunkPos pos, int range) {
|
||||
int prestepRange = range + 1;
|
||||
GridList<ChunkSynconizer> referencedChunks = generateStructureReference(r, pos, prestepRange);
|
||||
int centreIndex = referencedChunks.size() / 2;
|
||||
|
||||
for (int oy = -range; oy <= range; oy++) {
|
||||
for (int ox = -range; ox <= range; ox++) {
|
||||
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(referenceAccess, target.chunk, executors), Steps.Biomes);
|
||||
} finally {
|
||||
target.releaseOwnerLock();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
r.run();
|
||||
return referencedChunks;
|
||||
}
|
||||
|
||||
public GridList<ChunkSynconizer> generateNoise(Runnable r, ChunkPos pos, int range) {
|
||||
int prestepRange = range + 1;
|
||||
GridList<ChunkSynconizer> referencedChunks = generateBiomes(r, pos, prestepRange);
|
||||
int centreIndex = referencedChunks.size() / 2;
|
||||
|
||||
for (int oy = -range; oy <= range; oy++) {
|
||||
for (int ox = -range; ox <= range; ox++) {
|
||||
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(referenceAccess, target.chunk, executors),
|
||||
Steps.Noise);
|
||||
} finally {
|
||||
target.releaseOwnerLock();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
r.run();
|
||||
return referencedChunks;
|
||||
}
|
||||
|
||||
public GridList<ChunkSynconizer> generateSurface(Runnable r, ChunkPos pos, int range) {
|
||||
int prestepRange = range + 1;
|
||||
GridList<ChunkSynconizer> referencedChunks = generateNoise(r, pos, prestepRange);
|
||||
int centreIndex = referencedChunks.size() / 2;
|
||||
|
||||
for (int oy = -range; oy <= range; oy++) {
|
||||
for (int ox = -range; ox <= range; ox++) {
|
||||
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(referenceAccess, target.chunk),
|
||||
Steps.Surface);
|
||||
} finally {
|
||||
target.releaseOwnerLock();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
r.run();
|
||||
return referencedChunks;
|
||||
}
|
||||
|
||||
|
||||
public GridList<ChunkSynconizer> generateCarvers(Runnable r, ChunkPos pos, int range) {
|
||||
int prestepRange = range + 1;
|
||||
GridList<ChunkSynconizer> referencedChunks = generateSurface(r, pos, prestepRange);
|
||||
int centreIndex = referencedChunks.size() / 2;
|
||||
|
||||
for (int oy = -range; oy <= range; oy++) {
|
||||
for (int ox = -range; ox <= range; ox++) {
|
||||
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(referenceAccess, target.chunk),
|
||||
Steps.Carvers);
|
||||
} finally {
|
||||
target.releaseOwnerLock();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
r.run();
|
||||
return referencedChunks;
|
||||
}
|
||||
|
||||
|
||||
public GridList<ChunkSynconizer> generateFeatures(Runnable r, ChunkPos pos, int range) {
|
||||
int prestepRange = range + 1;
|
||||
GridList<ChunkSynconizer> referencedChunks = generateCarvers(r, pos, prestepRange);
|
||||
int centreIndex = referencedChunks.size() / 2;
|
||||
|
||||
for (int oy = -range; oy <= range; oy++) {
|
||||
for (int ox = -range; ox <= range; ox++) {
|
||||
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(referenceAccess, target.chunk),
|
||||
Steps.Features);
|
||||
} finally {
|
||||
target.releaseOwnerLock();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
r.run();
|
||||
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();
|
||||
private static ChunkGenerator gen;
|
||||
private static boolean doGenerateFeatures = true;
|
||||
private static RegistryAccess registry;
|
||||
private static StructureFeatureManager structFeat;
|
||||
private static StructureManager struct;
|
||||
private static long seed;
|
||||
|
||||
public final static void onLevelLoad(ChunkGenerator generator, WorldGenSettings genSettings, RegistryAccess registryAccess,
|
||||
StructureFeatureManager structureFeature, StructureManager structures, long worldSeed) {
|
||||
gen = generator;
|
||||
doGenerateFeatures = genSettings.generateFeatures();
|
||||
registry = registryAccess;
|
||||
structFeat = structureFeature;
|
||||
struct = structures;
|
||||
seed = worldSeed;
|
||||
}
|
||||
|
||||
public final static ChunkAccess generate(ChunkAccess chunk) {
|
||||
if (doGenerateFeatures) {
|
||||
// Should be thread safe
|
||||
gen.createStructures(registry, structFeat, chunk, struct, seed);
|
||||
}
|
||||
((ProtoChunk) chunk).setStatus(STATUS);
|
||||
return chunk;
|
||||
}
|
||||
|
||||
static ChunkAccess load(ServerLevel level, ChunkAccess chunk) {
|
||||
((ProtoChunk) chunk).setStatus(STATUS);
|
||||
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();
|
||||
private static ChunkGenerator gen;
|
||||
private static StructureFeatureManager structFeat;
|
||||
private static ServerLevel level;
|
||||
|
||||
public final static void onLevelLoad(ServerLevel serverLevel, ChunkGenerator generator, StructureFeatureManager structureFeature) {
|
||||
gen = generator;
|
||||
structFeat = structureFeature;
|
||||
level = serverLevel;
|
||||
}
|
||||
|
||||
public static final void generate(List<ChunkAccess> chunkList, ChunkAccess chunk) {
|
||||
WorldGenRegion worldGenRegion = new WorldGenRegion(level, chunkList, STATUS, -1);
|
||||
// Note: Not certain StructureFeatureManager.forWorldGenRegion(...) is thread safe
|
||||
gen.createReferences(worldGenRegion, structFeat.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;
|
||||
private static ChunkGenerator gen;
|
||||
private static StructureFeatureManager structFeat;
|
||||
private static ServerLevel level;
|
||||
|
||||
public final static void onLevelLoad(ServerLevel serverLevel, ChunkGenerator generator, Registry<Biome> registry, StructureFeatureManager structureFeature) {
|
||||
biomeRegistry = registry;
|
||||
gen = generator;
|
||||
structFeat = structureFeature;
|
||||
level = serverLevel;
|
||||
}
|
||||
|
||||
public static final ChunkAccess generate(List<ChunkAccess> chunkList, ChunkAccess chunk, Executor worker) {
|
||||
WorldGenRegion worldGenRegion = new WorldGenRegion(level, chunkList, STATUS, -1);
|
||||
chunk = joinAsync(gen.fillFromNoise(worker, structFeat.forWorldGenRegion(worldGenRegion), chunk));
|
||||
((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();
|
||||
private static ChunkGenerator gen;
|
||||
private static StructureFeatureManager structFeat;
|
||||
private static ServerLevel level;
|
||||
|
||||
public final static void onLevelLoad(ServerLevel serverLevel, ChunkGenerator generator, StructureFeatureManager structureFeature) {
|
||||
gen = generator;
|
||||
structFeat = structureFeature;
|
||||
level = serverLevel;
|
||||
}
|
||||
|
||||
public static final ChunkAccess generate(List<ChunkAccess> chunkList, ChunkAccess chunk, Executor worker) {
|
||||
WorldGenRegion worldGenRegion = new WorldGenRegion(level, chunkList, STATUS, 0);
|
||||
chunk = joinAsync(gen.fillFromNoise(worker, structFeat.forWorldGenRegion(worldGenRegion), chunk));
|
||||
((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();
|
||||
private static ChunkGenerator gen;
|
||||
private static StructureFeatureManager structFeat;
|
||||
private static ServerLevel level;
|
||||
|
||||
public final static void onLevelLoad(ServerLevel serverLevel, ChunkGenerator generator, StructureFeatureManager structureFeature) {
|
||||
gen = generator;
|
||||
structFeat = structureFeature;
|
||||
level = serverLevel;
|
||||
}
|
||||
|
||||
public static final ChunkAccess generate(List<ChunkAccess> chunkList, ChunkAccess chunk) {
|
||||
WorldGenRegion worldGenRegion = new WorldGenRegion(level, chunkList, STATUS, 0);
|
||||
gen.buildSurfaceAndBedrock(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();
|
||||
private static ChunkGenerator gen;
|
||||
private static StructureFeatureManager structFeat;
|
||||
private static ServerLevel level;
|
||||
private static long seed;
|
||||
private static BiomeManager biomes;
|
||||
|
||||
public final static void onLevelLoad(ServerLevel serverLevel, ChunkGenerator generator, StructureFeatureManager structureFeature,
|
||||
long worldSeed, BiomeManager biomeManger) {
|
||||
gen = generator;
|
||||
structFeat = structureFeature;
|
||||
level = serverLevel;
|
||||
seed = worldSeed;
|
||||
biomes = biomeManger;
|
||||
}
|
||||
|
||||
|
||||
public static final ChunkAccess generate(List<ChunkAccess> chunkList, ChunkAccess chunk) {
|
||||
gen.applyCarvers(seed, biomes, 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(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();
|
||||
private static ChunkGenerator gen;
|
||||
private static StructureFeatureManager structFeat;
|
||||
private static ServerLevel level;
|
||||
private static LevelLightEngine lights;
|
||||
|
||||
public final static void onLevelLoad(ServerLevel serverLevel, ChunkGenerator generator, StructureFeatureManager structureFeature,
|
||||
LevelLightEngine lightEngine) {
|
||||
gen = generator;
|
||||
structFeat = structureFeature;
|
||||
level = serverLevel;
|
||||
lights = lightEngine;
|
||||
}
|
||||
|
||||
private static ReentrantLock testLock = new ReentrantLock();
|
||||
public static final ChunkAccess generate(List<ChunkAccess> chunkList, ChunkAccess chunk) {
|
||||
ProtoChunk protoChunk = (ProtoChunk) chunk;
|
||||
if (chunk.getStatus() == STATUS) return chunk;
|
||||
testLock.lock();
|
||||
try {
|
||||
if (chunk.getStatus() != STATUS) {
|
||||
|
||||
protoChunk.setLightEngine(lights);
|
||||
|
||||
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);
|
||||
|
||||
gen.applyBiomeDecoration(worldGenRegion, structFeat.forWorldGenRegion(worldGenRegion));
|
||||
//Blender.generateBorderTicks(worldGenRegion, chunk);
|
||||
|
||||
protoChunk.setStatus(STATUS);
|
||||
}
|
||||
} finally {
|
||||
testLock.unlock();
|
||||
}
|
||||
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 joinAsync(lightEngine.lightChunk(chunk, chunk.isLightCorrect()));
|
||||
}
|
||||
|
||||
public static final ChunkAccess load(ChunkAccess chunk) {
|
||||
((ProtoChunk) chunk).setStatus(STATUS);
|
||||
return joinAsync(lightEngine.lightChunk(chunk, chunk.isLightCorrect()));
|
||||
}
|
||||
}
|
||||
|
||||
// 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); } }
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user